int main(int argc, char * argv[]) { signal(SIGPIPE, SIG_IGN); loop = uv_default_loop(); int result; http_server_init(&srv); srv.sock_listen_data = NULL; // should be null by default http_server_handler_init(&handler); handler.on_message_complete = &on_message_complete; result = http_server_setopt(&srv, HTTP_SERVER_OPT_HANDLER, &handler); result = http_server_setopt(&srv, HTTP_SERVER_OPT_HANDLER_DATA, &srv); // Set options //result = http_server_setopt(&srv, HTTP_SERVER_OPT_OPEN_SOCKET_DATA, NULL); //result = http_server_setopt(&srv, HTTP_SERVER_OPT_OPEN_SOCKET_FUNCTION, &_opensocket_function); result = http_server_setopt(&srv, HTTP_SERVER_OPT_SOCKET_DATA, NULL); result = http_server_setopt(&srv, HTTP_SERVER_OPT_SOCKET_FUNCTION, &_socket_function); http_server_start(&srv); result = uv_run(loop, UV_RUN_DEFAULT); http_server_free(&srv); return result; }
void http_server_unlink_ ( http_server_t * ( * self_p ), // Reference to object reference char * file, // Source file for call size_t line // Line number for call ) { #if defined (DEBUG) || defined (BASE_HISTORY) || defined (BASE_HISTORY_HTTP_SERVER) int history_last; #endif http_server_t * self = *self_p; // Dereferenced Reference to object reference if (self) { if (self->links == 0) { icl_console_print ("Missing link on http_server object"); http_server_show_ (self, ICL_CALLBACK_DUMP, stderr, file, line); } assert (self->links > 0); #if defined (DEBUG) || defined (BASE_HISTORY) || defined (BASE_HISTORY_HTTP_SERVER) // Track possession operation in history. Pre-empt value of links // after operation; otherwise race condition can result in writing // to freed memory. history_last = icl_atomic_inc32 ((volatile qbyte *) &self->history_last) + 1; self->history_file [history_last % HTTP_SERVER_HISTORY_LENGTH] = file; self->history_line [history_last % HTTP_SERVER_HISTORY_LENGTH] = line; self->history_type [history_last % HTTP_SERVER_HISTORY_LENGTH] = "unlink"; self->history_links [history_last % HTTP_SERVER_HISTORY_LENGTH] = self->links - 1; #endif if (icl_atomic_dec32 ((volatile qbyte *) &self->links) == 0) { if (self->zombie) http_server_free (self); else { // JS: Have to make the object look like it was called from the // application. _destroy will decrement links again. icl_atomic_inc32 ((volatile qbyte *) &self->links); http_server_destroy_ (self_p, file, line); } } else *self_p = NULL; } }
struct http_server * http_server_new(struct event_base *base, int port) { struct http_server *hs = NULL; hs = (struct http_server *)malloc(sizeof(struct http_server)); if (!hs) { printf("Could not create http server\n"); return NULL; } memset(hs, 0, sizeof(struct http_server)); hs->base = base; struct sockaddr_in sin; sin.sin_family=AF_INET; sin.sin_port=htons(port); sin.sin_addr.s_addr=INADDR_ANY; /* init connection listener */ hs->listener = evconnlistener_new_bind(base, http_connect_cb, hs, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_EXEC, 100, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)); if (!hs->listener) { printf("Could not bind a listener to port %d\n", port); goto failed; } evconnlistener_set_error_cb(hs->listener, http_connect_error_cb); /* init connection head node, for convinents */ hs->hc = http_connection_new(hs, -1, (struct sockaddr *)&sin); if (!hs->hc) { printf("Could not create a initial connection for http server\n"); goto failed; } /* init uris */ http_uris_init(hs); return hs; failed: http_server_free(hs); return NULL; }
int http_server_destroy_ ( http_server_t * ( * self_p ), // Reference to object reference char * file, // Source file size_t line // Line number ) { http_server_t * self = *self_p; // Dereferenced Reference to object reference int rc = 0; // Return code if (self) { if (icl_atomic_cas32 (&self->zombie, TRUE, FALSE) == FALSE) rc = http_server_annihilate_ (self_p, file, line); else if (icl_atomic_dec32 ((volatile qbyte *) &self->links) == 0) http_server_free (self); *self_p = NULL; } return (rc); }
void http_thread(void *asdf) { sigset_t sigs_to_block; struct http_config_t *lc; struct timeval http_timer_tv; http_timer_tv.tv_sec = 0; http_timer_tv.tv_usec = 200000; pthreads_profiling_reset("http"); sigemptyset(&sigs_to_block); sigaddset(&sigs_to_block, SIGALRM); sigaddset(&sigs_to_block, SIGINT); sigaddset(&sigs_to_block, SIGTERM); sigaddset(&sigs_to_block, SIGQUIT); sigaddset(&sigs_to_block, SIGHUP); sigaddset(&sigs_to_block, SIGURG); sigaddset(&sigs_to_block, SIGPIPE); sigaddset(&sigs_to_block, SIGUSR1); sigaddset(&sigs_to_block, SIGUSR2); pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL); /* start the http thread, which will start server threads */ hlog(LOG_INFO, "HTTP thread starting..."); /* we allocate a worker structure to be used within the http thread * for parsing incoming packets and passing them on to the dupecheck * thread. */ http_worker = worker_alloc(); http_worker->id = 80; /* we also need a client structure to be used with incoming * HTTP position uploads */ http_pseudoclient = pseudoclient_setup(80); http_reconfiguring = 1; while (!http_shutting_down) { if (http_reconfiguring) { http_reconfiguring = 0; // shut down existing instance http_server_free(); // do init #if 1 libbase = event_base_new(); // libevent 2.x #else libbase = event_init(); // libevent 1.x #endif // timer for the whole libevent, to catch shutdown signal ev_timer = event_new(libbase, -1, EV_TIMEOUT, http_timer, NULL); event_add(ev_timer, &http_timer_tv); for (lc = http_config; (lc); lc = lc->next) { hlog(LOG_INFO, "Binding HTTP %s socket %s:%d", lc->upload_port ? "upload" : "status", lc->host, lc->port); struct evhttp *srvr; struct evhttp_bound_socket *handle; if (lc->upload_port) { if (!srvr_upload) { srvr_upload = evhttp_new(libbase); http_srvr_defaults(srvr_upload); evhttp_set_allowed_methods(srvr_upload, EVHTTP_REQ_POST); /* uploads are POSTs, after all */ evhttp_set_gencb(srvr_upload, http_router, (void *)2); } srvr = srvr_upload; } else { if (!srvr_status) { srvr_status = evhttp_new(libbase); http_srvr_defaults(srvr_status); evhttp_set_gencb(srvr_status, http_router, (void *)1); } srvr = srvr_status; } handle = evhttp_bind_socket_with_handle(srvr, lc->host, lc->port); if (!handle) { hlog(LOG_ERR, "Failed to bind HTTP socket %s:%d: %s", lc->host, lc->port, strerror(errno)); // TODO: should exit? } } hlog(LOG_INFO, "HTTP thread ready."); } event_base_dispatch(libbase); } hlog(LOG_DEBUG, "HTTP thread shutting down..."); http_server_free(); /* free up the pseudo-client */ client_free(http_pseudoclient); http_pseudoclient = NULL; /* free up the pseudo-worker structure */ worker_free_buffers(http_worker); hfree(http_worker); http_worker = NULL; }