Commit 203d4a79 authored by Deomid Ryabkov's avatar Deomid Ryabkov Committed by rojer

Improved handling of sockets > FD_SETSIZE

PUBLISHED_FROM=0bf765bf2248d43514643f335592a77d5875618e
parent b04d47c3
...@@ -3244,21 +3244,23 @@ void mg_if_destroy_conn(struct mg_connection *nc) { ...@@ -3244,21 +3244,23 @@ void mg_if_destroy_conn(struct mg_connection *nc) {
nc->sock = INVALID_SOCKET; nc->sock = INVALID_SOCKET;
} }
static void mg_accept_conn(struct mg_connection *lc) { static int mg_accept_conn(struct mg_connection *lc) {
struct mg_connection *nc; struct mg_connection *nc;
union socket_address sa; union socket_address sa;
socklen_t sa_len = sizeof(sa); socklen_t sa_len = sizeof(sa);
/* NOTE(lsm): on Windows, sock is always > FD_SETSIZE */ /* NOTE(lsm): on Windows, sock is always > FD_SETSIZE */
sock_t sock = accept(lc->sock, &sa.sa, &sa_len); sock_t sock = accept(lc->sock, &sa.sa, &sa_len);
if (sock == INVALID_SOCKET) { if (sock == INVALID_SOCKET) {
DBG(("%p: failed to accept: %d", lc, errno)); if (mg_is_error(-1)) DBG(("%p: failed to accept: %d", lc, errno));
return; return 0;
} }
nc = mg_if_accept_new_conn(lc); nc = mg_if_accept_new_conn(lc);
if (nc == NULL) { if (nc == NULL) {
closesocket(sock); closesocket(sock);
return; return 0;
} }
DBG(("%p conn from %s:%d", nc, inet_ntoa(sa.sin.sin_addr),
ntohs(sa.sin.sin_port)));
mg_sock_set(nc, sock); mg_sock_set(nc, sock);
#ifdef MG_ENABLE_SSL #ifdef MG_ENABLE_SSL
if (lc->ssl_ctx != NULL) { if (lc->ssl_ctx != NULL) {
...@@ -3272,6 +3274,7 @@ static void mg_accept_conn(struct mg_connection *lc) { ...@@ -3272,6 +3274,7 @@ static void mg_accept_conn(struct mg_connection *lc) {
{ {
mg_if_accept_tcp_cb(nc, &sa, sa_len); mg_if_accept_tcp_cb(nc, &sa, sa_len);
} }
return 1;
} }
/* 'sa' must be an initialized address to bind to */ /* 'sa' must be an initialized address to bind to */
...@@ -3420,8 +3423,8 @@ static void mg_read_from_socket(struct mg_connection *conn) { ...@@ -3420,8 +3423,8 @@ static void mg_read_from_socket(struct mg_connection *conn) {
{ {
n = (int) MG_RECV_FUNC(conn->sock, buf, n = (int) MG_RECV_FUNC(conn->sock, buf,
recv_avail_size(conn, MG_TCP_RECV_BUFFER_SIZE), 0); recv_avail_size(conn, MG_TCP_RECV_BUFFER_SIZE), 0);
DBG(("%p %d bytes (PLAIN) <- %d", conn, n, conn->sock));
if (n > 0) { if (n > 0) {
DBG(("%p %d bytes (PLAIN) <- %d", conn, n, conn->sock));
mg_if_recv_tcp_cb(conn, buf, n); mg_if_recv_tcp_cb(conn, buf, n);
} else { } else {
MG_FREE(buf); MG_FREE(buf);
...@@ -3553,22 +3556,22 @@ void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) { ...@@ -3553,22 +3556,22 @@ void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) {
* flag on a listening socket and hangs in a loop. * flag on a listening socket and hangs in a loop.
*/ */
if (fd_flags & _MG_F_FD_CAN_READ) mg_accept_conn(nc); if (fd_flags & _MG_F_FD_CAN_READ) mg_accept_conn(nc);
return;
} else { } else {
mg_read_from_socket(nc); mg_read_from_socket(nc);
} }
} }
if (nc->flags & MG_F_CLOSE_IMMEDIATELY) return;
} }
if ((fd_flags & _MG_F_FD_CAN_WRITE) && nc->send_mbuf.len > 0) { if (!(nc->flags & MG_F_CLOSE_IMMEDIATELY)) {
mg_write_to_socket(nc); if ((fd_flags & _MG_F_FD_CAN_WRITE) && nc->send_mbuf.len > 0) {
} mg_write_to_socket(nc);
}
if (!(fd_flags & (_MG_F_FD_CAN_READ | _MG_F_FD_CAN_WRITE))) { if (!(fd_flags & (_MG_F_FD_CAN_READ | _MG_F_FD_CAN_WRITE))) {
mg_if_poll(nc, now); mg_if_poll(nc, now);
}
mg_if_timer(nc, now);
} }
mg_if_timer(nc, now);
DBG(("%p after fd=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, nc->flags, DBG(("%p after fd=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, nc->flags,
(int) nc->recv_mbuf.len, (int) nc->send_mbuf.len)); (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
...@@ -3622,7 +3625,11 @@ void mg_ev_mgr_remove_conn(struct mg_connection *nc) { ...@@ -3622,7 +3625,11 @@ void mg_ev_mgr_remove_conn(struct mg_connection *nc) {
} }
void mg_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd) { void mg_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd) {
if (sock != INVALID_SOCKET) { if (sock != INVALID_SOCKET
#ifdef __unix__
&& sock < FD_SETSIZE
#endif
) {
FD_SET(sock, set); FD_SET(sock, set);
if (*max_fd == INVALID_SOCKET || sock > *max_fd) { if (*max_fd == INVALID_SOCKET || sock > *max_fd) {
*max_fd = sock; *max_fd = sock;
...@@ -3638,6 +3645,9 @@ time_t mg_mgr_poll(struct mg_mgr *mgr, int timeout_ms) { ...@@ -3638,6 +3645,9 @@ time_t mg_mgr_poll(struct mg_mgr *mgr, int timeout_ms) {
fd_set read_set, write_set, err_set; fd_set read_set, write_set, err_set;
sock_t max_fd = INVALID_SOCKET; sock_t max_fd = INVALID_SOCKET;
int num_fds, num_ev, num_timers = 0; int num_fds, num_ev, num_timers = 0;
#ifdef __unix__
int try_dup = 1;
#endif
FD_ZERO(&read_set); FD_ZERO(&read_set);
FD_ZERO(&write_set); FD_ZERO(&write_set);
...@@ -3657,6 +3667,20 @@ time_t mg_mgr_poll(struct mg_mgr *mgr, int timeout_ms) { ...@@ -3657,6 +3667,20 @@ time_t mg_mgr_poll(struct mg_mgr *mgr, int timeout_ms) {
if (nc->sock != INVALID_SOCKET) { if (nc->sock != INVALID_SOCKET) {
num_fds++; num_fds++;
#ifdef __unix__
/* A hack to make sure all our file descriptos fit into FD_SETSIZE. */
if (nc->sock >= FD_SETSIZE && try_dup) {
int new_sock = dup(nc->sock);
if (new_sock >= 0 && new_sock < FD_SETSIZE) {
closesocket(nc->sock);
DBG(("new sock %d -> %d", nc->sock, new_sock));
nc->sock = new_sock;
} else {
try_dup = 0;
}
}
#endif
if (!(nc->flags & MG_F_WANT_WRITE) && if (!(nc->flags & MG_F_WANT_WRITE) &&
nc->recv_mbuf.len < nc->recv_mbuf_limit && nc->recv_mbuf.len < nc->recv_mbuf_limit &&
(!(nc->flags & MG_F_UDP) || nc->listener == NULL)) { (!(nc->flags & MG_F_UDP) || nc->listener == NULL)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment