#include #include #include #include #include #include #include #include #include #include #include #include struct http_serv_main { struct event_base * ev_base; struct evhttp * ev_http; pthread_t ev_dispatch_tid; }; /* config example: * [:0] * name = olp0 * type = niagara_3296 * serial_number = 12345678abcdefgh * * [olp_channel:0] * device = olp0 * state = 3 * watchdog = 1 * watchdog_kick_time_in_ms = 300 * watchdog_timeout_in_ms = 600 */ /* liveness probe callback */ static void http_serv_probe_cb(struct evhttp_request * req, void * arg) { struct evbuffer * evb = evbuffer_new(); if (!evb) { MR_ERROR("failed to create response buffer"); return; } evbuffer_add_printf(evb, "Probe successfully, MRZCPD is running."); evhttp_send_reply(req, HTTP_OK, "OK", evb); evbuffer_free(evb); } /* event_base dispatch thread */ static void * http_serv_dispatch(void * arg) { struct event_base * base = (struct event_base *)arg; event_base_dispatch(base); return NULL; } int http_serv_deinit(struct sc_main * sc_main) { struct http_serv_main * ht_server_main = sc_main->ht_server_main; assert(ht_server_main != NULL); /* stop event_base dispatch thread */ event_base_loopexit(ht_server_main->ev_base, NULL); pthread_join(ht_server_main->ev_dispatch_tid, NULL); /* release all ctx */ evhttp_free(ht_server_main->ev_http); event_base_free(ht_server_main->ev_base); /* free http_serv_main */ FREE(ht_server_main); return 0; } int http_serv_init(struct sc_main * sc_main) { struct http_serv_main * http_server_main = ZMALLOC(sizeof(struct http_serv_main)); MR_VERIFY_MALLOC(http_server_main); struct event_config * cfg = event_config_new(); struct event_base * base = event_base_new_with_config(cfg); if (!base) { MR_ERROR("Couldn't create an event_base."); goto errout; } event_config_free(cfg); cfg = NULL; /* Create a new evhttp object to socket requests. */ struct evhttp * http = evhttp_new(base); if (!http) { MR_ERROR("couldn't create evhttp. Exiting.\n"); goto errout; } /* The /dump URI will dump all requests to stdout and say 200 ok. */ evhttp_set_cb(http, "/probe", http_serv_probe_cb, (void *)http_server_main); /* Load the listen address and port */ char str_listen_addr[INET6_ADDRSTRLEN] = {}; MESA_load_profile_string_def(sc_main->local_cfgfile, "http_server", "listen_addr", str_listen_addr, sizeof(str_listen_addr), "::"); unsigned int listen_port = 9086; MESA_load_profile_uint_def(sc_main->local_cfgfile, "http_server", "listen_port", &listen_port, 9086); struct evhttp_bound_socket * socket = evhttp_bind_socket_with_handle(http, str_listen_addr, listen_port); if (!socket) { MR_ERROR("couldn't bind to %s:%d.", str_listen_addr, listen_port); goto errout; } /* create a thread to do the event_base dispatch */ pthread_t tid; int ret = pthread_create(&tid, NULL, http_serv_dispatch, base); if (ret != 0) { MR_ERROR("failed to create thread for event_base dispatch: %s", strerror(ret)); goto errout; } /* save the event_base, ev_http handles to http_serv_main */ http_server_main->ev_base = base; http_server_main->ev_http = http; http_server_main->ev_dispatch_tid = tid; sc_main->ht_server_main = http_server_main; MR_INFO("HTTP Server is listening on %s:%u", str_listen_addr, listen_port); return 0; errout: return -1; }