mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 13:09:38 +00:00 
			
		
		
		
	http_server: adds support for setting websocket subprotocol
Adds support for setting support subprotocol per websocket URI
This commit is contained in:
		| @@ -15,6 +15,7 @@ | ||||
|  | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <sys/random.h> | ||||
| #include <esp_log.h> | ||||
| #include <esp_err.h> | ||||
| @@ -44,7 +45,50 @@ static const char *TAG="httpd_ws"; | ||||
|  */ | ||||
| static const char ws_magic_uuid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | ||||
|  | ||||
| esp_err_t httpd_ws_respond_server_handshake(httpd_req_t *req) | ||||
| /* Checks if any subprotocols from the comma seperated list matches the supported one | ||||
|  * | ||||
|  * Returns true if the response should contain a protocol field | ||||
| */ | ||||
|  | ||||
| /** | ||||
|  * @brief Checks if any subprotocols from the comma seperated list matches the supported one | ||||
|  * | ||||
|  * @param supported_subprotocol[in] The subprotocol supported by the URI | ||||
|  * @param subprotocol[in],  [in]: A comma seperate list of subprotocols requested | ||||
|  * @param buf_len Length of the buffer | ||||
|  * @return true: found a matching subprotocol | ||||
|  * @return false | ||||
|  */ | ||||
| static bool httpd_ws_get_response_subprotocol(const char *supported_subprotocol, char *subprotocol, size_t buf_len) | ||||
| { | ||||
|     /* Request didnt contain any subprotocols */ | ||||
|     if (strnlen(subprotocol, buf_len) == 0) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (supported_subprotocol == NULL) { | ||||
|         ESP_LOGW(TAG, "Sec-WebSocket-Protocol %s not supported, URI do not support any subprotocols", subprotocol); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /* Get first subprotocol from comma seperated list */ | ||||
|     char *rest = NULL; | ||||
|     char *s = strtok_r(subprotocol, ", ", &rest); | ||||
|     do { | ||||
|         if (strncmp(s, supported_subprotocol, sizeof(subprotocol)) == 0) { | ||||
|             ESP_LOGD(TAG, "Requested subprotocol supported: %s", s); | ||||
|             return true; | ||||
|         } | ||||
|     } while ((s = strtok_r(NULL, ", ", &rest)) != NULL); | ||||
|  | ||||
|     ESP_LOGW(TAG, "Sec-WebSocket-Protocol %s not supported, supported subprotocol is %s", subprotocol, supported_subprotocol); | ||||
|  | ||||
|     /* No matches */ | ||||
|     return false; | ||||
|  | ||||
| } | ||||
|  | ||||
| esp_err_t httpd_ws_respond_server_handshake(httpd_req_t *req, const char *supported_subprotocol) | ||||
| { | ||||
|     /* Probe if input parameters are valid or not */ | ||||
|     if (!req || !req->aux) { | ||||
| @@ -101,18 +145,56 @@ esp_err_t httpd_ws_respond_server_handshake(httpd_req_t *req) | ||||
|  | ||||
|     ESP_LOGD(TAG, LOG_FMT("Generated server key: %s"), server_key_encoded); | ||||
|  | ||||
|     char subprotocol[50] = { '\0' }; | ||||
|     if (httpd_req_get_hdr_value_str(req, "Sec-WebSocket-Protocol", subprotocol, sizeof(subprotocol) - 1) == ESP_ERR_HTTPD_RESULT_TRUNC) { | ||||
|         ESP_LOGW(TAG, "Sec-WebSocket-Protocol length exceeded buffer size of %d, was trunctated", sizeof(subprotocol)); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /* Prepare the Switching Protocol response */ | ||||
|     char tx_buf[192] = { '\0' }; | ||||
|     int fmt_len = snprintf(tx_buf, sizeof(tx_buf), | ||||
|                            "HTTP/1.1 101 Switching Protocols\r\n" | ||||
|                            "Upgrade: websocket\r\n" | ||||
|                            "Connection: Upgrade\r\n" | ||||
|                            "Sec-WebSocket-Accept: %s\r\n\r\n", server_key_encoded); | ||||
|                            "Sec-WebSocket-Accept: %s\r\n", server_key_encoded); | ||||
|  | ||||
|     if (fmt_len < 0 || fmt_len > sizeof(tx_buf)) { | ||||
|         ESP_LOGW(TAG, LOG_FMT("Failed to prepare Tx buffer")); | ||||
|         return ESP_FAIL; | ||||
|     } | ||||
|  | ||||
|     if ( httpd_ws_get_response_subprotocol(supported_subprotocol, subprotocol, sizeof(subprotocol))) { | ||||
|         ESP_LOGD(TAG, "subprotocol: %s", subprotocol); | ||||
|         int r = snprintf(tx_buf + fmt_len, sizeof(tx_buf) - fmt_len, "Sec-WebSocket-Protocol: %s\r\n", supported_subprotocol); | ||||
|         if (r <= 0) { | ||||
|             ESP_LOGE(TAG, "Error in response generation" | ||||
|                           "(snprintf of subprotocol returned %d, buffer size: %d", r, sizeof(tx_buf)); | ||||
|             return ESP_FAIL; | ||||
|         } | ||||
|  | ||||
|         fmt_len += r; | ||||
|  | ||||
|         if (fmt_len >= sizeof(tx_buf)) { | ||||
|             ESP_LOGE(TAG, "Error in response generation" | ||||
|                           "(snprintf of subprotocol returned %d, desired response len: %d, buffer size: %d", r, fmt_len, sizeof(tx_buf)); | ||||
|             return ESP_FAIL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     int r = snprintf(tx_buf + fmt_len, sizeof(tx_buf) - fmt_len, "\r\n"); | ||||
|     if (r <= 0) { | ||||
|         ESP_LOGE(TAG, "Error in response generation" | ||||
|                         "(snprintf of subprotocol returned %d, buffer size: %d", r, sizeof(tx_buf)); | ||||
|         return ESP_FAIL; | ||||
|     } | ||||
|     fmt_len += r; | ||||
|     if (fmt_len >= sizeof(tx_buf)) { | ||||
|         ESP_LOGE(TAG, "Error in response generation" | ||||
|                        "(snprintf of header terminal returned %d, desired response len: %d, buffer size: %d", r, fmt_len, sizeof(tx_buf)); | ||||
|         return ESP_FAIL; | ||||
|     } | ||||
|  | ||||
|     /* Send off the response */ | ||||
|     if (httpd_send(req, tx_buf, fmt_len) < 0) { | ||||
|         ESP_LOGW(TAG, LOG_FMT("Failed to send the response")); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Marius Vikhammer
					Marius Vikhammer