we use the ESP32 with the ESP-IDF SDK to provide an access point for our application. The communication between the mobile device with the ESP32 is using websockets to exchange information. The ESP32 is about to accept only one WiFi client and one websocket connection at a time.
The websocket handler is FreeRTOS task as follows:
- static void _taskCallbackWsServer(void *pvParameters)
- {
- ( void ) pvParameters;
- //connection references
- ESP_LOGI(TAGSocket, "ws server start");
- struct netconn *conn;
- struct netconn *newconn;
- //set up new TCP listener
- conn = netconn_new(NETCONN_TCP);
- netconn_bind(conn, NULL, WS_PORT);
- netconn_listen(conn);
- //wait for connections
- while (netconn_accept(conn, &newconn) == ERR_OK)
- {
- _wsServerNetconnServe(newconn);
- }
- //close connection
- netconn_close(conn);
- netconn_delete(conn);
- }
- static void _wsServerNetconnServe(struct netconn *conn)
- {
- //Netbuf
- struct netbuf *inbuf;
- //message buffer
- char *buf;
- //pointer to buffer (multi purpose)
- char* p_buf;
- //Pointer to SHA1 input
- char* p_SHA1_Inp;
- //Pointer to SHA1 result
- char* p_SHA1_result;
- //multi purpose number buffer
- uint16_t i;
- //will point to payload (send and receive
- char* p_payload;
- //Frame header pointer
- WS_frame_header_t* p_frame_hdr;
- //allocate memory for SHA1 input
- p_SHA1_Inp = heap_caps_malloc(WS_CLIENT_KEY_L + sizeof(WS_sec_conKey),
- MALLOC_CAP_8BIT);
- //allocate memory for SHA1 result
- p_SHA1_result = heap_caps_malloc(SHA1_RES_L, MALLOC_CAP_8BIT);
- //Check if malloc suceeded
- if ((p_SHA1_Inp != NULL) && (p_SHA1_result != NULL))
- {
- //receive handshake request
- if (netconn_recv(conn, &inbuf) == ERR_OK)
- {
- WebSocket_receivedMessages++;
- //read buffer
- netbuf_data(inbuf, (void**) &buf, &i);
- //write static key into SHA1 Input
- for (i = 0; i < sizeof(WS_sec_conKey); i++)
- p_SHA1_Inp[i + WS_CLIENT_KEY_L] = WS_sec_conKey[i];
- //find Client Sec-WebSocket-Key:
- p_buf = strstr(buf, WS_sec_WS_keys);
- //check if needle "Sec-WebSocket-Key:" was found
- if (p_buf != NULL)
- {
- //get Client Key
- for (i = 0; i < WS_CLIENT_KEY_L; i++)
- p_SHA1_Inp[i] = *(p_buf + sizeof(WS_sec_WS_keys) + i);
- // calculate hash
- esp_sha(SHA1, (unsigned char*) p_SHA1_Inp, strlen(p_SHA1_Inp),
- (unsigned char*) p_SHA1_result);
- //hex to base64
- mbedtls_base64_encode((unsigned char*)0,0,(size_t*) &i,(unsigned char*) p_SHA1_result,
- SHA1_RES_L);
- size_t p_buf_len = i;
- p_buf = heap_caps_malloc(p_buf_len, MALLOC_CAP_8BIT);
- mbedtls_base64_encode((unsigned char*)p_buf,p_buf_len,(size_t*) &i,(unsigned char*) p_SHA1_result,
- SHA1_RES_L);
- i = p_buf_len;
- //free SHA1 input
- free(p_SHA1_Inp);
- //free SHA1 result
- free(p_SHA1_result);
- //allocate memory for handshake
- p_payload = heap_caps_malloc(
- sizeof(WS_srv_hs) + i - WS_SPRINTF_ARG_L,
- MALLOC_CAP_8BIT);
- //check if malloc suceeded
- if ( (p_payload != NULL) && (p_buf != NULL))
- {
- //prepare handshake
- sprintf(p_payload, WS_srv_hs, i - 1, p_buf);
- //send handshake
- WebSocket_sentMessages++;
- netconn_write(conn, p_payload, strlen(p_payload),
- NETCONN_COPY);
- //free base 64 encoded sec key
- free(p_buf);
- //free handshake memory
- free(p_payload);
- //set pointer to open WebSocket connection
- WS_conn = conn;
- _requestSetStatusOperation();
- //ESP_ERROR_CHECK(esp_timer_start_once(_packetTimeout_timer, 500000 ) );
- //Wait for new data
- while (netconn_recv(conn, &inbuf) == ERR_OK)
- {
- WebSocket_receivedMessages++;
- //read data from inbuf
- netbuf_data(inbuf, (void**) &buf, &i);
- //get pointer to header
- p_frame_hdr = (WS_frame_header_t*) buf;
- //check if clients wants to close the connection
- if (p_frame_hdr->opcode == WS_OP_CLS)
- break;
- //get payload length
- if (p_frame_hdr->payload_length <= WS_STD_LEN)
- {
- //get beginning of mask or payload
- p_buf = (char*) &buf[sizeof(WS_frame_header_t)];
- //check if content is masked
- if (p_frame_hdr->mask)
- {
- //allocate memory for decoded message
- p_payload = heap_caps_malloc( p_frame_hdr->payload_length + 1,
- MALLOC_CAP_8BIT);
- //check if malloc succeeded
- if (p_payload != NULL)
- {
- //decode playload
- for (i = 0; i < p_frame_hdr->payload_length; i++)
- {
- p_payload[i] = ( (p_buf + WS_MASK_L)[i] ^ p_buf[i % WS_MASK_L] );
- }
- //add 0 terminator
- p_payload[p_frame_hdr->payload_length] = 0;
- }
- }
- else
- {
- //content is not masked
- p_payload = p_buf;
- }
- //do stuff
- if ((p_payload != NULL) && (p_frame_hdr->opcode == WS_OP_TXT))
- {
- //prepare FreeRTOS message
- WebSocket_frame_t __ws_frame;
- __ws_frame.connection=conn;
- __ws_frame.frame_header=*p_frame_hdr;
- __ws_frame.payload_length=p_frame_hdr->payload_length;
- __ws_frame.payload=p_payload;
- //send message
- xQueueSendFromISR(_webSocketRxQueueHandle,&__ws_frame,0);
- }
- //free payload buffer (in this demo done by the receive task)
- // if (p_frame_hdr->mask && p_payload != NULL)
- // free(p_payload);
- }
- else //p_frame_hdr->payload_length<126
- {
- //get beginning of mask or payload
- p_buf = (char*) &buf[sizeof(WS_big_frame_header_t)];
- WS_big_frame_header_t* p_big_frame_hdr = (WS_big_frame_header_t*) buf;
- //check if content is masked
- size_t payload_length = (p_big_frame_hdr->ext_payload_lengthMSB << 8) | p_big_frame_hdr->ext_payload_lengthLSB;// zeile von unten
- if (p_frame_hdr->mask)
- {
- //allocate memory for decoded message
- p_payload = heap_caps_malloc( payload_length + 1,
- MALLOC_CAP_8BIT);
- //check if malloc succeeded
- if (p_payload != NULL)
- {
- //decode playload
- for (i = 0; i < payload_length; i++)
- {
- p_payload[i] = ( (p_buf + WS_MASK_L)[i] ^ p_buf[i % WS_MASK_L] );
- }
- //add 0 terminator
- p_payload[payload_length] = 0;
- }
- }
- else
- {
- //content is not masked
- p_payload = p_buf;
- }
- //do stuff
- if ((p_payload != NULL) && (p_frame_hdr->opcode == WS_OP_TXT))
- {
- //prepare FreeRTOS message
- WebSocket_frame_t __ws_frame;
- __ws_frame.connection = conn;
- __ws_frame.frame_header = *p_frame_hdr;
- __ws_frame.payload_length = payload_length;
- __ws_frame.payload = p_payload;
- // uint8_t ext_payload_lengthMSB: 8;
- // uint8_t ext_payload_lengthLSB: 8;
- //send message
- xQueueSendFromISR(_webSocketRxQueueHandle,&__ws_frame,0);
- }
- }
- //free input buffer
- netbuf_delete(inbuf);
- } //while(netconn_recv(conn, &inbuf)==ERR_OK)
- } //p_payload!=NULL
- } //check if needle "Sec-WebSocket-Key:" was found
- } //receive handshake
- } //p_SHA1_Inp!=NULL&p_SHA1_result!=NULL
- //release pointer to open WebSocket connection
- WS_conn = NULL;
- //delete buffer
- netbuf_delete(inbuf);
- // Close the connection
- netconn_close(conn);
- //Delete connection
- netconn_delete(conn);
- }
After about 30..40 connects and disconnects, the ESP32 is not handling new connection also a lot of free memory is still available.
Any idea how to get rid of it?
Any help is appregiated.
with kind regards
Michael