static void term(void *const unused) { fprintf(stderr, "\nStopping StrongLink server...\n"); uv_ref((uv_handle_t *)sigint); uv_signal_stop(sigint); async_close((uv_handle_t *)sigint); SLNRepoPullsStop(repo); HTTPServerClose(server_raw); HTTPServerClose(server_tls); uv_ref((uv_handle_t *)sigpipe); uv_signal_stop(sigpipe); uv_close((uv_handle_t *)sigpipe, NULL); }
void HTTPServerFree(HTTPServerRef *const serverptr) { HTTPServerRef server = *serverptr; if(!server) return; HTTPServerClose(server); server->listener = NULL; server->context = NULL; assert_zeroed(server, 1); FREE(serverptr); server = NULL; }
static void init(void *const unused) { int rc = async_random((byte_t *)&SLNSeed, sizeof(SLNSeed)); if(rc < 0) { alogf("Random seed error\n"); return; } uv_signal_init(async_loop, sigpipe); uv_signal_start(sigpipe, ignore, SIGPIPE); uv_unref((uv_handle_t *)sigpipe); str_t *tmp = strdup(path); strarg_t const reponame = basename(tmp); // TODO rc = SLNRepoCreate(path, reponame, &repo); FREE(&tmp); if(rc < 0) { alogf("Repository could not be opened: %s\n", sln_strerror(rc)); return; } blog = BlogCreate(repo); if(!blog) { alogf("Blog server could not be initialized\n"); return; } rc = RSSServerCreate(repo, &rss); if(rc < 0) { alogf("RSS server error: %s\n", sln_strerror(rc)); return; } if(init_http() < 0 || init_https() < 0) { HTTPServerClose(server_raw); HTTPServerClose(server_tls); return; } // SLNRepoPullsStart(repo); uv_signal_init(async_loop, sigint); uv_signal_start(sigint, stop, SIGINT); uv_unref((uv_handle_t *)sigint); }
static void term(void *const unused) { fprintf(stderr, "\n"); alogf("Stopping StrongLink server...\n"); uv_ref((uv_handle_t *)sigint); uv_signal_stop(sigint); async_close((uv_handle_t *)sigint); SLNRepoPullsStop(repo); HTTPServerClose(server_raw); HTTPServerClose(server_tls); async_pool_enter(NULL); fflush(NULL); // Everything. async_pool_leave(NULL); uv_ref((uv_handle_t *)sigpipe); uv_signal_stop(sigpipe); uv_close((uv_handle_t *)sigpipe, NULL); }
int HTTPServerListen(HTTPServerRef const server, strarg_t const address, strarg_t const port) { if(!server) return 0; assertf(!server->socket->data, "HTTPServer already listening"); int rc; rc = uv_tcp_init(async_loop, server->socket); if(rc < 0) return rc; server->socket->data = server; struct addrinfo const hints = { .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_NUMERICSERV | AI_PASSIVE, .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = 0, // ??? }; struct addrinfo *info; rc = async_getaddrinfo(address, port, &hints, &info); if(rc < 0) { HTTPServerClose(server); return rc; } int bound = 0; rc = 0; for(struct addrinfo *each = info; each; each = each->ai_next) { rc = uv_tcp_bind(server->socket, each->ai_addr, 0); if(rc >= 0) bound++; } uv_freeaddrinfo(info); if(!bound) { HTTPServerClose(server); if(rc < 0) return rc; return UV_EADDRNOTAVAIL; } rc = uv_listen((uv_stream_t *)server->socket, 511, connection_cb); if(rc < 0) { HTTPServerClose(server); return rc; } return 0; } int HTTPServerListenSecure(HTTPServerRef const server, strarg_t const address, strarg_t const port, struct tls **const tlsptr) { if(!server) return 0; int rc = HTTPServerListen(server, address, port); if(rc < 0) return rc; server->secure = *tlsptr; *tlsptr = NULL; return 0; } void HTTPServerClose(HTTPServerRef const server) { if(!server) return; if(!server->socket->data) return; if(server->secure) tls_close(server->secure); tls_free(server->secure); server->secure = NULL; async_close((uv_handle_t *)server->socket); } static void connection(uv_stream_t *const socket) { HTTPServerRef const server = socket->data; HTTPConnectionRef conn; int rc = HTTPConnectionCreateIncomingSecure(socket, server->secure, 0, &conn); if(rc < 0) { fprintf(stderr, "HTTP server connection error %s\n", uv_strerror(rc)); return; } assert(conn); for(;;) { server->listener(server->context, server, conn); rc = HTTPConnectionDrainMessage(conn); if(rc < 0) break; } HTTPConnectionFree(&conn); }