diff --git a/src/WebSockets.h b/src/WebSockets.h index 4a892ca..91d95eb 100644 --- a/src/WebSockets.h +++ b/src/WebSockets.h @@ -215,6 +215,7 @@ typedef enum { WSC_NOT_CONNECTED, WSC_HEADER, + WSC_BODY, WSC_CONNECTED } WSclientsStatus_t; diff --git a/src/WebSocketsClient.cpp b/src/WebSocketsClient.cpp index c20e8e1..bd31268 100644 --- a/src/WebSocketsClient.cpp +++ b/src/WebSocketsClient.cpp @@ -505,7 +505,8 @@ void WebSocketsClient::clientDisconnect(WSclient_t * client) { client->cIsWebsocket = false; client->cSessionId = ""; - client->status = WSC_NOT_CONNECTED; + client->status = WSC_NOT_CONNECTED; + _lastConnectionFail = millis(); DEBUG_WEBSOCKETS("[WS-Client] client disconnected.\n"); if(event) { @@ -548,12 +549,13 @@ bool WebSocketsClient::clientIsConnected(WSclient_t * client) { * Handel incomming data from Client */ void WebSocketsClient::handleClientData(void) { - if(_client.status == WSC_HEADER && _lastHeaderSent + WEBSOCKETS_TCP_TIMEOUT < millis()) { + if((_client.status == WSC_HEADER || _client.status == WSC_BODY) && _lastHeaderSent + WEBSOCKETS_TCP_TIMEOUT < millis()) { DEBUG_WEBSOCKETS("[WS-Client][handleClientData] header response timeout.. disconnecting!\n"); clientDisconnect(&_client); WEBSOCKETS_YIELD(); return; } + int len = _client.tcp->available(); if(len > 0) { switch(_client.status) { @@ -561,6 +563,12 @@ void WebSocketsClient::handleClientData(void) { String headerLine = _client.tcp->readStringUntil('\n'); handleHeader(&_client, &headerLine); } break; + case WSC_BODY: { + char buf[256] = { 0 }; + _client.tcp->readBytes(&buf[0], std::min((size_t)len, sizeof(buf))); + String bodyLine = buf; + handleHeader(&_client, &bodyLine); + } break; case WSC_CONNECTED: WebSockets::handleWebsocket(&_client); break; @@ -672,6 +680,22 @@ void WebSocketsClient::sendHeader(WSclient_t * client) { void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) { headerLine->trim(); // remove \r + // this code handels the http body for Socket.IO V3 requests + if(headerLine->length() > 0 && client->isSocketIO && client->status == WSC_BODY && client->cSessionId.length() == 0) { + DEBUG_WEBSOCKETS("[WS-Client][handleHeader] socket.io json: %s\n", headerLine->c_str()); + String sid_begin = WEBSOCKETS_STRING("\"sid\":\""); + if(headerLine->indexOf(sid_begin) > -1) { + int start = headerLine->indexOf(sid_begin) + sid_begin.length(); + int end = headerLine->indexOf('"', start); + client->cSessionId = headerLine->substring(start, end); + DEBUG_WEBSOCKETS("[WS-Client][handleHeader] - cSessionId: %s\n", client->cSessionId.c_str()); + + // Trigger websocket connection code path + *headerLine = ""; + } + } + + // headle HTTP header if(headerLine->length() > 0) { DEBUG_WEBSOCKETS("[WS-Client][handleHeader] RX: %s\n", headerLine->c_str()); @@ -736,6 +760,14 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) { DEBUG_WEBSOCKETS("[WS-Client][handleHeader] - cVersion: %d\n", client->cVersion); DEBUG_WEBSOCKETS("[WS-Client][handleHeader] - cSessionId: %s\n", client->cSessionId.c_str()); + if(client->isSocketIO && client->cSessionId.length() == 0 && clientIsConnected(client)) { + DEBUG_WEBSOCKETS("[WS-Client][handleHeader] still missing cSessionId try socket.io V3\n"); + client->status = WSC_BODY; + return; + } else { + client->status = WSC_HEADER; + } + bool ok = (client->cIsUpgrade && client->cIsWebsocket); if(ok) { @@ -777,15 +809,18 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) { runCbEvent(WStype_CONNECTED, (uint8_t *)client->cUrl.c_str(), client->cUrl.length()); #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) - } else if(clientIsConnected(client) && client->isSocketIO && client->cSessionId.length() > 0) { - if(_client.tcp->available()) { - // read not needed data - DEBUG_WEBSOCKETS("[WS-Client][handleHeader] still data in buffer (%d), clean up.\n", _client.tcp->available()); - while(_client.tcp->available() > 0) { - _client.tcp->read(); + } else if(client->isSocketIO) { + if(client->cSessionId.length() > 0) { + DEBUG_WEBSOCKETS("[WS-Client][handleHeader] found cSessionId\n"); + if(clientIsConnected(client) && _client.tcp->available()) { + // read not needed data + DEBUG_WEBSOCKETS("[WS-Client][handleHeader] still data in buffer (%d), clean up.\n", _client.tcp->available()); + while(_client.tcp->available() > 0) { + _client.tcp->read(); + } } + sendHeader(client); } - sendHeader(client); #endif } else { DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");