mirror of
https://github.com/lammertb/libhttp.git
synced 2026-01-27 08:02:47 +03:00
Moved mg_accept_new_connection to own file
This commit is contained in:
1
Makefile
1
Makefile
@@ -42,6 +42,7 @@ PORTS = 8080
|
||||
BUILD_DIRS = $(BUILD_DIR) $(BUILD_DIR)/src $(BUILD_DIR)/resources
|
||||
|
||||
LIB_SOURCES = src/libhttp.c \
|
||||
src/httplib_accept_new_connection.c \
|
||||
src/httplib_check_feature.c \
|
||||
src/httplib_free_context.c \
|
||||
src/httplib_get_response_code_text.c \
|
||||
|
||||
103
src/httplib_accept_new_connection.c
Normal file
103
src/httplib_accept_new_connection.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Lammert Bies
|
||||
* Copyright (c) 2013-2016 the Civetweb developers
|
||||
* Copyright (c) 2004-2013 Sergey Lyubka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "libhttp-private.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void XX_httplib_accept_new_connection( const struct socket *lostener, struct mg_context *ctx );
|
||||
*
|
||||
* The function XX_httplib_accept_new_connection() is used to process new
|
||||
* incoming connections to the server.
|
||||
*/
|
||||
|
||||
void XX_httplib_accept_new_connection( const struct socket *listener, struct mg_context *ctx ) {
|
||||
|
||||
struct socket so;
|
||||
char src_addr[IP_ADDR_STR_LEN];
|
||||
socklen_t len = sizeof(so.rsa);
|
||||
int on = 1;
|
||||
int timeout;
|
||||
|
||||
if ( listener == NULL ) return;
|
||||
|
||||
if ((so.sock = accept(listener->sock, &so.rsa.sa, &len))
|
||||
== INVALID_SOCKET) {
|
||||
} else if (!XX_httplib_check_acl(ctx, ntohl(*(uint32_t *)&so.rsa.sin.sin_addr))) {
|
||||
XX_httplib_sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
|
||||
mg_cry( XX_httplib_fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
|
||||
closesocket(so.sock);
|
||||
so.sock = INVALID_SOCKET;
|
||||
} else {
|
||||
/* Put so socket structure into the queue */
|
||||
XX_httplib_set_close_on_exec(so.sock, XX_httplib_fc(ctx));
|
||||
so.is_ssl = listener->is_ssl;
|
||||
so.ssl_redir = listener->ssl_redir;
|
||||
if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
|
||||
mg_cry( XX_httplib_fc(ctx), "%s: getsockname() failed: %s", __func__, strerror(ERRNO));
|
||||
}
|
||||
|
||||
/* Set TCP keep-alive. This is needed because if HTTP-level
|
||||
* keep-alive
|
||||
* is enabled, and client resets the connection, server won't get
|
||||
* TCP FIN or RST and will keep the connection open forever. With
|
||||
* TCP keep-alive, next keep-alive handshake will figure out that
|
||||
* the client is down and will close the server end.
|
||||
* Thanks to Igor Klopov who suggested the patch. */
|
||||
if (setsockopt(so.sock, SOL_SOCKET, SO_KEEPALIVE, (SOCK_OPT_TYPE)&on, sizeof(on)) != 0) {
|
||||
|
||||
mg_cry( XX_httplib_fc(ctx), "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s", __func__, strerror(ERRNO));
|
||||
}
|
||||
|
||||
/* Disable TCP Nagle's algorithm. Normally TCP packets are coalesced
|
||||
* to effectively fill up the underlying IP packet payload and
|
||||
* reduce the overhead of sending lots of small buffers. However
|
||||
* this hurts the server's throughput (ie. operations per second)
|
||||
* when HTTP 1.1 persistent connections are used and the responses
|
||||
* are relatively small (eg. less than 1400 bytes).
|
||||
*/
|
||||
if ((ctx != NULL) && (ctx->config[CONFIG_TCP_NODELAY] != NULL)
|
||||
&& (!strcmp(ctx->config[CONFIG_TCP_NODELAY], "1"))) {
|
||||
if (XX_httplib_set_tcp_nodelay(so.sock, 1) != 0) {
|
||||
mg_cry( XX_httplib_fc(ctx), "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s", __func__, strerror(ERRNO));
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx && ctx->config[REQUEST_TIMEOUT]) {
|
||||
timeout = atoi(ctx->config[REQUEST_TIMEOUT]);
|
||||
} else {
|
||||
timeout = -1;
|
||||
}
|
||||
|
||||
if (timeout > 0) {
|
||||
XX_httplib_set_sock_timeout(so.sock, timeout);
|
||||
}
|
||||
|
||||
XX_httplib_produce_socket(ctx, &so);
|
||||
}
|
||||
|
||||
} /* XX_httplib_accept_new_connection */
|
||||
@@ -515,6 +515,8 @@ typedef struct asn1_integer ASN1_INTEGER;
|
||||
typedef struct evp_md EVP_MD;
|
||||
typedef struct x509 X509;
|
||||
|
||||
#define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */
|
||||
|
||||
|
||||
#define SSL_CTRL_OPTIONS (32)
|
||||
#define SSL_CTRL_CLEAR_OPTIONS (77)
|
||||
@@ -793,19 +795,25 @@ struct worker_thread_args {
|
||||
void XX_httplib_accept_new_connection( const struct socket *listener, struct mg_context *ctx );
|
||||
int XX_httplib_atomic_dec( volatile int *addr );
|
||||
int XX_httplib_atomic_inc( volatile int *addr );
|
||||
int XX_httplib_check_acl( struct mg_context *ctx, uint32_t remote_ip );
|
||||
void XX_httplib_close_all_listening_sockets( struct mg_context *ctx );
|
||||
void XX_httplib_set_close_on_exec( SOCKET sock, struct mg_connection *conn );
|
||||
struct mg_connection * XX_httplib_fc( struct mg_context *ctx );
|
||||
void XX_httplib_free_context( struct mg_context *ctx );
|
||||
int XX_httplib_get_option_index( const char *name );
|
||||
uint64_t XX_httplib_get_random( void );
|
||||
void XX_httplib_get_system_name( char **sysName );
|
||||
int XX_httplib_join_thread( pthread_t threadid );
|
||||
void XX_httplib_produce_socket( struct mg_context *ctx, const struct socket *sp );
|
||||
int XX_httplib_set_acl_option( struct mg_context *ctx );
|
||||
int XX_httplib_set_gpass_option( struct mg_context *ctx );
|
||||
int XX_httplib_set_ports_option( struct mg_context *ctx );
|
||||
int XX_httplib_set_sock_timeout( SOCKET sock, int milliseconds );
|
||||
int XX_httplib_set_ssl_option( struct mg_context *ctx );
|
||||
int XX_httplib_set_tcp_nodelay( SOCKET sock, int nodelay_on );
|
||||
void XX_httplib_set_thread_name( const char *name );
|
||||
int XX_httplib_set_uid_option( struct mg_context *ctx );
|
||||
void XX_httplib_sockaddr_to_string(char *buf, size_t len, const union usa *usa);
|
||||
char * XX_httplib_strdup( const char *str );
|
||||
void XX_httplib_tls_dtor( void *key );
|
||||
void XX_httplib_uninitialize_ssl( struct mg_context *ctx );
|
||||
|
||||
165
src/libhttp.c
165
src/libhttp.c
@@ -490,9 +490,6 @@ typedef int socklen_t;
|
||||
#endif /* NO_SOCKLEN_T */
|
||||
#define _DARWIN_UNLIMITED_SELECT
|
||||
|
||||
#define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */
|
||||
|
||||
|
||||
|
||||
#if !defined(NO_SSL) && !defined(NO_SSL_DL)
|
||||
|
||||
@@ -1168,7 +1165,7 @@ int mg_get_server_ports(const struct mg_context *ctx, int size, struct mg_server
|
||||
}
|
||||
|
||||
|
||||
static void sockaddr_to_string(char *buf, size_t len, const union usa *usa) {
|
||||
void XX_httplib_sockaddr_to_string(char *buf, size_t len, const union usa *usa) {
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
@@ -1182,7 +1179,8 @@ static void sockaddr_to_string(char *buf, size_t len, const union usa *usa) {
|
||||
getnameinfo(&usa->sa, sizeof(usa->sin6), buf, (unsigned)len, NULL, 0, NI_NUMERICHOST);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} /* XX_httplib_sockaddr_to_string */
|
||||
|
||||
|
||||
/* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be
|
||||
@@ -1246,7 +1244,7 @@ void mg_cry(const struct mg_connection *conn, const char *fmt, ...) {
|
||||
flockfile(fi.fp);
|
||||
timestamp = time(NULL);
|
||||
|
||||
sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
|
||||
XX_httplib_sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
|
||||
fprintf(fi.fp,
|
||||
"[%010lu] [error] [client %s] ",
|
||||
(unsigned long)timestamp,
|
||||
@@ -2221,17 +2219,17 @@ static int poll(struct pollfd *pfd, unsigned int n, int milliseconds) {
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
/* conn parameter may be NULL */
|
||||
void XX_httplib_set_close_on_exec( SOCKET sock, struct mg_connection *conn ) {
|
||||
|
||||
static void
|
||||
set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
|
||||
{
|
||||
(void)conn; /* Unused. */
|
||||
#if defined(_WIN32_WCE)
|
||||
(void)sock;
|
||||
#else
|
||||
SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
} /* XX_httplib_set_close_on_exec */
|
||||
|
||||
|
||||
int
|
||||
@@ -2474,14 +2472,14 @@ static int mg_stat(struct mg_connection *conn, const char *path, struct file *fi
|
||||
|
||||
} /* mg_stat */
|
||||
|
||||
|
||||
static void set_close_on_exec(SOCKET fd, struct mg_connection *conn /* may be null */) {
|
||||
/* conn may be NULL */
|
||||
void XX_httplib_set_close_on_exec( SOCKET fd, struct mg_connection *conn ) {
|
||||
|
||||
if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
|
||||
if (conn) { mg_cry(conn, "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s", __func__, strerror(ERRNO)); }
|
||||
}
|
||||
|
||||
} /* set_close_on_exec */
|
||||
} /* XX_httplib_set_close_on_exec */
|
||||
|
||||
|
||||
int mg_start_thread(mg_thread_func_t func, void *param) {
|
||||
@@ -4549,7 +4547,7 @@ connect_socket(struct mg_context *ctx /* may be NULL */,
|
||||
return 0;
|
||||
}
|
||||
|
||||
set_close_on_exec(*sock, XX_httplib_fc(ctx));
|
||||
XX_httplib_set_close_on_exec(*sock, XX_httplib_fc(ctx));
|
||||
|
||||
if ((ip_ver == 4)
|
||||
&& (connect(*sock, (struct sockaddr *)&sa->sin, sizeof(sa->sin))
|
||||
@@ -5904,7 +5902,7 @@ static void prepare_cgi_environment(struct mg_connection *conn, const char *prog
|
||||
addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
|
||||
}
|
||||
|
||||
sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
|
||||
XX_httplib_sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
|
||||
addenv(env, "REMOTE_ADDR=%s", src_addr);
|
||||
|
||||
addenv(env, "REQUEST_METHOD=%s", conn->request_info.request_method);
|
||||
@@ -6094,12 +6092,12 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) {
|
||||
}
|
||||
|
||||
/* Make sure child closes all pipe descriptors. It must dup them to 0,1 */
|
||||
set_close_on_exec((SOCKET)fdin[0], conn); /* stdin read */
|
||||
set_close_on_exec((SOCKET)fdout[1], conn); /* stdout write */
|
||||
set_close_on_exec((SOCKET)fderr[1], conn); /* stderr write */
|
||||
set_close_on_exec((SOCKET)fdin[1], conn); /* stdin write */
|
||||
set_close_on_exec((SOCKET)fdout[0], conn); /* stdout read */
|
||||
set_close_on_exec((SOCKET)fderr[0], conn); /* stderr read */
|
||||
XX_httplib_set_close_on_exec((SOCKET)fdin[0], conn); /* stdin read */
|
||||
XX_httplib_set_close_on_exec((SOCKET)fdout[1], conn); /* stdout write */
|
||||
XX_httplib_set_close_on_exec((SOCKET)fderr[1], conn); /* stderr write */
|
||||
XX_httplib_set_close_on_exec((SOCKET)fdin[1], conn); /* stdin write */
|
||||
XX_httplib_set_close_on_exec((SOCKET)fdout[0], conn); /* stdout read */
|
||||
XX_httplib_set_close_on_exec((SOCKET)fderr[0], conn); /* stderr read */
|
||||
|
||||
/* Parent closes only one side of the pipes.
|
||||
* If we don't mark them as closed, close() attempt before
|
||||
@@ -7741,9 +7739,7 @@ static void redirect_to_https_port(struct mg_connection *conn, int ssl_index) {
|
||||
} else {
|
||||
/* Cannot get host from the Host: header.
|
||||
* Fallback to our IP address. */
|
||||
if (conn) {
|
||||
sockaddr_to_string(host, hostlen, &conn->client.lsa);
|
||||
}
|
||||
if (conn) XX_httplib_sockaddr_to_string(host, hostlen, &conn->client.lsa);
|
||||
}
|
||||
|
||||
/* Send host, port, uri and (if it exists) ?query_string */
|
||||
@@ -8806,7 +8802,7 @@ int XX_httplib_set_ports_option( struct mg_context *ctx ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
set_close_on_exec(so.sock, XX_httplib_fc(ctx));
|
||||
XX_httplib_set_close_on_exec(so.sock, XX_httplib_fc(ctx));
|
||||
ctx->listening_sockets = ptr;
|
||||
ctx->listening_sockets[ctx->num_listening_sockets] = so;
|
||||
ctx->listening_socket_fds = pfd;
|
||||
@@ -8877,7 +8873,7 @@ static void log_access(const struct mg_connection *conn) {
|
||||
|
||||
ri = &conn->request_info;
|
||||
|
||||
sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
|
||||
XX_httplib_sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
|
||||
referer = header_val(conn, "Referer");
|
||||
user_agent = header_val(conn, "User-Agent");
|
||||
|
||||
@@ -8916,7 +8912,7 @@ static void log_access(const struct mg_connection *conn) {
|
||||
/* Verify given socket address against the ACL.
|
||||
* Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
|
||||
*/
|
||||
static int check_acl(struct mg_context *ctx, uint32_t remote_ip) {
|
||||
int XX_httplib_check_acl( struct mg_context *ctx, uint32_t remote_ip ) {
|
||||
|
||||
int allowed, flag;
|
||||
uint32_t net, mask;
|
||||
@@ -8938,15 +8934,14 @@ static int check_acl(struct mg_context *ctx, uint32_t remote_ip) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (net == (remote_ip & mask)) {
|
||||
allowed = flag;
|
||||
}
|
||||
if (net == (remote_ip & mask)) allowed = flag;
|
||||
}
|
||||
|
||||
return allowed == '+';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
} /* XX_httplib_check_acl */
|
||||
|
||||
|
||||
#if !defined(_WIN32)
|
||||
@@ -9638,7 +9633,7 @@ int XX_httplib_set_gpass_option( struct mg_context *ctx ) {
|
||||
|
||||
int XX_httplib_set_acl_option(struct mg_context *ctx) {
|
||||
|
||||
return check_acl(ctx, (uint32_t)0x7f000001UL) != -1;
|
||||
return XX_httplib_check_acl(ctx, (uint32_t)0x7f000001UL) != -1;
|
||||
|
||||
} /* XX_httplib_set_acl_option */
|
||||
|
||||
@@ -9666,7 +9661,7 @@ static void reset_per_request_attributes(struct mg_connection *conn) {
|
||||
}
|
||||
|
||||
|
||||
static int set_sock_timeout(SOCKET sock, int milliseconds) {
|
||||
int XX_httplib_set_sock_timeout( SOCKET sock, int milliseconds ) {
|
||||
|
||||
int r0 = 0, r1, r2;
|
||||
|
||||
@@ -9702,17 +9697,19 @@ static int set_sock_timeout(SOCKET sock, int milliseconds) {
|
||||
r2 = setsockopt( sock, SOL_SOCKET, SO_SNDTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
|
||||
|
||||
return r0 || r1 || r2;
|
||||
}
|
||||
|
||||
} /* XX_httplib_set_sock_timeout */
|
||||
|
||||
|
||||
static int set_tcp_nodelay(SOCKET sock, int nodelay_on) {
|
||||
int XX_httplib_set_tcp_nodelay( SOCKET sock, int nodelay_on ) {
|
||||
|
||||
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (SOCK_OPT_TYPE)&nodelay_on, sizeof(nodelay_on)) != 0) { /* Error */
|
||||
return 1;
|
||||
}
|
||||
/* OK */
|
||||
return 0;
|
||||
}
|
||||
|
||||
} /* XX_httplib_set_tcp_nodelay */
|
||||
|
||||
|
||||
static void close_socket_gracefully(struct mg_connection *conn) {
|
||||
@@ -10232,7 +10229,7 @@ int mg_get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int
|
||||
if (timeout >= 0) {
|
||||
mg_snprintf(conn, NULL, txt, sizeof(txt), "%i", timeout);
|
||||
rctx.config[REQUEST_TIMEOUT] = txt;
|
||||
set_sock_timeout(conn->client.sock, timeout);
|
||||
XX_httplib_set_sock_timeout(conn->client.sock, timeout);
|
||||
} else {
|
||||
rctx.config[REQUEST_TIMEOUT] = NULL;
|
||||
}
|
||||
@@ -10582,9 +10579,8 @@ process_new_connection(struct mg_connection *conn)
|
||||
|
||||
#if defined(ALTERNATIVE_QUEUE)
|
||||
|
||||
static void
|
||||
produce_socket(struct mg_context *ctx, const struct socket *sp)
|
||||
{
|
||||
void XX_httplib_produce_socket( struct mg_context *ctx, const struct socket *sp ) {
|
||||
|
||||
unsigned int i;
|
||||
|
||||
for (;;) {
|
||||
@@ -10600,12 +10596,12 @@ produce_socket(struct mg_context *ctx, const struct socket *sp)
|
||||
/* queue is full */
|
||||
mg_sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
} /* XX_httplib_produce_socket */
|
||||
|
||||
|
||||
static int
|
||||
consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index)
|
||||
{
|
||||
static int consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index) {
|
||||
|
||||
ctx->client_socks[thread_index].in_use = 0;
|
||||
event_wait(ctx->client_wait_events[thread_index]);
|
||||
*sp = ctx->client_socks[thread_index];
|
||||
@@ -10652,9 +10648,8 @@ consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index)
|
||||
|
||||
|
||||
/* Master thread adds accepted socket to a queue */
|
||||
static void
|
||||
produce_socket(struct mg_context *ctx, const struct socket *sp)
|
||||
{
|
||||
void XX_httplib_produce_socket(struct mg_context *ctx, const struct socket *sp) {
|
||||
|
||||
#define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
|
||||
if (!ctx) {
|
||||
return;
|
||||
@@ -10676,7 +10671,9 @@ produce_socket(struct mg_context *ctx, const struct socket *sp)
|
||||
(void)pthread_cond_signal(&ctx->sq_full);
|
||||
(void)pthread_mutex_unlock(&ctx->thread_mutex);
|
||||
#undef QUEUE_SIZE
|
||||
}
|
||||
|
||||
} /* XX_httplib_produce_socket */
|
||||
|
||||
#endif /* ALTERNATIVE_QUEUE */
|
||||
|
||||
|
||||
@@ -10738,7 +10735,7 @@ static void * worker_thread_run( struct worker_thread_args *thread_args ) {
|
||||
ntohs(conn->client.rsa.sin.sin_port);
|
||||
}
|
||||
|
||||
sockaddr_to_string(conn->request_info.remote_addr,
|
||||
XX_httplib_sockaddr_to_string(conn->request_info.remote_addr,
|
||||
sizeof(conn->request_info.remote_addr),
|
||||
&conn->client.rsa);
|
||||
|
||||
@@ -10818,73 +10815,3 @@ void *XX_httplib_worker_thread( void *thread_func_param ) {
|
||||
} /* XX_httplib_worker_thread */
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
||||
void XX_httplib_accept_new_connection( const struct socket *listener, struct mg_context *ctx ) {
|
||||
|
||||
struct socket so;
|
||||
char src_addr[IP_ADDR_STR_LEN];
|
||||
socklen_t len = sizeof(so.rsa);
|
||||
int on = 1;
|
||||
int timeout;
|
||||
|
||||
if (!listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((so.sock = accept(listener->sock, &so.rsa.sa, &len))
|
||||
== INVALID_SOCKET) {
|
||||
} else if (!check_acl(ctx, ntohl(*(uint32_t *)&so.rsa.sin.sin_addr))) {
|
||||
sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
|
||||
mg_cry( XX_httplib_fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
|
||||
closesocket(so.sock);
|
||||
so.sock = INVALID_SOCKET;
|
||||
} else {
|
||||
/* Put so socket structure into the queue */
|
||||
set_close_on_exec(so.sock, XX_httplib_fc(ctx));
|
||||
so.is_ssl = listener->is_ssl;
|
||||
so.ssl_redir = listener->ssl_redir;
|
||||
if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
|
||||
mg_cry( XX_httplib_fc(ctx), "%s: getsockname() failed: %s", __func__, strerror(ERRNO));
|
||||
}
|
||||
|
||||
/* Set TCP keep-alive. This is needed because if HTTP-level
|
||||
* keep-alive
|
||||
* is enabled, and client resets the connection, server won't get
|
||||
* TCP FIN or RST and will keep the connection open forever. With
|
||||
* TCP keep-alive, next keep-alive handshake will figure out that
|
||||
* the client is down and will close the server end.
|
||||
* Thanks to Igor Klopov who suggested the patch. */
|
||||
if (setsockopt(so.sock, SOL_SOCKET, SO_KEEPALIVE, (SOCK_OPT_TYPE)&on, sizeof(on)) != 0) {
|
||||
|
||||
mg_cry( XX_httplib_fc(ctx), "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s", __func__, strerror(ERRNO));
|
||||
}
|
||||
|
||||
/* Disable TCP Nagle's algorithm. Normally TCP packets are coalesced
|
||||
* to effectively fill up the underlying IP packet payload and
|
||||
* reduce the overhead of sending lots of small buffers. However
|
||||
* this hurts the server's throughput (ie. operations per second)
|
||||
* when HTTP 1.1 persistent connections are used and the responses
|
||||
* are relatively small (eg. less than 1400 bytes).
|
||||
*/
|
||||
if ((ctx != NULL) && (ctx->config[CONFIG_TCP_NODELAY] != NULL)
|
||||
&& (!strcmp(ctx->config[CONFIG_TCP_NODELAY], "1"))) {
|
||||
if (set_tcp_nodelay(so.sock, 1) != 0) {
|
||||
mg_cry( XX_httplib_fc(ctx), "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s", __func__, strerror(ERRNO));
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx && ctx->config[REQUEST_TIMEOUT]) {
|
||||
timeout = atoi(ctx->config[REQUEST_TIMEOUT]);
|
||||
} else {
|
||||
timeout = -1;
|
||||
}
|
||||
|
||||
if (timeout > 0) {
|
||||
set_sock_timeout(so.sock, timeout);
|
||||
}
|
||||
|
||||
produce_socket(ctx, &so);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user