int plugin_io_init(plugin_t *p) { if (!is_io_plugin(p)) return 0; _d("Initializing plugin %s for I/O", basename(p->name)); if (uev_io_init(ctx, &p->watcher, generic_io_cb, p, p->io.fd, p->io.flags)) { _e("Failed setting up I/O plugin %s", basename(p->name)); return 1; } return 0; }
/* Generic libev I/O callback, looks up correct plugin and calls its callback */ static void generic_io_cb(int fd, int events) { plugin_t *p, *tmp; /* Find matching plugin, pick first matching fd */ PLUGIN_ITERATOR(p, tmp) { if (is_io_plugin(p) && p->io.fd == fd) { _d("Calling I/O %s from runloop...", basename(p->name)); p->io.cb(p->io.arg, fd, events); break; } } }
/* Setup any I/O callbacks for plugins that use them */ static void init_plugins(void) { int i = 0; plugin_t *p, *tmp; PLUGIN_ITERATOR(p, tmp) { if (is_io_plugin(p)) { _d("Initializing plugin %s for I/O", basename(p->name)); fds[i].revents = 0; fds[i].events = p->io.flags; fds[i++].fd = p->io.fd; } } }
/* Generic libev I/O callback, looks up correct plugin and calls its callback */ static void generic_io_cb(uev_t *w, void *arg, int events) { plugin_t *p = (plugin_t *)arg; if (is_io_plugin(p) && p->io.fd == w->fd) { /* Stop watcher, callback may close descriptor on us ... */ uev_io_stop(w); _d("Calling I/O %s from runloop...", basename(p->name)); p->io.cb(p->io.arg, w->fd, events); /* Update fd, may be changed by plugin callback, e.g., if FIFO */ uev_io_set(w, p->io.fd, p->io.flags); } }
/* Generic libev I/O callback, looks up correct plugin and calls its callback */ static void generic_io_cb(struct pollfd *io) { plugin_t *p, *tmp; /* Find matching plugin, pick first matching fd */ PLUGIN_ITERATOR(p, tmp) { if (is_io_plugin(p) && p->io.fd == io->fd) { _d("Calling I/O %s from runloop...", basename(p->name)); p->io.cb(p->io.arg, io->fd, io->events); /* Update fd, may be changed by plugin callback, e.g., if FIFO */ io->fd = p->io.fd; io->events = p->io.flags; io->revents = 0; break; } } }
int plugin_register(plugin_t *plugin) { int i, inuse = 0; if (!plugin) { errno = EINVAL; return 1; } if (!plugin->name) { Dl_info info; if (!dladdr(plugin, &info) || !info.dli_fname) plugin->name = "unknown"; else plugin->name = (char *)info.dli_fname; } /* Already registered? */ if (plugin_find(plugin->name)) { _d("... %s already loaded.", plugin->name); return 0; } check_plugin_depends(plugin); if (is_io_plugin(plugin)) { if (num_fds + 1 >= MAX_NUM_FDS) { num_fds = MAX_NUM_SVC; errno = ENOMEM; return 1; } num_fds++; inuse++; } if (plugin->svc.cb) { svc_t *svc = svc_find(plugin->name); if (svc) { inuse++; svc->cb = plugin->svc.cb; svc->dynamic = plugin->svc.dynamic; svc->dynamic_stop = plugin->svc.dynamic_stop; } } for (i = 0; i < HOOK_MAX_NUM; i++) { if (plugin->hook[i].cb) inuse++; } if (!inuse) { _d("No service \"%s\" loaded, and no I/O or finit hooks, skipping plugin.", basename(plugin->name)); return 1; } TAILQ_INSERT_TAIL(&plugins, plugin, link); return 0; }