|  | @@ -1515,6 +1515,9 @@ struct mg_handler_info {
 | 
											
												
													
														|  |  	mg_websocket_data_handler data_handler;
 |  |  	mg_websocket_data_handler data_handler;
 | 
											
												
													
														|  |  	mg_websocket_close_handler close_handler;
 |  |  	mg_websocket_close_handler close_handler;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +	/* accepted subprotocols for ws/wss requests. */
 | 
											
												
													
														|  | 
 |  | +	struct mg_websocket_subprotocols *subprotocols;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  	/* Handler for authorization requests */
 |  |  	/* Handler for authorization requests */
 | 
											
												
													
														|  |  	mg_authorization_handler auth_handler;
 |  |  	mg_authorization_handler auth_handler;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -9367,7 +9370,6 @@ static int
 | 
											
												
													
														|  |  send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
 |  |  send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
 |  |  	static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
 | 
											
												
													
														|  | -	const char *protocol = NULL;
 |  | 
 | 
											
												
													
														|  |  	char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
 |  |  	char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
 | 
											
												
													
														|  |  	SHA1_CTX sha_ctx;
 |  |  	SHA1_CTX sha_ctx;
 | 
											
												
													
														|  |  	int truncated;
 |  |  	int truncated;
 | 
											
										
											
												
													
														|  | @@ -9389,33 +9391,8 @@ send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
 | 
											
												
													
														|  |  	          "Connection: Upgrade\r\n"
 |  |  	          "Connection: Upgrade\r\n"
 | 
											
												
													
														|  |  	          "Sec-WebSocket-Accept: %s\r\n",
 |  |  	          "Sec-WebSocket-Accept: %s\r\n",
 | 
											
												
													
														|  |  	          b64_sha);
 |  |  	          b64_sha);
 | 
											
												
													
														|  | -	protocol = mg_get_header(conn, "Sec-WebSocket-Protocol");
 |  | 
 | 
											
												
													
														|  | -	if (protocol) {
 |  | 
 | 
											
												
													
														|  | -		/* The protocol is a comma seperated list of names. */
 |  | 
 | 
											
												
													
														|  | -		/* The server must only return one value from this list. */
 |  | 
 | 
											
												
													
														|  | -		/* First check if it is a list or just a single value. */
 |  | 
 | 
											
												
													
														|  | -		const char *sep = strchr(protocol, ',');
 |  | 
 | 
											
												
													
														|  | -		if (sep == NULL) {
 |  | 
 | 
											
												
													
														|  | -			/* Just a single protocol -> accept it. */
 |  | 
 | 
											
												
													
														|  | -			mg_printf(conn, "Sec-WebSocket-Protocol: %s\r\n\r\n", protocol);
 |  | 
 | 
											
												
													
														|  | -		} else {
 |  | 
 | 
											
												
													
														|  | -			/* Multiple protocols -> accept the first one. */
 |  | 
 | 
											
												
													
														|  | -			/* This is just a quick fix if the client offers multiple
 |  | 
 | 
											
												
													
														|  | -			 * protocols. In order to get the behavior intended by
 |  | 
 | 
											
												
													
														|  | -			 * RFC 6455 (https://tools.ietf.org/rfc/rfc6455.txt), it is
 |  | 
 | 
											
												
													
														|  | -			 * required to have a list of websocket subprotocols accepted
 |  | 
 | 
											
												
													
														|  | -			 * by the server. Then the server must either select a subprotocol
 |  | 
 | 
											
												
													
														|  | -			 * supported by client and server, or the server has to abort the
 |  | 
 | 
											
												
													
														|  | -			 * handshake by not returning a Sec-Websocket-Protocol header if
 |  | 
 | 
											
												
													
														|  | -			 * no subprotocol is acceptable.
 |  | 
 | 
											
												
													
														|  | -			 */
 |  | 
 | 
											
												
													
														|  | -			mg_printf(conn,
 |  | 
 | 
											
												
													
														|  | -			          "Sec-WebSocket-Protocol: %.*s\r\n\r\n",
 |  | 
 | 
											
												
													
														|  | -			          (int)(sep - protocol),
 |  | 
 | 
											
												
													
														|  | -			          protocol);
 |  | 
 | 
											
												
													
														|  | -		}
 |  | 
 | 
											
												
													
														|  | -		/* TODO: Real subprotocol negotiation instead of just taking the first
 |  | 
 | 
											
												
													
														|  | -		 * websocket subprotocol suggested by the client. */
 |  | 
 | 
											
												
													
														|  | 
 |  | +	if (conn->request_info.acceptedSubprotocol) {
 | 
											
												
													
														|  | 
 |  | +		mg_printf(conn, "Sec-WebSocket-Protocol: %s\r\n\r\n", conn->request_info.acceptedSubprotocol);
 | 
											
												
													
														|  |  	} else {
 |  |  	} else {
 | 
											
												
													
														|  |  		mg_printf(conn, "%s", "\r\n");
 |  |  		mg_printf(conn, "%s", "\r\n");
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
										
											
												
													
														|  | @@ -9732,6 +9709,7 @@ static void
 | 
											
												
													
														|  |  handle_websocket_request(struct mg_connection *conn,
 |  |  handle_websocket_request(struct mg_connection *conn,
 | 
											
												
													
														|  |                           const char *path,
 |  |                           const char *path,
 | 
											
												
													
														|  |                           int is_callback_resource,
 |  |                           int is_callback_resource,
 | 
											
												
													
														|  | 
 |  | +						 struct mg_websocket_subprotocols * subprotocols,
 | 
											
												
													
														|  |                           mg_websocket_connect_handler ws_connect_handler,
 |  |                           mg_websocket_connect_handler ws_connect_handler,
 | 
											
												
													
														|  |                           mg_websocket_ready_handler ws_ready_handler,
 |  |                           mg_websocket_ready_handler ws_ready_handler,
 | 
											
												
													
														|  |                           mg_websocket_data_handler ws_data_handler,
 |  |                           mg_websocket_data_handler ws_data_handler,
 | 
											
										
											
												
													
														|  | @@ -9789,6 +9767,51 @@ handle_websocket_request(struct mg_connection *conn,
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	/* Step 2: If a callback is responsible, call it. */
 |  |  	/* Step 2: If a callback is responsible, call it. */
 | 
											
												
													
														|  |  	if (is_callback_resource) {
 |  |  	if (is_callback_resource) {
 | 
											
												
													
														|  | 
 |  | +		/* Step 2.1 check and select subprotocol */
 | 
											
												
													
														|  | 
 |  | +		const char *protocol = mg_get_header(conn, "Sec-WebSocket-Protocol");
 | 
											
												
													
														|  | 
 |  | +		if(protocol && subprotocols) {
 | 
											
												
													
														|  | 
 |  | +			int len, idx;
 | 
											
												
													
														|  | 
 |  | +			const char *sep, *curSubProtocol, *acceptedSubProtocol = NULL;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +			/* look for matching subprotocol */
 | 
											
												
													
														|  | 
 |  | +			do {
 | 
											
												
													
														|  | 
 |  | +				sep = strchr(protocol, ',');
 | 
											
												
													
														|  | 
 |  | +				curSubProtocol = protocol;
 | 
											
												
													
														|  | 
 |  | +				len = sep ? (int) (sep - protocol) : strlen(protocol);
 | 
											
												
													
														|  | 
 |  | +				protocol = sep ? sep + 1 : NULL;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +				for(idx = 0; idx < subprotocols->nb_subprotocols; idx++) {
 | 
											
												
													
														|  | 
 |  | +					if(strlen(subprotocols->subprotocols[idx])==len
 | 
											
												
													
														|  | 
 |  | +							&& strncmp(curSubProtocol, subprotocols->subprotocols[idx], len)==0) {
 | 
											
												
													
														|  | 
 |  | +						acceptedSubProtocol = subprotocols->subprotocols[idx];
 | 
											
												
													
														|  | 
 |  | +						break;
 | 
											
												
													
														|  | 
 |  | +					}
 | 
											
												
													
														|  | 
 |  | +				}
 | 
											
												
													
														|  | 
 |  | +			} while(sep && !acceptedSubProtocol);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +			conn->request_info.acceptedSubprotocol = acceptedSubProtocol;
 | 
											
												
													
														|  | 
 |  | +		} else if (protocol) {
 | 
											
												
													
														|  | 
 |  | +			/* keep legacy behavior */
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +			/* The protocol is a comma seperated list of names. */
 | 
											
												
													
														|  | 
 |  | +			/* The server must only return one value from this list. */
 | 
											
												
													
														|  | 
 |  | +			/* First check if it is a list or just a single value. */
 | 
											
												
													
														|  | 
 |  | +			const char *sep = strrchr(protocol, ',');
 | 
											
												
													
														|  | 
 |  | +			if (sep == NULL) {
 | 
											
												
													
														|  | 
 |  | +				/* Just a single protocol -> accept it. */
 | 
											
												
													
														|  | 
 |  | +				conn->request_info.acceptedSubprotocol = protocol;
 | 
											
												
													
														|  | 
 |  | +			} else {
 | 
											
												
													
														|  | 
 |  | +				/* Multiple protocols -> accept the last one. */
 | 
											
												
													
														|  | 
 |  | +				/* This is just a quick fix if the client offers multiple
 | 
											
												
													
														|  | 
 |  | +				 * protocols. The handler should have a list of accepted protocols on his own
 | 
											
												
													
														|  | 
 |  | +				 * and use it to select one protocol among those the client has offered.
 | 
											
												
													
														|  | 
 |  | +				 */
 | 
											
												
													
														|  | 
 |  | +				conn->request_info.acceptedSubprotocol = (sep+1);
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		if (ws_connect_handler != NULL
 |  |  		if (ws_connect_handler != NULL
 | 
											
												
													
														|  |  		    && ws_connect_handler(conn, cbData) != 0) {
 |  |  		    && ws_connect_handler(conn, cbData) != 0) {
 | 
											
												
													
														|  |  			/* C callback has returned non-zero, do not proceed with
 |  |  			/* C callback has returned non-zero, do not proceed with
 | 
											
										
											
												
													
														|  | @@ -10150,6 +10173,7 @@ mg_set_handler_type(struct mg_context *ctx,
 | 
											
												
													
														|  |                      int handler_type,
 |  |                      int handler_type,
 | 
											
												
													
														|  |                      int is_delete_request,
 |  |                      int is_delete_request,
 | 
											
												
													
														|  |                      mg_request_handler handler,
 |  |                      mg_request_handler handler,
 | 
											
												
													
														|  | 
 |  | +					struct mg_websocket_subprotocols *subprotocols,
 | 
											
												
													
														|  |                      mg_websocket_connect_handler connect_handler,
 |  |                      mg_websocket_connect_handler connect_handler,
 | 
											
												
													
														|  |                      mg_websocket_ready_handler ready_handler,
 |  |                      mg_websocket_ready_handler ready_handler,
 | 
											
												
													
														|  |                      mg_websocket_data_handler data_handler,
 |  |                      mg_websocket_data_handler data_handler,
 | 
											
										
											
												
													
														|  | @@ -10230,6 +10254,7 @@ mg_set_handler_type(struct mg_context *ctx,
 | 
											
												
													
														|  |  					if (handler_type == REQUEST_HANDLER) {
 |  |  					if (handler_type == REQUEST_HANDLER) {
 | 
											
												
													
														|  |  						tmp_rh->handler = handler;
 |  |  						tmp_rh->handler = handler;
 | 
											
												
													
														|  |  					} else if (handler_type == WEBSOCKET_HANDLER) {
 |  |  					} else if (handler_type == WEBSOCKET_HANDLER) {
 | 
											
												
													
														|  | 
 |  | +						tmp_rh->subprotocols = subprotocols;
 | 
											
												
													
														|  |  						tmp_rh->connect_handler = connect_handler;
 |  |  						tmp_rh->connect_handler = connect_handler;
 | 
											
												
													
														|  |  						tmp_rh->ready_handler = ready_handler;
 |  |  						tmp_rh->ready_handler = ready_handler;
 | 
											
												
													
														|  |  						tmp_rh->data_handler = data_handler;
 |  |  						tmp_rh->data_handler = data_handler;
 | 
											
										
											
												
													
														|  | @@ -10276,6 +10301,7 @@ mg_set_handler_type(struct mg_context *ctx,
 | 
											
												
													
														|  |  	if (handler_type == REQUEST_HANDLER) {
 |  |  	if (handler_type == REQUEST_HANDLER) {
 | 
											
												
													
														|  |  		tmp_rh->handler = handler;
 |  |  		tmp_rh->handler = handler;
 | 
											
												
													
														|  |  	} else if (handler_type == WEBSOCKET_HANDLER) {
 |  |  	} else if (handler_type == WEBSOCKET_HANDLER) {
 | 
											
												
													
														|  | 
 |  | +		tmp_rh->subprotocols = subprotocols;
 | 
											
												
													
														|  |  		tmp_rh->connect_handler = connect_handler;
 |  |  		tmp_rh->connect_handler = connect_handler;
 | 
											
												
													
														|  |  		tmp_rh->ready_handler = ready_handler;
 |  |  		tmp_rh->ready_handler = ready_handler;
 | 
											
												
													
														|  |  		tmp_rh->data_handler = data_handler;
 |  |  		tmp_rh->data_handler = data_handler;
 | 
											
										
											
												
													
														|  | @@ -10303,6 +10329,7 @@ mg_set_request_handler(struct mg_context *ctx,
 | 
											
												
													
														|  |  	                    REQUEST_HANDLER,
 |  |  	                    REQUEST_HANDLER,
 | 
											
												
													
														|  |  	                    handler == NULL,
 |  |  	                    handler == NULL,
 | 
											
												
													
														|  |  	                    handler,
 |  |  	                    handler,
 | 
											
												
													
														|  | 
 |  | +						NULL,
 | 
											
												
													
														|  |  	                    NULL,
 |  |  	                    NULL,
 | 
											
												
													
														|  |  	                    NULL,
 |  |  	                    NULL,
 | 
											
												
													
														|  |  	                    NULL,
 |  |  	                    NULL,
 | 
											
										
											
												
													
														|  | @@ -10315,6 +10342,27 @@ mg_set_request_handler(struct mg_context *ctx,
 | 
											
												
													
														|  |  void
 |  |  void
 | 
											
												
													
														|  |  mg_set_websocket_handler(struct mg_context *ctx,
 |  |  mg_set_websocket_handler(struct mg_context *ctx,
 | 
											
												
													
														|  |                           const char *uri,
 |  |                           const char *uri,
 | 
											
												
													
														|  | 
 |  | +						 mg_websocket_connect_handler connect_handler,
 | 
											
												
													
														|  | 
 |  | +                         mg_websocket_ready_handler ready_handler,
 | 
											
												
													
														|  | 
 |  | +                         mg_websocket_data_handler data_handler,
 | 
											
												
													
														|  | 
 |  | +                         mg_websocket_close_handler close_handler,
 | 
											
												
													
														|  | 
 |  | +                         void *cbdata)
 | 
											
												
													
														|  | 
 |  | +{
 | 
											
												
													
														|  | 
 |  | +	mg_set_websocket_handler_with_subprotocols(ctx,
 | 
											
												
													
														|  | 
 |  | +			uri,
 | 
											
												
													
														|  | 
 |  | +			NULL,
 | 
											
												
													
														|  | 
 |  | +			connect_handler,
 | 
											
												
													
														|  | 
 |  | +			ready_handler,
 | 
											
												
													
														|  | 
 |  | +			data_handler,
 | 
											
												
													
														|  | 
 |  | +			close_handler,
 | 
											
												
													
														|  | 
 |  | +			cbdata);
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +void
 | 
											
												
													
														|  | 
 |  | +mg_set_websocket_handler_with_subprotocols(struct mg_context *ctx,
 | 
											
												
													
														|  | 
 |  | +                         const char *uri,
 | 
											
												
													
														|  | 
 |  | +						 struct mg_websocket_subprotocols* subprotocols,
 | 
											
												
													
														|  |                           mg_websocket_connect_handler connect_handler,
 |  |                           mg_websocket_connect_handler connect_handler,
 | 
											
												
													
														|  |                           mg_websocket_ready_handler ready_handler,
 |  |                           mg_websocket_ready_handler ready_handler,
 | 
											
												
													
														|  |                           mg_websocket_data_handler data_handler,
 |  |                           mg_websocket_data_handler data_handler,
 | 
											
										
											
												
													
														|  | @@ -10329,6 +10377,7 @@ mg_set_websocket_handler(struct mg_context *ctx,
 | 
											
												
													
														|  |  	                    WEBSOCKET_HANDLER,
 |  |  	                    WEBSOCKET_HANDLER,
 | 
											
												
													
														|  |  	                    is_delete_request,
 |  |  	                    is_delete_request,
 | 
											
												
													
														|  |  	                    NULL,
 |  |  	                    NULL,
 | 
											
												
													
														|  | 
 |  | +						subprotocols,
 | 
											
												
													
														|  |  	                    connect_handler,
 |  |  	                    connect_handler,
 | 
											
												
													
														|  |  	                    ready_handler,
 |  |  	                    ready_handler,
 | 
											
												
													
														|  |  	                    data_handler,
 |  |  	                    data_handler,
 | 
											
										
											
												
													
														|  | @@ -10349,6 +10398,7 @@ mg_set_auth_handler(struct mg_context *ctx,
 | 
											
												
													
														|  |  	                    AUTH_HANDLER,
 |  |  	                    AUTH_HANDLER,
 | 
											
												
													
														|  |  	                    handler == NULL,
 |  |  	                    handler == NULL,
 | 
											
												
													
														|  |  	                    NULL,
 |  |  	                    NULL,
 | 
											
												
													
														|  | 
 |  | +						NULL,
 | 
											
												
													
														|  |  	                    NULL,
 |  |  	                    NULL,
 | 
											
												
													
														|  |  	                    NULL,
 |  |  	                    NULL,
 | 
											
												
													
														|  |  	                    NULL,
 |  |  	                    NULL,
 | 
											
										
											
												
													
														|  | @@ -10362,6 +10412,7 @@ static int
 | 
											
												
													
														|  |  get_request_handler(struct mg_connection *conn,
 |  |  get_request_handler(struct mg_connection *conn,
 | 
											
												
													
														|  |                      int handler_type,
 |  |                      int handler_type,
 | 
											
												
													
														|  |                      mg_request_handler *handler,
 |  |                      mg_request_handler *handler,
 | 
											
												
													
														|  | 
 |  | +					struct mg_websocket_subprotocols **subprotocols,
 | 
											
												
													
														|  |                      mg_websocket_connect_handler *connect_handler,
 |  |                      mg_websocket_connect_handler *connect_handler,
 | 
											
												
													
														|  |                      mg_websocket_ready_handler *ready_handler,
 |  |                      mg_websocket_ready_handler *ready_handler,
 | 
											
												
													
														|  |                      mg_websocket_data_handler *data_handler,
 |  |                      mg_websocket_data_handler *data_handler,
 | 
											
										
											
												
													
														|  | @@ -10387,6 +10438,7 @@ get_request_handler(struct mg_connection *conn,
 | 
											
												
													
														|  |  			if (tmp_rh->handler_type == handler_type) {
 |  |  			if (tmp_rh->handler_type == handler_type) {
 | 
											
												
													
														|  |  				if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
 |  |  				if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
 | 
											
												
													
														|  |  					if (handler_type == WEBSOCKET_HANDLER) {
 |  |  					if (handler_type == WEBSOCKET_HANDLER) {
 | 
											
												
													
														|  | 
 |  | +						*subprotocols = tmp_rh->subprotocols;
 | 
											
												
													
														|  |  						*connect_handler = tmp_rh->connect_handler;
 |  |  						*connect_handler = tmp_rh->connect_handler;
 | 
											
												
													
														|  |  						*ready_handler = tmp_rh->ready_handler;
 |  |  						*ready_handler = tmp_rh->ready_handler;
 | 
											
												
													
														|  |  						*data_handler = tmp_rh->data_handler;
 |  |  						*data_handler = tmp_rh->data_handler;
 | 
											
										
											
												
													
														|  | @@ -10410,6 +10462,7 @@ get_request_handler(struct mg_connection *conn,
 | 
											
												
													
														|  |  				if (tmp_rh->uri_len < urilen && uri[tmp_rh->uri_len] == '/'
 |  |  				if (tmp_rh->uri_len < urilen && uri[tmp_rh->uri_len] == '/'
 | 
											
												
													
														|  |  				    && memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
 |  |  				    && memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
 | 
											
												
													
														|  |  					if (handler_type == WEBSOCKET_HANDLER) {
 |  |  					if (handler_type == WEBSOCKET_HANDLER) {
 | 
											
												
													
														|  | 
 |  | +						*subprotocols = tmp_rh->subprotocols;
 | 
											
												
													
														|  |  						*connect_handler = tmp_rh->connect_handler;
 |  |  						*connect_handler = tmp_rh->connect_handler;
 | 
											
												
													
														|  |  						*ready_handler = tmp_rh->ready_handler;
 |  |  						*ready_handler = tmp_rh->ready_handler;
 | 
											
												
													
														|  |  						*data_handler = tmp_rh->data_handler;
 |  |  						*data_handler = tmp_rh->data_handler;
 | 
											
										
											
												
													
														|  | @@ -10432,6 +10485,7 @@ get_request_handler(struct mg_connection *conn,
 | 
											
												
													
														|  |  			if (tmp_rh->handler_type == handler_type) {
 |  |  			if (tmp_rh->handler_type == handler_type) {
 | 
											
												
													
														|  |  				if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
 |  |  				if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
 | 
											
												
													
														|  |  					if (handler_type == WEBSOCKET_HANDLER) {
 |  |  					if (handler_type == WEBSOCKET_HANDLER) {
 | 
											
												
													
														|  | 
 |  | +						*subprotocols = tmp_rh->subprotocols;
 | 
											
												
													
														|  |  						*connect_handler = tmp_rh->connect_handler;
 |  |  						*connect_handler = tmp_rh->connect_handler;
 | 
											
												
													
														|  |  						*ready_handler = tmp_rh->ready_handler;
 |  |  						*ready_handler = tmp_rh->ready_handler;
 | 
											
												
													
														|  |  						*data_handler = tmp_rh->data_handler;
 |  |  						*data_handler = tmp_rh->data_handler;
 | 
											
										
											
												
													
														|  | @@ -10511,6 +10565,7 @@ handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |  		int i;
 |  |  		int i;
 | 
											
												
													
														|  |  		struct mg_file file = STRUCT_FILE_INITIALIZER;
 |  |  		struct mg_file file = STRUCT_FILE_INITIALIZER;
 | 
											
												
													
														|  |  		mg_request_handler callback_handler = NULL;
 |  |  		mg_request_handler callback_handler = NULL;
 | 
											
												
													
														|  | 
 |  | +		struct mg_websocket_subprotocols *subprotocols;
 | 
											
												
													
														|  |  		mg_websocket_connect_handler ws_connect_handler = NULL;
 |  |  		mg_websocket_connect_handler ws_connect_handler = NULL;
 | 
											
												
													
														|  |  		mg_websocket_ready_handler ws_ready_handler = NULL;
 |  |  		mg_websocket_ready_handler ws_ready_handler = NULL;
 | 
											
												
													
														|  |  		mg_websocket_data_handler ws_data_handler = NULL;
 |  |  		mg_websocket_data_handler ws_data_handler = NULL;
 | 
											
										
											
												
													
														|  | @@ -10608,6 +10663,7 @@ handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |  		                        is_websocket_request ? WEBSOCKET_HANDLER
 |  |  		                        is_websocket_request ? WEBSOCKET_HANDLER
 | 
											
												
													
														|  |  		                                             : REQUEST_HANDLER,
 |  |  		                                             : REQUEST_HANDLER,
 | 
											
												
													
														|  |  		                        &callback_handler,
 |  |  		                        &callback_handler,
 | 
											
												
													
														|  | 
 |  | +								&subprotocols,
 | 
											
												
													
														|  |  		                        &ws_connect_handler,
 |  |  		                        &ws_connect_handler,
 | 
											
												
													
														|  |  		                        &ws_ready_handler,
 |  |  		                        &ws_ready_handler,
 | 
											
												
													
														|  |  		                        &ws_data_handler,
 |  |  		                        &ws_data_handler,
 | 
											
										
											
												
													
														|  | @@ -10643,6 +10699,7 @@ handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |  		                        AUTH_HANDLER,
 |  |  		                        AUTH_HANDLER,
 | 
											
												
													
														|  |  		                        NULL,
 |  |  		                        NULL,
 | 
											
												
													
														|  |  		                        NULL,
 |  |  		                        NULL,
 | 
											
												
													
														|  | 
 |  | +								NULL,
 | 
											
												
													
														|  |  		                        NULL,
 |  |  		                        NULL,
 | 
											
												
													
														|  |  		                        NULL,
 |  |  		                        NULL,
 | 
											
												
													
														|  |  		                        NULL,
 |  |  		                        NULL,
 | 
											
										
											
												
													
														|  | @@ -10732,6 +10789,7 @@ handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |  				handle_websocket_request(conn,
 |  |  				handle_websocket_request(conn,
 | 
											
												
													
														|  |  				                         path,
 |  |  				                         path,
 | 
											
												
													
														|  |  				                         is_callback_resource,
 |  |  				                         is_callback_resource,
 | 
											
												
													
														|  | 
 |  | +										 subprotocols,
 | 
											
												
													
														|  |  				                         ws_connect_handler,
 |  |  				                         ws_connect_handler,
 | 
											
												
													
														|  |  				                         ws_ready_handler,
 |  |  				                         ws_ready_handler,
 | 
											
												
													
														|  |  				                         ws_data_handler,
 |  |  				                         ws_data_handler,
 | 
											
										
											
												
													
														|  | @@ -10750,6 +10808,7 @@ handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |  				handle_websocket_request(conn,
 |  |  				handle_websocket_request(conn,
 | 
											
												
													
														|  |  				                         path,
 |  |  				                         path,
 | 
											
												
													
														|  |  				                         0 /* Lua Script */,
 |  |  				                         0 /* Lua Script */,
 | 
											
												
													
														|  | 
 |  | +										 NULL,
 | 
											
												
													
														|  |  				                         NULL,
 |  |  				                         NULL,
 | 
											
												
													
														|  |  				                         NULL,
 |  |  				                         NULL,
 | 
											
												
													
														|  |  				                         NULL,
 |  |  				                         NULL,
 | 
											
										
											
												
													
														|  | @@ -10761,6 +10820,7 @@ handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |  				    conn,
 |  |  				    conn,
 | 
											
												
													
														|  |  				    path,
 |  |  				    path,
 | 
											
												
													
														|  |  				    !is_script_resource /* could be deprecated global callback */,
 |  |  				    !is_script_resource /* could be deprecated global callback */,
 | 
											
												
													
														|  | 
 |  | +					NULL,
 | 
											
												
													
														|  |  				    deprecated_websocket_connect_wrapper,
 |  |  				    deprecated_websocket_connect_wrapper,
 | 
											
												
													
														|  |  				    deprecated_websocket_ready_wrapper,
 |  |  				    deprecated_websocket_ready_wrapper,
 | 
											
												
													
														|  |  				    deprecated_websocket_data_wrapper,
 |  |  				    deprecated_websocket_data_wrapper,
 |