parent
b2ce003bcc
commit
db85c135cb
78
src/uhttpd.c
78
src/uhttpd.c
|
@ -27,7 +27,6 @@
|
|||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef HAVE_DLOPEN
|
||||
#include <dlfcn.h>
|
||||
|
@ -145,6 +144,40 @@ static void uh_worker_exit(struct ev_loop *loop, struct ev_child *w, int revents
|
|||
free(wk);
|
||||
}
|
||||
|
||||
static int uh_socket(int family)
|
||||
{
|
||||
int on = 1;
|
||||
int sock;
|
||||
|
||||
sock = socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||
if (sock < 0) {
|
||||
uh_log_err("socket: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) < 0) {
|
||||
uh_log_err("setsockopt: %s\n", strerror(errno));
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int));
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
static int uh_listen(int sock, struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
if (bind(sock, addr, addrlen) < 0) {
|
||||
uh_log_err("bind: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
listen(sock, SOMAXCONN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uh_start_worker(struct uh_server *srv, int n)
|
||||
{
|
||||
struct uh_server_internal *srvi = (struct uh_server_internal *)srv;
|
||||
|
@ -159,6 +192,9 @@ static void uh_start_worker(struct uh_server *srv, int n)
|
|||
|
||||
uh_stop_accept(srvi);
|
||||
|
||||
if (srvi->reuseport)
|
||||
close(srvi->sock);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
pids[i] = fork();
|
||||
switch (pids[i]) {
|
||||
|
@ -167,6 +203,12 @@ static void uh_start_worker(struct uh_server *srv, int n)
|
|||
return;
|
||||
case 0:
|
||||
ev_loop_fork(srvi->loop);
|
||||
|
||||
if (srvi->reuseport) {
|
||||
srvi->sock = uh_socket(srvi->addr.sa.sa_family);
|
||||
uh_listen(srvi->sock, &srvi->addr.sa, srvi->addrlen);
|
||||
}
|
||||
|
||||
uh_start_accept(srvi);
|
||||
|
||||
uh_log_info("worker %d started\n", i);
|
||||
|
@ -337,7 +379,6 @@ int uh_server_init(struct uh_server *srv, struct ev_loop *loop, const char *host
|
|||
char addr_str[INET6_ADDRSTRLEN];
|
||||
socklen_t addrlen;
|
||||
int sock = -1;
|
||||
int on = 1;
|
||||
|
||||
if (!host || *host == '\0') {
|
||||
addr.sin.sin_family = AF_INET;
|
||||
|
@ -377,34 +418,31 @@ int uh_server_init(struct uh_server *srv, struct ev_loop *loop, const char *host
|
|||
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));
|
||||
memset(srvi, 0, sizeof(struct uh_server_internal));
|
||||
|
||||
srvi->loop = loop ? loop : EV_DEFAULT;
|
||||
|
||||
srvi->reuseport = support_so_reuseport();
|
||||
|
||||
sock = uh_socket(addr.sa.sa_family);
|
||||
if (sock < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) < 0) {
|
||||
uh_log_err("setsockopt: %s\n", strerror(errno));
|
||||
if (uh_listen(sock, &addr.sa, addrlen) < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (bind(sock, &addr.sa, addrlen) < 0) {
|
||||
close(sock);
|
||||
uh_log_err("bind: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
srvi->sock = sock;
|
||||
|
||||
listen(sock, SOMAXCONN);
|
||||
uh_start_accept(srvi);
|
||||
|
||||
srvi->addrlen = addrlen;
|
||||
memcpy(&srvi->addr, &addr, sizeof(addr));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
memset(srvi, 0, sizeof(struct uh_server_internal));
|
||||
|
||||
srvi->loop = loop ? loop : EV_DEFAULT;
|
||||
srvi->sock = sock;
|
||||
srv->free = uh_server_free;
|
||||
srv->start_worker = uh_start_worker;
|
||||
|
||||
|
@ -420,8 +458,6 @@ 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;
|
||||
|
||||
uh_start_accept(srvi);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#ifndef LIBUHTTPD_UHTTPD_INTERNAL_H
|
||||
#define LIBUHTTPD_UHTTPD_INTERNAL_H
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "uhttpd.h"
|
||||
|
||||
struct uh_connection_internal;
|
||||
|
@ -32,6 +34,13 @@ struct uh_connection_internal;
|
|||
struct uh_server_internal {
|
||||
struct uh_server com;
|
||||
int sock;
|
||||
bool reuseport;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
} addr;
|
||||
socklen_t addrlen;
|
||||
char *docroot;
|
||||
char *index_page;
|
||||
struct ev_loop *loop;
|
||||
|
|
17
src/utils.c
17
src/utils.c
|
@ -27,6 +27,7 @@
|
|||
#include <inttypes.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
|
@ -44,3 +45,19 @@ const char *saddr2str(struct sockaddr *addr, char buf[], int len, int *port)
|
|||
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool support_so_reuseport()
|
||||
{
|
||||
bool ok = false;
|
||||
int on = 1;
|
||||
int sock;
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (!setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int)))
|
||||
ok = true;
|
||||
|
||||
close(sock);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -41,4 +41,6 @@
|
|||
|
||||
const char *saddr2str(struct sockaddr *addr, char buf[], int len, int *port);
|
||||
|
||||
bool support_so_reuseport();
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue