From 7b6e8fb93cb74bf0f59fc753243a04977a049f8d Mon Sep 17 00:00:00 2001 From: Sergey Lyubka <valenok@gmail.com> Date: Thu, 16 Jan 2014 13:23:23 +0000 Subject: [PATCH] Moved idle_timeout_ms into compile-time option --- mongoose.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 8 deletions(-) diff --git a/mongoose.c b/mongoose.c index f9d3c8f84..ad9afc5cb 100644 --- a/mongoose.c +++ b/mongoose.c @@ -1,5 +1,5 @@ // Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com> -// Copyright (c) 2013 Cesanta Software Limited +// Copyright (c) 2013-2014 Cesanta Software Limited // All rights reserved // // This library is dual-licensed: you can redistribute it and/or modify @@ -64,6 +64,7 @@ typedef struct _stati64 file_stat_t; #define snprintf _snprintf #define vsnprintf _vsnprintf #define INT64_FMT "I64d" +#define EINPROGRESS WSAEINPROGRESS #define mutex_init(x) InitializeCriticalSection(x) #define mutex_destroy(x) DeleteCriticalSection(x) #define mutex_lock(x) EnterCriticalSection(x) @@ -182,6 +183,10 @@ struct ll { struct ll *prev, *next; }; #define USE_POST_SIZE_LIMIT 0 #endif +#ifndef USE_IDLE_TIMEOUT_SECONDS +#define USE_IDLE_TIMEOUT_SECONDS 30 +#endif + #ifdef ENABLE_DBG #define DBG(x) do { printf("%-20s ", __func__); printf x; putchar('\n'); \ fflush(stdout); } while(0) @@ -235,7 +240,6 @@ enum { GLOBAL_AUTH_FILE, #endif HIDE_FILES_PATTERN, - IDLE_TIMEOUT_MS, #ifndef NO_FILESYSTEM INDEX_FILES, #endif @@ -265,7 +269,6 @@ static const char *static_config_options[] = { "global_auth_file", NULL, #endif "hide_files_patterns", NULL, - "idle_timeout_ms", "30000", #ifndef NO_FILESYSTEM "index_files","index.html,index.htm,index.cgi,index.php,index.lp", #endif @@ -307,10 +310,15 @@ union endpoint { struct uri_handler *uh; // URI handler user function }; -enum endpoint_type { EP_NONE, EP_FILE, EP_CGI, EP_USER, EP_PUT }; +enum endpoint_type { EP_NONE, EP_FILE, EP_CGI, EP_USER, EP_PUT, EP_CLIENT }; enum connection_flags { - CONN_CLOSE = 1, CONN_SPOOL_DONE = 2, CONN_SSL_HANDS_SHAKEN = 4, - CONN_HEADERS_SENT = 8, CONN_BUFFER = 16 + CONN_CLOSE = 1, // Connection must be closed at the end of the poll + CONN_SPOOL_DONE = 2, // All data has been buffered for sending + CONN_SSL_HANDS_SHAKEN = 4, // SSL handshake has completed. Only for SSL + CONN_HEADERS_SENT = 8, // User callback has sent HTTP headers + CONN_BUFFER = 16, // CGI only. Holds data send until CGI prints + // all HTTP headers + CONN_CONNECTED = 32 // HTTP client has connected }; struct connection { @@ -331,6 +339,7 @@ struct connection { int request_len; // Request length, including last \r\n after last header int flags; // CONN_* flags: CONN_CLOSE, CONN_SPOOL_DONE, etc void *ssl; // SSL descriptor + mg_handler_t handler; // Callback for HTTP client }; static void close_local_endpoint(struct connection *conn); @@ -3495,6 +3504,19 @@ static void read_from_client(struct connection *conn) { } } +static void read_from_server(struct connection *conn) { + sock_t ok, sock = conn->client_sock; + socklen_t len = sizeof(ok); + + conn->mg_conn.wsbits = 1; + if (!(conn->flags & CONN_CONNECTED) && + getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *) &ok, &len) < 0) { + conn->mg_conn.wsbits = 0; + } + conn->handler(&conn->mg_conn); + conn->flags |= CONN_CLOSE | CONN_CONNECTED; +} + #ifndef NO_LOGGING static void log_header(const struct mg_connection *conn, const char *header, FILE *fp) { @@ -3547,6 +3569,7 @@ static void close_local_endpoint(struct connection *conn) { (conn->endpoint_type == EP_FILE || conn->endpoint_type == EP_USER); switch (conn->endpoint_type) { + case EP_PUT: close(conn->endpoint.fd); break; case EP_FILE: close(conn->endpoint.fd); break; case EP_CGI: closesocket(conn->endpoint.cgi_sock); break; default: break; @@ -3591,6 +3614,40 @@ static void transfer_file_data(struct connection *conn) { } } +struct mg_connection *mg_connect(struct mg_server *server, const char *host, + int port, mg_handler_t handler) { + sock_t sock = INVALID_SOCKET; + struct sockaddr_in sin; + struct hostent *he = NULL; + struct connection *conn = NULL; + int connected; + + if (host == NULL || (he = gethostbyname(host)) == NULL || + (sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) return NULL; + + sin.sin_family = AF_INET; + sin.sin_port = htons((uint16_t) port); + sin.sin_addr = * (struct in_addr *) he->h_addr_list[0]; + set_non_blocking_mode(sock); + + connected = connect(sock, (struct sockaddr *) &sin, sizeof(sin)); + if (connected != 0 && errno != EINPROGRESS) { + return NULL; + } else if ((conn = (struct connection *) calloc(1, sizeof(*conn))) == NULL) { + closesocket(sock); + return NULL; + } + + conn->client_sock = sock; + conn->endpoint_type = EP_CLIENT; + conn->handler = handler; + conn->mg_conn.server_param = server->server_data; + conn->flags = connected == 0 ? CONN_CONNECTED : 0; + LINKED_LIST_ADD_TO_FRONT(&server->active_connections, &conn->link); + + return &conn->mg_conn; +} + static void execute_iteration(struct mg_server *server) { struct ll *lp, *tmp; struct connection *conn; @@ -3617,7 +3674,7 @@ unsigned int mg_poll_server(struct mg_server *server, int milliseconds) { fd_set read_set, write_set; sock_t max_fd = -1; time_t current_time = time(NULL), expire_time = current_time - - atoi(server->config_options[IDLE_TIMEOUT_MS]) / 1000; + USE_IDLE_TIMEOUT_SECONDS; if (server->listening_sock == INVALID_SOCKET) return 0; @@ -3661,7 +3718,11 @@ unsigned int mg_poll_server(struct mg_server *server, int milliseconds) { conn = LINKED_LIST_ENTRY(lp, struct connection, link); if (FD_ISSET(conn->client_sock, &read_set)) { conn->last_activity_time = current_time; - read_from_client(conn); + if (conn->endpoint_type == EP_CLIENT) { + read_from_server(conn); + } else { + read_from_client(conn); + } } #ifndef NO_CGI if (conn->endpoint_type == EP_CGI && -- GitLab