static int init_http(void) { if(!SERVER_PORT_RAW) return 0; server_raw = HTTPServerCreate((HTTPListener)listener, blog); if(!server_raw) { alogf("HTTP server could not be initialized\n"); return -1; } int rc = HTTPServerListen(server_raw, SERVER_ADDRESS, SERVER_PORT_RAW); if(rc < 0) { alogf("HTTP server could not be started: %s\n", sln_strerror(rc)); return -1; } strarg_t const port = SERVER_PORT_RAW; alogf("StrongLink server running at http://localhost:%s/\n", port); return 0; }
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); }