#include #include static void angel_call_cb(liAngelConnection *acon, const gchar *mod, gsize mod_len, const gchar *action, gsize action_len, gint32 id, GString *data) { liServer *srv = acon->data; liPlugin *p; const liPluginAngel *acb; UNUSED(action_len); UNUSED(mod_len); if (NULL == (p = g_hash_table_lookup(srv->plugins, mod))) goto not_found; if (NULL == p->angelcbs) goto not_found; for (acb = p->angelcbs; acb->name; acb++) { if (0 == strcmp(acb->name, action)) break; } if (!acb->name) goto not_found; acb->angel_cb(srv, p, id, data); return; not_found: ERROR(srv, "received message for %s:%s, couldn't find receiver", mod, action); if (-1 != id) li_angel_send_result(acon, id, g_string_new_len(CONST_STR_LEN("receiver not found")), NULL, NULL, NULL); } static void angel_close_cb(liAngelConnection *acon, GError *err) { liServer *srv = acon->data; ERROR(srv, "li_fatal: angel connection close: %s", err ? err->message : g_strerror(errno)); if (err) g_error_free(err); abort(); } void li_angel_setup(liServer *srv) { srv->acon = li_angel_connection_new(&srv->main_worker->loop, 0, srv, angel_call_cb, angel_close_cb); srv->dest_state = LI_SERVER_SUSPENDED; } typedef struct angel_listen_cb_ctx angel_listen_cb_ctx; struct angel_listen_cb_ctx { liServer *srv; liAngelListenCB cb; gpointer data; }; static void li_angel_listen_cb(gpointer pctx, gboolean timeout, GString *error, GString *data, GArray *fds) { angel_listen_cb_ctx ctx = * (angel_listen_cb_ctx*) pctx; liServer *srv = ctx.srv; guint i; UNUSED(data); g_slice_free(angel_listen_cb_ctx, pctx); if (timeout) { ERROR(srv, "listen failed: %s", "time out"); return; } if (error->len > 0) { ERROR(srv, "listen failed: %s", error->str); /* TODO: exit? */ return; } if (fds && fds->len > 0) { for (i = 0; i < fds->len; i++) { int fd = g_array_index(fds, int, i); /* DEBUG(srv, "listening on fd %i", fd); */ if (ctx.cb) { ctx.cb(srv, fd, ctx.data); } else { li_server_listen(srv, fd); } } g_array_set_size(fds, 0); } else { ERROR(srv, "listen failed: %s", "received no filedescriptors"); } } /* listen to a socket */ void li_angel_listen(liServer *srv, GString *str, liAngelListenCB cb, gpointer data) { if (srv->acon) { liAngelCall *acall = li_angel_call_new(&srv->main_worker->loop, li_angel_listen_cb, 20.0); angel_listen_cb_ctx *ctx = g_slice_new0(angel_listen_cb_ctx); GError *err = NULL; ctx->srv = srv; ctx->cb = cb; ctx->data = data; acall->context = ctx; if (!li_angel_send_call(srv->acon, CONST_STR_LEN("core"), CONST_STR_LEN("listen"), acall, g_string_new_len(GSTR_LEN(str)), &err)) { ERROR(srv, "couldn't send call: %s", err->message); g_error_free(err); } } else { int fd = li_angel_fake_listen(srv, str); if (-1 == fd) { ERROR(srv, "listen('%s') failed", str->str); /* TODO: exit? */ } else { if (cb) { cb(srv, fd, data); } else { li_server_listen(srv, fd); } } } } /* send log messages while startup to angel */ void li_angel_log(liServer *srv, GString *str) { li_angel_fake_log(srv, str); } typedef struct angel_log_cb_ctx angel_log_cb_ctx; struct angel_log_cb_ctx { liServer *srv; liAngelLogOpen cb; gpointer data; GString *logname; }; static void li_angel_log_open_cb(gpointer pctx, gboolean timeout, GString *error, GString *data, GArray *fds) { angel_log_cb_ctx ctx = * (angel_log_cb_ctx*) pctx; liServer *srv = ctx.srv; UNUSED(data); g_slice_free(angel_log_cb_ctx, pctx); if (timeout) { ERROR(srv, "Couldn't open log file '%s': timeout", ctx.logname->str); goto failed; } if (error->len > 0) { ERROR(srv, "Couldn't open log file '%s': %s", ctx.logname->str, error->str); goto failed; } if (NULL == fds || fds->len != 1) { ERROR(srv, "Couldn't open log file '%s': no or too many filedescriptors (%i)", ctx.logname->str, (int) (NULL == fds ? 0 : fds->len)); goto failed; } ctx.cb(srv, g_array_index(fds, int, 0), ctx.data); g_array_set_size(fds, 0); goto cleanup; failed: ctx.cb(srv, -1, ctx.data); cleanup: g_string_free(ctx.logname, TRUE); } void li_angel_log_open_file(liServer *srv, liEventLoop *loop, GString *filename, liAngelLogOpen cb, gpointer data) { if (srv->acon) { liAngelCall *acall = li_angel_call_new(loop, li_angel_log_open_cb, 10.0); angel_log_cb_ctx *ctx = g_slice_new0(angel_log_cb_ctx); GError *err = NULL; ctx->srv = srv; ctx->cb = cb; ctx->data = data; ctx->logname = g_string_new_len(GSTR_LEN(filename)); acall->context = ctx; if (!li_angel_send_call(srv->acon, CONST_STR_LEN("core"), CONST_STR_LEN("log-open-file"), acall, g_string_new_len(GSTR_LEN(filename)), &err)) { ERROR(srv, "couldn't send call: %s", err->message); g_error_free(err); } } else { int fd = li_angel_fake_log_open_file(srv, filename); cb(srv, fd, data); } }