Merge branch 'bugfix/fix_ws_ping_receive_v4.4' into 'release/v4.4'

fix(websocket): Support handler deal with PING and CLOSE frame (backport v4.4)

See merge request espressif/esp-idf!18529
This commit is contained in:
Mahavir Jain
2022-06-17 14:11:39 +08:00
3 changed files with 68 additions and 38 deletions

View File

@@ -445,6 +445,12 @@ esp_err_t httpd_ws_get_frame_type(httpd_req_t *req)
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
struct sock_db *sd = aux->sd;
if (sd == NULL) {
ESP_LOGW(TAG, LOG_FMT("Invalid sd pointer"));
return ESP_ERR_INVALID_ARG;
}
/* Read the first byte from the frame to get the FIN flag and Opcode */ /* Read the first byte from the frame to get the FIN flag and Opcode */
/* Please refer to RFC6455 Section 5.2 for more details */ /* Please refer to RFC6455 Section 5.2 for more details */
uint8_t first_byte = 0; uint8_t first_byte = 0;
@@ -463,8 +469,12 @@ esp_err_t httpd_ws_get_frame_type(httpd_req_t *req)
aux->ws_final = (first_byte & HTTPD_WS_FIN_BIT) != 0; aux->ws_final = (first_byte & HTTPD_WS_FIN_BIT) != 0;
aux->ws_type = (first_byte & HTTPD_WS_OPCODE_BITS); aux->ws_type = (first_byte & HTTPD_WS_OPCODE_BITS);
/* If userspace requests control frames, do not deal with the control frames */
if (!sd->ws_control_frames) {
ESP_LOGD(TAG, LOG_FMT("Handler not requests control frames"));
/* Reply to PING. For PONG and CLOSE, it will be handled elsewhere. */ /* Reply to PING. For PONG and CLOSE, it will be handled elsewhere. */
if(aux->ws_type == HTTPD_WS_TYPE_PING) { if (aux->ws_type == HTTPD_WS_TYPE_PING) {
ESP_LOGD(TAG, LOG_FMT("Got a WS PING frame, Replying PONG...")); ESP_LOGD(TAG, LOG_FMT("Got a WS PING frame, Replying PONG..."));
/* Read the rest of the PING frame, for PONG to reply back. */ /* Read the rest of the PING frame, for PONG to reply back. */
@@ -474,7 +484,7 @@ esp_err_t httpd_ws_get_frame_type(httpd_req_t *req)
memset(&frame, 0, sizeof(httpd_ws_frame_t)); memset(&frame, 0, sizeof(httpd_ws_frame_t));
frame.payload = frame_buf; frame.payload = frame_buf;
if(httpd_ws_recv_frame(req, &frame, 126) != ESP_OK) { if (httpd_ws_recv_frame(req, &frame, 126) != ESP_OK) {
ESP_LOGD(TAG, LOG_FMT("Cannot receive the full PING frame")); ESP_LOGD(TAG, LOG_FMT("Cannot receive the full PING frame"));
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
} }
@@ -502,7 +512,7 @@ esp_err_t httpd_ws_get_frame_type(httpd_req_t *req)
frame.payload = NULL; frame.payload = NULL;
return httpd_ws_send_frame(req, &frame); return httpd_ws_send_frame(req, &frame);
} }
}
return ESP_OK; return ESP_OK;
} }

View File

@@ -73,8 +73,18 @@ static esp_err_t ws_handler(httpd_req_t *req)
httpd_req_to_sockfd(req)); httpd_req_to_sockfd(req));
// If it was a TEXT message, just echo it back // If it was a TEXT message, just echo it back
} else if (ws_pkt.type == HTTPD_WS_TYPE_TEXT) { } else if (ws_pkt.type == HTTPD_WS_TYPE_TEXT || ws_pkt.type == HTTPD_WS_TYPE_PING || ws_pkt.type == HTTPD_WS_TYPE_CLOSE) {
if (ws_pkt.type == HTTPD_WS_TYPE_TEXT) {
ESP_LOGI(TAG, "Received packet with message: %s", ws_pkt.payload); ESP_LOGI(TAG, "Received packet with message: %s", ws_pkt.payload);
} else if (ws_pkt.type == HTTPD_WS_TYPE_PING) {
// Response PONG packet to peer
ESP_LOGI(TAG, "Got a WS PING frame, Replying PONG");
ws_pkt.type = HTTPD_WS_TYPE_PONG;
} else if (ws_pkt.type == HTTPD_WS_TYPE_CLOSE) {
// Response CLOSE packet with no payload to peer
ws_pkt.len = 0;
ws_pkt.payload = NULL;
}
ret = httpd_ws_send_frame(req, &ws_pkt); ret = httpd_ws_send_frame(req, &ws_pkt);
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGE(TAG, "httpd_ws_send_frame failed with %d", ret); ESP_LOGE(TAG, "httpd_ws_send_frame failed with %d", ret);

View File

@@ -155,6 +155,16 @@ def test_examples_protocol_https_wss_server(env, extra_data): # type: (tiny_tes
raise RuntimeError('Failed to receive the correct echo response') raise RuntimeError('Failed to receive the correct echo response')
Utility.console_log('Correct echo response obtained from the wss server') Utility.console_log('Correct echo response obtained from the wss server')
# Test for PING
Utility.console_log('Testing for send PING')
ws.write(data=DATA, opcode=OPCODE_PING)
dut1.expect('Got a WS PING frame, Replying PONG')
opcode, data = ws.read()
data = data.decode('UTF-8')
if data != DATA or opcode != OPCODE_PONG:
raise RuntimeError('Failed to receive the PONG response')
Utility.console_log('Passed the test for PING')
# Test for keepalive # Test for keepalive
Utility.console_log('Testing for keep alive (approx time = 20s)') Utility.console_log('Testing for keep alive (approx time = 20s)')
start_time = time.time() start_time = time.time()