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