Only if there is a chance that two tasks may try to operate (send WS packets) on the same sockfd at the same time.So i need to add queue work in the reception handler too ?
Websocket Async Messages
-
MicroController
- Posts: 2661
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: Websocket Async Messages
Re: Websocket Async Messages
Hi,
I returned from vacation and went to test the code with the new handler `.ws_pre_handshake_cb = get_clients_open_connection_handler` along with the "old" handler, and now it gives an error saying that the packet is not binary, "WebSocket Type Not Binary!!!".
The packet is being interpreted as continue and packet final false.
I haven't changed my mobile app.
I installed esp-idf v5.5.2
Note:
ESP-IDF version: v5.5.2
I returned from vacation and went to test the code with the new handler `.ws_pre_handshake_cb = get_clients_open_connection_handler` along with the "old" handler, and now it gives an error saying that the packet is not binary, "WebSocket Type Not Binary!!!".
The packet is being interpreted as continue and packet final false.
I haven't changed my mobile app.
I installed esp-idf v5.5.2
Code: Select all
.ws_pre_handshake_cb = get_clients_open_connection_handler
static esp_err_t get_clients_open_connection_handler(httpd_req_t* req)
{
char message[50];
int sockfd = httpd_req_to_sockfd(req);
ESP_LOGI(TAG, LOG_USER("New Connection Was Opened"));
ESP_LOGI(TAG, LOG_USER("New Connection Socket: %d\n"), sockfd);
bool code = ws_server_users_login(req, message, sizeof(message));
if (code)
{
add_ws_client_to_list(sockfd);
resp_Ws_Error_Message_Sync(req, message, command_error);
return ESP_OK;
}
else
{
ESP_LOGI(TAG, LOG_USER("Message: %s\n"), message);
resp_Ws_Error_Message_Sync(req, message, command_error);
ESP_LOGI(TAG, LOG_USER("SEND CLOSE FRAME"));
esp_err_t ret = send_close_frame(unexpected_condition_code, message, sockfd); // send_close_frame( normal_closure, NULL, sockfd );
ESP_LOGI(TAG, LOG_USER("Send Close Frame: %s\n"), esp_err_to_name(ret));
return ESP_FAIL;
}
}
Code: Select all
.handler = get_clients_message_handler
static esp_err_t get_clients_message_handler(httpd_req_t* req)
{
ESP_LOGI(TAG, LOG_USER("FUNCTION: %s"), __func__);
ESP_LOGI(TAG, LOG_USER("[%s]req->method = %d\n"), __func__, req->method);
httpd_ws_frame_t ws_pkt;
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
// Primeira chamada: apenas para ler o cabeçalho (tipo e tamanho)
esp_err_t ret = httpd_ws_recv_frame(req, &ws_pkt, 0);
if (ret != ESP_OK)
{
ESP_LOGW(TAG, "httpd_ws_recv_frame() falhou ao ler cabecalho: %s", esp_err_to_name(ret));
return ret;
}
#if enable_handle_ws_control_frames
// Se for controle com ZERO bytes, desvia direto para o handler
if (ws_pkt.len == 0 && (ws_pkt.type == HTTPD_WS_TYPE_PING || ws_pkt.type == HTTPD_WS_TYPE_PONG || ws_pkt.type == HTTPD_WS_TYPE_CLOSE))
{
return control_frames_handler(req, &ws_pkt);
}
#endif
if (ws_pkt.len > 125)
{
ESP_LOGW(TAG, "Mensagem muito grande: %d bytes. Rejeitando.", ws_pkt.len);
return ESP_OK;
}
// Aloca buffer na stack se houver payload
size_t buf_capacity = (ws_pkt.len > 0) ? ws_pkt.len : 1;
uint8_t buf[buf_capacity];
memset(buf, 0, buf_capacity);
ws_pkt.payload = buf;
// Segunda chamada: le o payload apenas se len > 0 (evita bug de fechar socket)
if (ws_pkt.len > 0)
{
ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len);
if (ret != ESP_OK)
{
#if webSocketDebug
ESP_LOGI(TAG, "Erro ao ler payload: %s", esp_err_to_name(ret));
#endif
return ret;
}
}
#if webSocketDebug
printFrame(&ws_pkt, "Received Client Frame", req);
#endif
#if enable_handle_ws_control_frames
// Se for controle com payload > 0, chama o handler apos a leitura
if (ws_pkt.type == HTTPD_WS_TYPE_PING || ws_pkt.type == HTTPD_WS_TYPE_PONG || ws_pkt.type == HTTPD_WS_TYPE_CLOSE)
{
return control_frames_handler(req, &ws_pkt);
}
#endif
// Tratamento de frames de dados (Binary/Text)
if (ws_pkt.type != HTTPD_WS_TYPE_BINARY)
{
int fd = httpd_req_to_sockfd(req);
ESP_LOGI(TAG, "Tipo nao binario: %d | Socket: %d", ws_pkt.type, fd);
resp_Ws_Error_Message_Sync(req, "WebSocket Type Not Binary!!!", command_error);
return ESP_FAIL;
}
// Processa comando se houver payload
if (ws_pkt.len > 0)
{
uint8_t comando = ws_pkt.payload[0];
if (comando < web_comm_t_array_size_t)
{
ret = func_pointer[comando](req, comando, &ws_pkt);
#if webSocketDebug
ESP_LOGI(TAG, "ret select_func = %d", ret);
#endif
return ESP_OK;
}
else
{
static const char msg[] = "Erro: Comando invalido = ";
static const size_t MAX_UINT8_DECIMAL_DIGITS = 3; // uint8_t max decimal convertido para texto.
static const size_t size = sizeof(msg) + MAX_UINT8_DECIMAL_DIGITS;
char err_msg[size];
snprintf(err_msg, size, "%s%hhu", msg, comando); // %hhu é o especificador exato para uint8_t
resp_Ws_Error_Message_Sync(req, err_msg, command_error);
return ESP_FAIL;
}
}
else
{
ESP_LOGW(TAG, "Frame binario vazio. Ignorando.");
}
return ESP_OK;
}
Note:
ESP-IDF version: v5.5.2
Re: Websocket Async Messages
I found the problem, in the function .handler = get_clients_message_handler, still need to check:
https://github.com/espressif/esp-idf/issues/18215
Code: Select all
if (req->method == HTTP_GET)
{
ESP_LOGI(TAG, "Handshake done, the new connection was opened");
ESP_LOGI(TAG, LOG_USER("New Connection Socket: %d\n"), httpd_req_to_sockfd(req));
return ESP_OK;
}
https://github.com/espressif/esp-idf/issues/18215
Who is online
Users browsing this forum: Baidu [Spider], Google [Bot] and 16 guests