parent
175f7c8f55
commit
9166d3ab80
|
@ -59,9 +59,8 @@ static void usage(const char *prog)
|
|||
fprintf(stderr, "Usage: %s [option]\n"
|
||||
" -h docroot # Document root, default is .\n"
|
||||
" -i index_page # Index page, default is index.html\n"
|
||||
" -a addr # Default addr is localhost\n"
|
||||
" -p port # Default port is 8080\n"
|
||||
" -s # SSl on\n"
|
||||
" -a addr # address to listen\n"
|
||||
" -s addr # address to listen with ssl\n"
|
||||
" -P # plugin path\n"
|
||||
" -w # worker process number, default is equal to available CPUs\n"
|
||||
" -v # verbose\n", prog);
|
||||
|
@ -75,16 +74,17 @@ int main(int argc, char **argv)
|
|||
struct uh_server *srv = NULL;
|
||||
const char *plugin_path = NULL;
|
||||
bool verbose = false;
|
||||
bool ssl = false;
|
||||
const char *docroot = ".";
|
||||
const char *index_page = "index.html";
|
||||
const char *addr = "localhost";
|
||||
pid_t workers[MAX_WORKER] = {};
|
||||
int nworker = get_nprocs();
|
||||
int port = 8080;
|
||||
int opt, i;
|
||||
|
||||
while ((opt = getopt(argc, argv, "h:i:a:p:sfP:w:v")) != -1) {
|
||||
srv = uh_server_new(loop);
|
||||
if (!srv)
|
||||
return -1;
|
||||
|
||||
while ((opt = getopt(argc, argv, "h:i:a:s:P:w:v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
docroot = optarg;
|
||||
|
@ -93,13 +93,12 @@ int main(int argc, char **argv)
|
|||
index_page = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
addr = optarg;
|
||||
if (srv->listen(srv, optarg, false) < 1)
|
||||
goto err;
|
||||
break;
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
ssl = true;
|
||||
case 's':
|
||||
if (srv->listen(srv, optarg, true) < 1)
|
||||
goto err;
|
||||
break;
|
||||
case 'P':
|
||||
plugin_path = optarg;
|
||||
|
@ -124,13 +123,8 @@ int main(int argc, char **argv)
|
|||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
srv = uh_server_new(loop, addr, port);
|
||||
if (!srv)
|
||||
return -1;
|
||||
|
||||
#if UHTTPD_SSL_SUPPORT
|
||||
if (ssl && srv->ssl_init(srv, "server-cert.pem", "server-key.pem") < 0)
|
||||
goto err;
|
||||
srv->ssl_init(srv, "cert.pem", "key.pem");
|
||||
#endif
|
||||
|
||||
srv->set_docroot(srv, docroot);
|
||||
|
|
|
@ -58,28 +58,37 @@ static void usage(const char *prog)
|
|||
fprintf(stderr, "Usage: %s [option]\n"
|
||||
" -h docroot # Document root, default is .\n"
|
||||
" -i index_page # Index page, default is index.html\n"
|
||||
" -a addr # Default addr is localhost\n"
|
||||
" -p port # Default port is 8080\n"
|
||||
" -s # SSl on\n"
|
||||
" -a addr # address to listen\n"
|
||||
" -s addr # address to listen with ssl\n"
|
||||
" -P # plugin path\n"
|
||||
" -w # worker process number, default is equal to available CPUs\n"
|
||||
" -v # verbose\n", prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void start_server(const char *addr, int port, const char *docroot, const char *index_page, const char *plugin, bool ssl)
|
||||
static void start_server(const char *addr, const char *addrs, const char *docroot, const char *index_page, const char *plugin, bool ssl)
|
||||
{
|
||||
struct ev_loop *loop = ev_loop_new(0);
|
||||
struct uh_server *srv = NULL;
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
srv = uh_server_new(loop, addr, port);
|
||||
srv = uh_server_new(loop);
|
||||
if (!srv)
|
||||
return;
|
||||
|
||||
if (addr) {
|
||||
if (srv->listen(srv, addrs, false) < 0)
|
||||
return;
|
||||
} else if (addrs) {
|
||||
if (srv->listen(srv, addrs, true) < 0)
|
||||
return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
#if UHTTPD_SSL_SUPPORT
|
||||
if (ssl && srv->ssl_init(srv, "server-cert.pem", "server-key.pem") < 0)
|
||||
if (ssl && srv->ssl_init(srv, "cert.pem", "key.pem") < 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
@ -105,13 +114,13 @@ int main(int argc, char **argv)
|
|||
bool ssl = false;
|
||||
const char *docroot = ".";
|
||||
const char *index_page = "index.html";
|
||||
const char *addr = "localhost";
|
||||
const char *addr = NULL;
|
||||
const char *addrs = NULL;
|
||||
pid_t workers[MAX_WORKER] = {};
|
||||
int nworker = get_nprocs();
|
||||
int port = 8080;
|
||||
int opt, i;
|
||||
|
||||
while ((opt = getopt(argc, argv, "h:i:a:p:sP:w:v")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "h:i:a:s:P:w:v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
docroot = optarg;
|
||||
|
@ -122,11 +131,8 @@ int main(int argc, char **argv)
|
|||
case 'a':
|
||||
addr = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
ssl = true;
|
||||
addrs = optarg;
|
||||
break;
|
||||
case 'P':
|
||||
plugin_path = optarg;
|
||||
|
@ -164,7 +170,7 @@ int main(int argc, char **argv)
|
|||
|
||||
if (pid == 0) {
|
||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||
start_server(addr, port, docroot, index_page, plugin_path, ssl);
|
||||
start_server(addr, addrs, docroot, index_page, plugin_path, ssl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,9 +48,8 @@ static void usage(const char *prog)
|
|||
fprintf(stderr, "Usage: %s [option]\n"
|
||||
" -h docroot # Document root, default is .\n"
|
||||
" -i index_page # Index page, default is index.html\n"
|
||||
" -a addr # Default addr is localhost\n"
|
||||
" -p port # Default port is 8080\n"
|
||||
" -s # SSl on\n"
|
||||
" -a addr # address to listen\n"
|
||||
" -s addr # address to listen with ssl\n"
|
||||
" -P # plugin path\n"
|
||||
" -v # verbose\n", prog);
|
||||
exit(1);
|
||||
|
@ -63,14 +62,15 @@ int main(int argc, char **argv)
|
|||
struct uh_server *srv = NULL;
|
||||
const char *plugin_path = NULL;
|
||||
bool verbose = false;
|
||||
bool ssl = false;
|
||||
const char *docroot = ".";
|
||||
const char *index_page = "index.html";
|
||||
const char *addr = "localhost";
|
||||
int port = 8080;
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "h:i:a:p:sP:v")) != -1) {
|
||||
srv = uh_server_new(loop);
|
||||
if (!srv)
|
||||
return -1;
|
||||
|
||||
while ((opt = getopt(argc, argv, "h:i:a:s:P:v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
docroot = optarg;
|
||||
|
@ -79,13 +79,12 @@ int main(int argc, char **argv)
|
|||
index_page = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
addr = optarg;
|
||||
if (srv->listen(srv, optarg, false) < 1)
|
||||
goto err;
|
||||
break;
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
ssl = true;
|
||||
case 's':
|
||||
if (srv->listen(srv, optarg, true) < 1)
|
||||
goto err;
|
||||
break;
|
||||
case 'P':
|
||||
plugin_path = optarg;
|
||||
|
@ -93,7 +92,7 @@ int main(int argc, char **argv)
|
|||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
default: /* '?' */
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
@ -105,13 +104,8 @@ int main(int argc, char **argv)
|
|||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
srv = uh_server_new(loop, addr, port);
|
||||
if (!srv)
|
||||
return -1;
|
||||
|
||||
#if UHTTPD_SSL_SUPPORT
|
||||
if (ssl && srv->ssl_init(srv, "server-cert.pem", "server-key.pem") < 0)
|
||||
goto err;
|
||||
srv->ssl_init(srv, "cert.pem", "key.pem");
|
||||
#endif
|
||||
|
||||
srv->set_docroot(srv, docroot);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
openssl req -x509 -newkey rsa:2048 -nodes -keyout server-key.pem -out server-cert.pem -subj "/C=CZ/O=Acme Inc./OU=ACME/CN=ACME-DEV-123"
|
||||
openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -subj "/C=CZ/O=Acme Inc./OU=ACME/CN=ACME-DEV-123"
|
||||
|
|
|
@ -794,8 +794,9 @@ static void conn_init_cb(struct uh_connection *conn)
|
|||
conn->close = conn_close;
|
||||
}
|
||||
|
||||
struct uh_connection_internal *uh_new_connection(struct uh_server_internal *srv, int sock, struct sockaddr *addr)
|
||||
struct uh_connection_internal *uh_new_connection(struct uh_listener *l, int sock, struct sockaddr *addr)
|
||||
{
|
||||
struct uh_server_internal *srv = l->srv;
|
||||
struct uh_connection_internal *conn;
|
||||
|
||||
conn = calloc(1, sizeof(struct uh_connection_internal));
|
||||
|
@ -822,7 +823,7 @@ struct uh_connection_internal *uh_new_connection(struct uh_server_internal *srv,
|
|||
ev_timer_start(srv->loop, &conn->timer);
|
||||
|
||||
#if UHTTPD_SSL_SUPPORT
|
||||
if (srv->ssl_ctx)
|
||||
if (l->ssl)
|
||||
conn->ssl = uh_ssl_new(srv->ssl_ctx, sock);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ struct uh_connection_internal {
|
|||
void (*handler)(struct uh_connection *conn, int event);
|
||||
};
|
||||
|
||||
struct uh_connection_internal *uh_new_connection(struct uh_server_internal *srv, int sock, struct sockaddr *addr);
|
||||
struct uh_connection_internal *uh_new_connection(struct uh_listener *l, int sock, struct sockaddr *addr);
|
||||
|
||||
void conn_free(struct uh_connection_internal *conn);
|
||||
|
||||
|
|
247
src/uhttpd.c
247
src/uhttpd.c
|
@ -42,15 +42,11 @@ static void uh_server_free(struct uh_server *srv)
|
|||
struct uh_server_internal *srvi = (struct uh_server_internal *)srv;
|
||||
struct uh_connection_internal *conn = srvi->conns;
|
||||
struct uh_path_handler *h = srvi->handlers;
|
||||
struct uh_listener *l = srvi->listeners;
|
||||
#ifdef HAVE_DLOPEN
|
||||
struct uh_plugin *p = srvi->plugins;
|
||||
#endif
|
||||
|
||||
ev_io_stop(srvi->loop, &srvi->ior);
|
||||
|
||||
if (srvi->sock > 0)
|
||||
close(srvi->sock);
|
||||
|
||||
if (srvi->docroot)
|
||||
free(srvi->docroot);
|
||||
|
||||
|
@ -69,6 +65,18 @@ static void uh_server_free(struct uh_server *srv)
|
|||
free(temp);
|
||||
}
|
||||
|
||||
while (l) {
|
||||
struct uh_listener *temp = l;
|
||||
|
||||
ev_io_stop(srvi->loop, &l->ior);
|
||||
|
||||
if (l->sock > 0)
|
||||
close(l->sock);
|
||||
|
||||
l = l->next;
|
||||
free(temp);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
while (p) {
|
||||
struct uh_plugin *temp = p;
|
||||
|
@ -85,7 +93,8 @@ static void uh_server_free(struct uh_server *srv)
|
|||
|
||||
static void uh_accept_cb(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
{
|
||||
struct uh_server_internal *srv = container_of(w, struct uh_server_internal, ior);
|
||||
struct uh_listener *l = container_of(w, struct uh_listener, ior);
|
||||
struct uh_server_internal *srv = l->srv;
|
||||
struct uh_connection_internal *conn;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
|
@ -97,7 +106,7 @@ static void uh_accept_cb(struct ev_loop *loop, struct ev_io *w, int revents)
|
|||
int port;
|
||||
int sock;
|
||||
|
||||
sock = accept4(srv->sock, (struct sockaddr *)&addr, &addr_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||
sock = accept4(l->sock, (struct sockaddr *)&addr, &addr_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||
if (sock < 0) {
|
||||
if (errno != EAGAIN)
|
||||
uh_log_err("accept: %s\n", strerror(errno));
|
||||
|
@ -109,7 +118,21 @@ static void uh_accept_cb(struct ev_loop *loop, struct ev_io *w, int revents)
|
|||
uh_log_debug("New Connection from: %s %d\n", addr_str, port);
|
||||
}
|
||||
|
||||
conn = uh_new_connection(srv, sock, &addr.sa);
|
||||
if (l->ssl) {
|
||||
#if UHTTPD_SSL_SUPPORT
|
||||
if (!srv->ssl_ctx) {
|
||||
uh_log_err("SSL not initialized\n");
|
||||
close(sock);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
close(sock);
|
||||
uh_log_err("SSL not enabled when build\n");
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
conn = uh_new_connection(l, sock, &addr.sa);
|
||||
if (!conn)
|
||||
return;
|
||||
|
||||
|
@ -123,7 +146,7 @@ static void uh_accept_cb(struct ev_loop *loop, struct ev_io *w, int revents)
|
|||
srv->conns = conn;
|
||||
}
|
||||
|
||||
struct uh_server *uh_server_new(struct ev_loop *loop, const char *host, int port)
|
||||
struct uh_server *uh_server_new(struct ev_loop *loop)
|
||||
{
|
||||
struct uh_server *srv;
|
||||
|
||||
|
@ -133,10 +156,7 @@ struct uh_server *uh_server_new(struct ev_loop *loop, const char *host, int port
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (uh_server_init(srv, loop, host, port) < 0) {
|
||||
free(srv);
|
||||
return NULL;
|
||||
}
|
||||
uh_server_init(srv, loop);
|
||||
|
||||
return srv;
|
||||
}
|
||||
|
@ -279,93 +299,155 @@ static struct ev_loop *uh_get_loop(struct uh_server *srv)
|
|||
return srvi->loop;
|
||||
}
|
||||
|
||||
int uh_server_init(struct uh_server *srv, struct ev_loop *loop, const char *host, int port)
|
||||
static int parse_address(const char *addr, char **host, char **port)
|
||||
{
|
||||
static char buf[256];
|
||||
char *s;
|
||||
int l;
|
||||
|
||||
strcpy(buf, addr);
|
||||
|
||||
*host = NULL;
|
||||
*port = buf;
|
||||
|
||||
s = strrchr(buf, ':');
|
||||
if (!s)
|
||||
return -1;
|
||||
|
||||
*host = buf;
|
||||
*port = s + 1;
|
||||
*s = 0;
|
||||
|
||||
if (*host && **host == '[') {
|
||||
l = strlen(*host);
|
||||
if (l >= 2) {
|
||||
(*host)[l - 1] = 0;
|
||||
(*host)++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*host)[0] == '\0')
|
||||
*host = "0";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uh_server_listen(struct uh_server *srv, const char *addr, bool ssl)
|
||||
{
|
||||
struct uh_server_internal *srvi = (struct uh_server_internal *)srv;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
} addr;
|
||||
struct uh_listener *l;
|
||||
char *host, *port;
|
||||
struct addrinfo *addrs = NULL, *p = NULL;
|
||||
static struct addrinfo hints = {
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_PASSIVE,
|
||||
};
|
||||
char addr_str[INET6_ADDRSTRLEN];
|
||||
socklen_t addrlen;
|
||||
int sock = -1;
|
||||
int bound = 0;
|
||||
int on = 1;
|
||||
int status;
|
||||
int sock;
|
||||
|
||||
if (!host || *host == '\0') {
|
||||
addr.sin.sin_family = AF_INET;
|
||||
addr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, host, &addr.sin.sin_addr) == 1) {
|
||||
addr.sa.sa_family = AF_INET;
|
||||
} else if (inet_pton(AF_INET6, host, &addr.sin6.sin6_addr) == 1) {
|
||||
addr.sa.sa_family = AF_INET6;
|
||||
} else {
|
||||
static struct addrinfo hints = {
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_PASSIVE
|
||||
};
|
||||
struct addrinfo *ais;
|
||||
int status;
|
||||
|
||||
status = getaddrinfo(host, NULL, &hints, &ais);
|
||||
if (status != 0) {
|
||||
uh_log_err("getaddrinfo(): %s\n", gai_strerror(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&addr, ais->ai_addr, ais->ai_addrlen);
|
||||
freeaddrinfo(ais);
|
||||
}
|
||||
|
||||
if (addr.sa.sa_family == AF_INET) {
|
||||
addr.sin.sin_port = ntohs(port);
|
||||
addrlen = sizeof(addr.sin);
|
||||
inet_ntop(AF_INET, &addr.sin.sin_addr, addr_str, sizeof(addr_str));
|
||||
} else {
|
||||
addr.sin6.sin6_port = ntohs(port);
|
||||
addrlen = sizeof(addr.sin6);
|
||||
inet_ntop(AF_INET6, &addr.sin6.sin6_addr, addr_str, sizeof(addr_str));
|
||||
}
|
||||
|
||||
sock = socket(addr.sa.sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||
if (sock < 0) {
|
||||
uh_log_err("socket: %s\n", strerror(errno));
|
||||
if (parse_address(addr, &host, &port) < 0) {
|
||||
uh_log_err("invalid address\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) < 0) {
|
||||
uh_log_err("setsockopt: %s\n", strerror(errno));
|
||||
goto err;
|
||||
status = getaddrinfo(host, port, &hints, &addrs);
|
||||
if (status != 0) {
|
||||
uh_log_err("getaddrinfo(): %s\n", gai_strerror(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int));
|
||||
/* try to bind a new socket to each found address */
|
||||
for (p = addrs; p; p = p->ai_next) {
|
||||
sock = socket(p->ai_family, p->ai_socktype | SOCK_NONBLOCK | SOCK_CLOEXEC, p->ai_protocol);
|
||||
if (sock < 0) {
|
||||
uh_log_err("socket: %s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bind(sock, &addr.sa, addrlen) < 0) {
|
||||
uh_log_err("bind: %s\n", strerror(errno));
|
||||
goto err;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) < 0) {
|
||||
uh_log_err("setsockopt: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* required to get parallel v4 + v6 working */
|
||||
if (p->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(int)) < 0) {
|
||||
uh_log_err("setsockopt: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int));
|
||||
|
||||
if (bind(sock, p->ai_addr, p->ai_addrlen) < 0) {
|
||||
uh_log_err("bind: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (listen(sock, SOMAXCONN) < 0) {
|
||||
uh_log_err("bind: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
l = calloc(1, sizeof(struct uh_listener));
|
||||
if (!l) {
|
||||
uh_log_err("calloc: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
l->sock = sock;
|
||||
l->ssl = ssl;
|
||||
l->srv = srvi;
|
||||
|
||||
ev_io_init(&l->ior, uh_accept_cb, sock, EV_READ);
|
||||
ev_io_start(srvi->loop, &l->ior);
|
||||
|
||||
if (!srvi->listeners) {
|
||||
srvi->listeners = l;
|
||||
} else {
|
||||
l->next = srvi->listeners;
|
||||
srvi->listeners = l;
|
||||
}
|
||||
|
||||
if (p->ai_family == AF_INET) {
|
||||
struct sockaddr_in *ina = (struct sockaddr_in *)p->ai_addr;
|
||||
inet_ntop(p->ai_family, &ina->sin_addr, addr_str, sizeof(addr_str));
|
||||
uh_log_debug("Listen on: %s:%d with ssl %s\n", addr_str, ntohs(ina->sin_port), ssl ? "on" : "off");
|
||||
} else {
|
||||
struct sockaddr_in6 *in6a = (struct sockaddr_in6 *)p->ai_addr;
|
||||
inet_ntop(p->ai_family, &in6a->sin6_addr, addr_str, sizeof(addr_str));
|
||||
uh_log_debug("Listen on: [%s]:%d with ssl %s\n", addr_str, ntohs(in6a->sin6_port), ssl ? "on" : "off");
|
||||
}
|
||||
|
||||
bound++;
|
||||
|
||||
continue;
|
||||
|
||||
err:
|
||||
if (sock > -1)
|
||||
close(sock);
|
||||
}
|
||||
|
||||
if (listen(sock, SOMAXCONN) < 0) {
|
||||
uh_log_err("bind: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
freeaddrinfo(addrs);
|
||||
|
||||
if (uh_log_get_threshold() == LOG_DEBUG) {
|
||||
saddr2str(&addr.sa, addr_str, sizeof(addr_str), &port);
|
||||
uh_log_debug("Listen on: %s %d\n", addr_str, port);
|
||||
}
|
||||
return bound;
|
||||
}
|
||||
|
||||
void uh_server_init(struct uh_server *srv, struct ev_loop *loop)
|
||||
{
|
||||
struct uh_server_internal *srvi = (struct uh_server_internal *)srv;
|
||||
|
||||
memset(srvi, 0, sizeof(struct uh_server_internal));
|
||||
|
||||
srvi->loop = loop ? loop : EV_DEFAULT;
|
||||
srvi->sock = sock;
|
||||
|
||||
srv->get_loop = uh_get_loop;
|
||||
srv->free = uh_server_free;
|
||||
|
||||
srv->listen = uh_server_listen;
|
||||
|
||||
#if UHTTPD_SSL_SUPPORT
|
||||
srv->ssl_init = uh_server_ssl_init;
|
||||
#endif
|
||||
|
@ -378,13 +460,4 @@ int uh_server_init(struct uh_server *srv, struct ev_loop *loop, const char *host
|
|||
|
||||
srv->set_docroot = uh_set_docroot;
|
||||
srv->set_index_page = uh_set_index_page;
|
||||
|
||||
ev_io_init(&srvi->ior, uh_accept_cb, sock, EV_READ);
|
||||
ev_io_start(srvi->loop, &srvi->ior);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
|
14
src/uhttpd.h
14
src/uhttpd.h
|
@ -89,6 +89,14 @@ typedef void (*uh_path_handler_prototype)(struct uh_connection *conn, int event)
|
|||
struct uh_server {
|
||||
struct ev_loop *(*get_loop)(struct uh_server *srv);
|
||||
void (*free)(struct uh_server *srv);
|
||||
/*
|
||||
** listen an address, multiple call allowed
|
||||
** returns the number of successful listen
|
||||
**
|
||||
** :80 0:80 0.0.0.0:80 [::]:80
|
||||
** localhost:80 [::1]:80
|
||||
*/
|
||||
int (*listen)(struct uh_server *srv, const char *addr, bool ssl);
|
||||
#if UHTTPD_SSL_SUPPORT
|
||||
int (*ssl_init)(struct uh_server *srv, const char *cert, const char *key);
|
||||
#endif
|
||||
|
@ -120,11 +128,9 @@ struct uh_path_handler {
|
|||
/*
|
||||
* uh_server_new - creat an uh_server struct and init it
|
||||
* @loop: If NULL will use EV_DEFAULT
|
||||
* @host: If NULL will listen on "0.0.0.0"
|
||||
* @port: port to listen on
|
||||
*/
|
||||
struct uh_server *uh_server_new(struct ev_loop *loop, const char *host, int port);
|
||||
struct uh_server *uh_server_new(struct ev_loop *loop);
|
||||
|
||||
int uh_server_init(struct uh_server *srv, struct ev_loop *loop, const char *host, int port);
|
||||
void uh_server_init(struct uh_server *srv, struct ev_loop *loop);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,15 +29,23 @@
|
|||
|
||||
#include "uhttpd.h"
|
||||
|
||||
struct uh_server_internal;
|
||||
struct uh_connection_internal;
|
||||
|
||||
struct uh_listener {
|
||||
int sock;
|
||||
bool ssl;
|
||||
struct ev_io ior;
|
||||
struct uh_server_internal *srv;
|
||||
struct uh_listener *next;
|
||||
};
|
||||
|
||||
struct uh_server_internal {
|
||||
struct uh_server com;
|
||||
int sock;
|
||||
char *docroot;
|
||||
char *index_page;
|
||||
struct ev_loop *loop;
|
||||
struct ev_io ior;
|
||||
struct uh_listener *listeners;
|
||||
struct uh_connection_internal *conns;
|
||||
void (*conn_closed_cb)(struct uh_connection *conn);
|
||||
void (*default_handler)(struct uh_connection *conn, int event);
|
||||
|
@ -48,9 +56,4 @@ struct uh_server_internal {
|
|||
struct uh_path_handler *handlers;
|
||||
};
|
||||
|
||||
struct worker {
|
||||
struct ev_child w;
|
||||
int i;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue