|  | @@ -9595,6 +9595,7 @@ static void reset_per_request_attributes(struct mg_connection *conn)
 | 
											
												
													
														|  |  	conn->request_info.remote_user = NULL;
 |  |  	conn->request_info.remote_user = NULL;
 | 
											
												
													
														|  |  	conn->request_info.request_method = NULL;
 |  |  	conn->request_info.request_method = NULL;
 | 
											
												
													
														|  |  	conn->request_info.uri = NULL;
 |  |  	conn->request_info.uri = NULL;
 | 
											
												
													
														|  | 
 |  | +	conn->request_info.rel_uri = NULL;
 | 
											
												
													
														|  |  	conn->request_info.http_version = NULL;
 |  |  	conn->request_info.http_version = NULL;
 | 
											
												
													
														|  |  	conn->request_info.num_headers = 0;
 |  |  	conn->request_info.num_headers = 0;
 | 
											
												
													
														|  |  	conn->data_len = 0;
 |  |  	conn->data_len = 0;
 | 
											
										
											
												
													
														|  | @@ -9849,6 +9850,7 @@ struct {
 | 
											
												
													
														|  |                                  {NULL, 0, 0}};
 |  |                                  {NULL, 0, 0}};
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +/* return 0 for invalid uri, 1 for *, 2 for relative uri, 3 for absolute uri without port and 4 dor absolute uri with port */
 | 
											
												
													
														|  |  static int is_valid_uri(const char *uri)
 |  |  static int is_valid_uri(const char *uri)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	int i;
 |  |  	int i;
 | 
											
										
											
												
													
														|  | @@ -9865,7 +9867,7 @@ static int is_valid_uri(const char *uri)
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  	if (uri[0] == '/') {
 |  |  	if (uri[0] == '/') {
 | 
											
												
													
														|  |  		/* relative uri */
 |  |  		/* relative uri */
 | 
											
												
													
														|  | -		return 1;
 |  | 
 | 
											
												
													
														|  | 
 |  | +		return 2;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	/* it could be an absolute uri */
 |  |  	/* it could be an absolute uri */
 | 
											
										
											
												
													
														|  | @@ -9884,7 +9886,7 @@ static int is_valid_uri(const char *uri)
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  |  			portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
 |  |  			portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
 | 
											
												
													
														|  |  			if (!portbegin) {
 |  |  			if (!portbegin) {
 | 
											
												
													
														|  | -				return 1;
 |  | 
 | 
											
												
													
														|  | 
 |  | +				return 3;
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  			port = strtoul(portbegin + 1, &portend, 10);
 |  |  			port = strtoul(portbegin + 1, &portend, 10);
 | 
											
										
											
												
													
														|  | @@ -9892,7 +9894,7 @@ static int is_valid_uri(const char *uri)
 | 
											
												
													
														|  |  				return 0;
 |  |  				return 0;
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -			return 1;
 |  | 
 | 
											
												
													
														|  | 
 |  | +			return 4;
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -9900,8 +9902,10 @@ static int is_valid_uri(const char *uri)
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -static int is_absolute_uri_at_current_server(const char *uri,
 |  | 
 | 
											
												
													
														|  | -                                             const struct mg_connection *conn)
 |  | 
 | 
											
												
													
														|  | 
 |  | +/* Return NULL or the relative uri at the current server */
 | 
											
												
													
														|  | 
 |  | +static const char *
 | 
											
												
													
														|  | 
 |  | +is_absolute_uri_at_current_server(const char *uri,
 | 
											
												
													
														|  | 
 |  | +                                  const struct mg_connection *conn)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	const char *domain;
 |  |  	const char *domain;
 | 
											
												
													
														|  |  	size_t domain_len;
 |  |  	size_t domain_len;
 | 
											
										
											
												
													
														|  | @@ -9937,6 +9941,7 @@ static int is_absolute_uri_at_current_server(const char *uri,
 | 
											
												
													
														|  |  					return 0;
 |  |  					return 0;
 | 
											
												
													
														|  |  				}
 |  |  				}
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  | 
 |  | +			/* protocol found, port set */
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -9947,11 +9952,17 @@ static int is_absolute_uri_at_current_server(const char *uri,
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  #if defined(USE_IPV6)
 |  |  #if defined(USE_IPV6)
 | 
											
												
													
														|  |  	if (conn->client.lsa.sa.sa_family == AF_INET6) {
 |  |  	if (conn->client.lsa.sa.sa_family == AF_INET6) {
 | 
											
												
													
														|  | -		return (conn->client.lsa.sin6.sin6_port == port);
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | 
 |  | +		if (conn->client.lsa.sin6.sin6_port != port) {
 | 
											
												
													
														|  | 
 |  | +			return 0;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +	} else
 | 
											
												
													
														|  |  #endif
 |  |  #endif
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	return (conn->client.lsa.sin.sin_port == port);
 |  | 
 | 
											
												
													
														|  | 
 |  | +	{
 | 
											
												
													
														|  | 
 |  | +		if (conn->client.lsa.sin.sin_port == port) {
 | 
											
												
													
														|  | 
 |  | +			return 0;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +	}
 | 
											
												
													
														|  | 
 |  | +	return hostend;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -10299,13 +10310,15 @@ mg_connect_websocket_client(const char *host,
 | 
											
												
													
														|  |  	return conn;
 |  |  	return conn;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  static void process_new_connection(struct mg_connection *conn)
 |  |  static void process_new_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	if (conn && conn->ctx) {
 |  |  	if (conn && conn->ctx) {
 | 
											
												
													
														|  |  		struct mg_request_info *ri = &conn->request_info;
 |  |  		struct mg_request_info *ri = &conn->request_info;
 | 
											
												
													
														|  |  		int keep_alive_enabled, keep_alive, discard_len;
 |  |  		int keep_alive_enabled, keep_alive, discard_len;
 | 
											
												
													
														|  |  		char ebuf[100];
 |  |  		char ebuf[100];
 | 
											
												
													
														|  | -		int reqerr;
 |  | 
 | 
											
												
													
														|  | 
 |  | +		const char *hostend;
 | 
											
												
													
														|  | 
 |  | +		int reqerr, uri_type;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  		keep_alive_enabled =
 |  |  		keep_alive_enabled =
 | 
											
												
													
														|  |  		    !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
 |  |  		    !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
 | 
											
										
											
												
													
														|  | @@ -10322,7 +10335,7 @@ static void process_new_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |  					/*assert(ebuf[0] != '\0');*/
 |  |  					/*assert(ebuf[0] != '\0');*/
 | 
											
												
													
														|  |  					send_http_error(conn, reqerr, "%s", ebuf);
 |  |  					send_http_error(conn, reqerr, "%s", ebuf);
 | 
											
												
													
														|  |  				}
 |  |  				}
 | 
											
												
													
														|  | -			} else if (!is_valid_uri(conn->request_info.uri)) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +			} else if ((uri_type = is_valid_uri(conn->request_info.uri)) == 0) {
 | 
											
												
													
														|  |  				mg_snprintf(conn,
 |  |  				mg_snprintf(conn,
 | 
											
												
													
														|  |  				            NULL, /* No truncation check for ebuf */
 |  |  				            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  |  				            ebuf,
 |  |  				            ebuf,
 | 
											
										
											
												
													
														|  | @@ -10341,6 +10354,36 @@ static void process_new_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |  				send_http_error(conn, 505, "%s", ebuf);
 |  |  				send_http_error(conn, 505, "%s", ebuf);
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +			switch (uri_type) {
 | 
											
												
													
														|  | 
 |  | +			case 1:
 | 
											
												
													
														|  | 
 |  | +				/* Asterisk */
 | 
											
												
													
														|  | 
 |  | +				conn->request_info.rel_uri = NULL;
 | 
											
												
													
														|  | 
 |  | +				break;
 | 
											
												
													
														|  | 
 |  | +			case 2:
 | 
											
												
													
														|  | 
 |  | +				/* relative uri */
 | 
											
												
													
														|  | 
 |  | +				conn->request_info.rel_uri = conn->request_info.uri;
 | 
											
												
													
														|  | 
 |  | +				break;
 | 
											
												
													
														|  | 
 |  | +			case 3:
 | 
											
												
													
														|  | 
 |  | +				/* absolute uri */
 | 
											
												
													
														|  | 
 |  | +				hostend = is_absolute_uri_at_current_server(
 | 
											
												
													
														|  | 
 |  | +				    conn->request_info.uri, conn);
 | 
											
												
													
														|  | 
 |  | +				if (hostend) {
 | 
											
												
													
														|  | 
 |  | +					conn->request_info.rel_uri = hostend;
 | 
											
												
													
														|  | 
 |  | +				} else {
 | 
											
												
													
														|  | 
 |  | +					conn->request_info.rel_uri = NULL;
 | 
											
												
													
														|  | 
 |  | +				}
 | 
											
												
													
														|  | 
 |  | +				break;
 | 
											
												
													
														|  | 
 |  | +			default:
 | 
											
												
													
														|  | 
 |  | +				mg_snprintf(conn,
 | 
											
												
													
														|  | 
 |  | +				            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | 
 |  | +				            ebuf,
 | 
											
												
													
														|  | 
 |  | +				            sizeof(ebuf),
 | 
											
												
													
														|  | 
 |  | +				            "Invalid URI: [%s]",
 | 
											
												
													
														|  | 
 |  | +				            ri->uri);
 | 
											
												
													
														|  | 
 |  | +				send_http_error(conn, 400, "%s", ebuf);
 | 
											
												
													
														|  | 
 |  | +				break;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  			if (ebuf[0] == '\0') {
 |  |  			if (ebuf[0] == '\0') {
 | 
											
												
													
														|  |  				handle_request(conn);
 |  |  				handle_request(conn);
 | 
											
												
													
														|  |  				if (conn->ctx->callbacks.end_request != NULL) {
 |  |  				if (conn->ctx->callbacks.end_request != NULL) {
 | 
											
										
											
												
													
														|  | @@ -10392,6 +10435,7 @@ static void process_new_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  /* Worker threads take accepted socket from the queue */
 |  |  /* Worker threads take accepted socket from the queue */
 | 
											
												
													
														|  |  static int consume_socket(struct mg_context *ctx, struct socket *sp)
 |  |  static int consume_socket(struct mg_context *ctx, struct socket *sp)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
										
											
												
													
														|  | @@ -10431,6 +10475,7 @@ static int consume_socket(struct mg_context *ctx, struct socket *sp)
 | 
											
												
													
														|  |  #undef QUEUE_SIZE
 |  |  #undef QUEUE_SIZE
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  static void *worker_thread_run(void *thread_func_param)
 |  |  static void *worker_thread_run(void *thread_func_param)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	struct mg_context *ctx = (struct mg_context *)thread_func_param;
 |  |  	struct mg_context *ctx = (struct mg_context *)thread_func_param;
 | 
											
										
											
												
													
														|  | @@ -10524,8 +10569,8 @@ static void *worker_thread_run(void *thread_func_param)
 | 
											
												
													
														|  |  	return NULL;
 |  |  	return NULL;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -/* Threads have different return types on Windows and Unix. */
 |  | 
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +/* Threads have different return types on Windows and Unix. */
 | 
											
												
													
														|  |  #ifdef _WIN32
 |  |  #ifdef _WIN32
 | 
											
												
													
														|  |  static unsigned __stdcall worker_thread(void *thread_func_param)
 |  |  static unsigned __stdcall worker_thread(void *thread_func_param)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
										
											
												
													
														|  | @@ -10540,6 +10585,7 @@ static void *worker_thread(void *thread_func_param)
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  #endif /* _WIN32 */
 |  |  #endif /* _WIN32 */
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  /* Master thread adds accepted socket to a queue */
 |  |  /* Master thread adds accepted socket to a queue */
 | 
											
												
													
														|  |  static void produce_socket(struct mg_context *ctx, const struct socket *sp)
 |  |  static void produce_socket(struct mg_context *ctx, const struct socket *sp)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
										
											
												
													
														|  | @@ -10567,6 +10613,7 @@ static void produce_socket(struct mg_context *ctx, const struct socket *sp)
 | 
											
												
													
														|  |  #undef QUEUE_SIZE
 |  |  #undef QUEUE_SIZE
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  static void accept_new_connection(const struct socket *listener,
 |  |  static void accept_new_connection(const struct socket *listener,
 | 
											
												
													
														|  |                                    struct mg_context *ctx)
 |  |                                    struct mg_context *ctx)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
										
											
												
													
														|  | @@ -10636,6 +10683,7 @@ static void accept_new_connection(const struct socket *listener,
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  static void master_thread_run(void *thread_func_param)
 |  |  static void master_thread_run(void *thread_func_param)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	struct mg_context *ctx = (struct mg_context *)thread_func_param;
 |  |  	struct mg_context *ctx = (struct mg_context *)thread_func_param;
 |