|  | @@ -449,7 +449,7 @@ enum {
 | 
											
												
													
														|  |    ACCESS_LOG_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE,
 |  |    ACCESS_LOG_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE,
 | 
											
												
													
														|  |    GLOBAL_PASSWORDS_FILE, INDEX_FILES, ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST,
 |  |    GLOBAL_PASSWORDS_FILE, INDEX_FILES, ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST,
 | 
											
												
													
														|  |    EXTRA_MIME_TYPES, LISTENING_PORTS, DOCUMENT_ROOT, SSL_CERTIFICATE,
 |  |    EXTRA_MIME_TYPES, LISTENING_PORTS, DOCUMENT_ROOT, SSL_CERTIFICATE,
 | 
											
												
													
														|  | -  NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES,
 |  | 
 | 
											
												
													
														|  | 
 |  | +  NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES, REQUEST_TIMEOUT,
 | 
											
												
													
														|  |    NUM_OPTIONS
 |  |    NUM_OPTIONS
 | 
											
												
													
														|  |  };
 |  |  };
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -477,6 +477,7 @@ static const char *config_options[] = {
 | 
											
												
													
														|  |    "u", "run_as_user", NULL,
 |  |    "u", "run_as_user", NULL,
 | 
											
												
													
														|  |    "w", "url_rewrite_patterns", NULL,
 |  |    "w", "url_rewrite_patterns", NULL,
 | 
											
												
													
														|  |    "x", "hide_files_patterns", NULL,
 |  |    "x", "hide_files_patterns", NULL,
 | 
											
												
													
														|  | 
 |  | +  "z", "request_timeout", NULL,
 | 
											
												
													
														|  |    NULL
 |  |    NULL
 | 
											
												
													
														|  |  };
 |  |  };
 | 
											
												
													
														|  |  #define ENTRIES_PER_CONFIG_OPTION 3
 |  |  #define ENTRIES_PER_CONFIG_OPTION 3
 | 
											
										
											
												
													
														|  | @@ -4314,6 +4315,23 @@ static int parse_port_string(const struct vec *vec, struct socket *so) {
 | 
											
												
													
														|  |    return 1;
 |  |    return 1;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +static int set_timeout(struct mg_context *ctx, SOCKET sock) {
 | 
											
												
													
														|  | 
 |  | +#ifndef _WIN32
 | 
											
												
													
														|  | 
 |  | +    struct timeval timeout;
 | 
											
												
													
														|  | 
 |  | +    if( !ctx->config[REQUEST_TIMEOUT] )
 | 
											
												
													
														|  | 
 |  | +        return 0;
 | 
											
												
													
														|  | 
 |  | +    timeout.tv_sec = 0;
 | 
											
												
													
														|  | 
 |  | +    timeout.tv_usec = atoi(ctx->config[REQUEST_TIMEOUT]) * 1000;
 | 
											
												
													
														|  | 
 |  | +#else
 | 
											
												
													
														|  | 
 |  | +    DWORD timeout;
 | 
											
												
													
														|  | 
 |  | +    if( !ctx->config[REQUEST_TIMEOUT] )
 | 
											
												
													
														|  | 
 |  | +        return 0;
 | 
											
												
													
														|  | 
 |  | +    timeout = atoi(ctx->config[REQUEST_TIMEOUT]);
 | 
											
												
													
														|  | 
 |  | +#endif
 | 
											
												
													
														|  | 
 |  | +    return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, sizeof(timeout))
 | 
											
												
													
														|  | 
 |  | +        || setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&timeout, sizeof(timeout));
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  static int set_ports_option(struct mg_context *ctx) {
 |  |  static int set_ports_option(struct mg_context *ctx) {
 | 
											
												
													
														|  |    const char *list = ctx->config[LISTENING_PORTS];
 |  |    const char *list = ctx->config[LISTENING_PORTS];
 | 
											
												
													
														|  |    int on = 1, success = 1;
 |  |    int on = 1, success = 1;
 | 
											
										
											
												
													
														|  | @@ -4332,6 +4350,7 @@ static int set_ports_option(struct mg_context *ctx) {
 | 
											
												
													
														|  |        success = 0;
 |  |        success = 0;
 | 
											
												
													
														|  |      } else if ((sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6)) ==
 |  |      } else if ((sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6)) ==
 | 
											
												
													
														|  |                 INVALID_SOCKET ||
 |  |                 INVALID_SOCKET ||
 | 
											
												
													
														|  | 
 |  | +               set_timeout(ctx, sock) ||
 | 
											
												
													
														|  |                 // On Windows, SO_REUSEADDR is recommended only for
 |  |                 // On Windows, SO_REUSEADDR is recommended only for
 | 
											
												
													
														|  |                 // broadcast UDP sockets
 |  |                 // broadcast UDP sockets
 | 
											
												
													
														|  |                 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &on,
 |  |                 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &on,
 |