#include #include #include #include "event2/event.h" #include "event2/buffer.h" #include "event2/http.h" #include "http_healthcheck.h" #include struct http_status_ctx { pthread_t pthread; struct event_base *base; struct event *ev; struct evhttp *http; unsigned int enable; unsigned int port; char addr[PATH_MAX]; char path[PATH_MAX]; uint64_t is_error; } g_ctx = {0}; static void http_callback(struct evhttp_request *req, void *arg) { evhttp_send_reply(req, HTTP_OK, "", NULL); } static void gc_callback(evutil_socket_t fd, short what, void *arg) { // do nothing // add gc_callback to avoid event_base_dispatch blocking, handle event_base_loopbreak inmediately } static void *http_healthcheck_thread(void *arg) { struct timeval gc_delay = {0, 500 * 1000}; // Microseconds, we set 500 miliseconds here. printf("[http_healthcheck_thread]: running (listen: %s:%d path: %s)\n", g_ctx.addr, g_ctx.port, g_ctx.path); g_ctx.base = event_base_new(); if (g_ctx.base == NULL) { printf("[http_healthcheck_thread]: event_base_new failed\n"); goto end; } g_ctx.ev = event_new(g_ctx.base, -1, EV_PERSIST, gc_callback, NULL); if (g_ctx.ev == NULL) { printf("[http_healthcheck_thread]: event_new failed\n"); goto end; } if (evtimer_add(g_ctx.ev, &gc_delay) < 0) { printf("[http_healthcheck_thread]: evtimer_add failed\n"); goto end; } g_ctx.http = evhttp_new(g_ctx.base); if (evhttp_set_cb(g_ctx.http, g_ctx.path, http_callback, NULL) < 0) { printf("[http_healthcheck_thread]: evhttp_set_cb failed\n"); goto end; } if (evhttp_bind_socket(g_ctx.http, g_ctx.addr, g_ctx.port) < 0) { printf("[http_healthcheck_thread]: evhttp_bind_socket failed\n"); goto end; } event_base_dispatch(g_ctx.base); end: if (g_ctx.http) { evhttp_free(g_ctx.http); } if (g_ctx.ev) { event_free(g_ctx.ev); } if (g_ctx.base) { event_base_free(g_ctx.base); } printf("[http_healthcheck_thread]: exit\n"); return NULL; } void http_healthcheck_server_start(const char *profile) { MESA_load_profile_uint_def(profile, "http_healthcheck_server", "enable", &g_ctx.enable, 0); MESA_load_profile_uint_def(profile, "http_healthcheck_server", "port", &g_ctx.port, 8080); MESA_load_profile_string_def(profile, "http_healthcheck_server", "addr", g_ctx.addr, sizeof(g_ctx.addr), "127.0.0.1"); MESA_load_profile_string_def(profile, "http_healthcheck_server", "path", g_ctx.path, sizeof(g_ctx.path), "/status"); if (!g_ctx.enable) { return; } pthread_create(&g_ctx.pthread, NULL, http_healthcheck_thread, (void *)&g_ctx); } void http_healthcheck_server_stop() { if (g_ctx.enable) { event_base_loopbreak(g_ctx.base); pthread_join(g_ctx.pthread, NULL); } }