Merge branch 'bugfix/fix_ws_ping_receive' into 'master'

fix(websocket): Support handler deal with PING and CLOSE frame

Closes IDFGH-7209

See merge request espressif/esp-idf!18065
This commit is contained in:
Mahavir Jain
2022-06-13 17:23:38 +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

@@ -74,8 +74,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

@@ -143,6 +143,16 @@ def test_examples_protocol_https_wss_server(dut: Dut) -> None:
raise RuntimeError('Failed to receive the correct echo response') raise RuntimeError('Failed to receive the correct echo response')
logging.info('Correct echo response obtained from the wss server') logging.info('Correct echo response obtained from the wss server')
# Test for PING
logging.info('Testing for send PING')
ws.write(data=DATA, opcode=OPCODE_PING)
dut.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')
logging.info('Passed the test for PING')
# Test for keepalive # Test for keepalive
logging.info('Testing for keep alive (approx time = 20s)') logging.info('Testing for keep alive (approx time = 20s)')
start_time = time.time() start_time = time.time()