diff --git a/src/WebSockets.cpp b/src/WebSockets.cpp index 4310e56..0b5736f 100644 --- a/src/WebSockets.cpp +++ b/src/WebSockets.cpp @@ -56,12 +56,15 @@ void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * rea /** * - * @param client WSclient_t * ptr to the client struct + * @param client WSclient_t * ptr to the client struct * @param opcode WSopcode_t * @param payload uint8_t * * @param length size_t + * @param mask bool add dummy mask to the frame (needed for web browser) + * @param fin bool can be used to send data in more then one frame (set fin on the last frame) + * @param headerToPayload bool set true if the payload has reserved 14 Byte at the beginning to dynamically add the Header (payload neet to be in RAM!) */ -void WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool mask, bool fin) { +void WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool mask, bool fin, bool headerToPayload) { if(!client->tcp.connected()) { DEBUG_WEBSOCKETS("[WS][%d][sendFrame] not Connected!?\n", client->num); @@ -74,49 +77,72 @@ void WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay } DEBUG_WEBSOCKETS("[WS][%d][sendFrame] ------- send massage frame -------\n", client->num); - DEBUG_WEBSOCKETS("[WS][%d][sendFrame] fin: %u opCode: %u mask: %u length: %u\n", client->num, fin, opcode, mask, length); + DEBUG_WEBSOCKETS("[WS][%d][sendFrame] fin: %u opCode: %u mask: %u length: %u headerToPayload: %u\n", client->num, fin, opcode, mask, length, headerToPayload); if(opcode == WSop_text) { - DEBUG_WEBSOCKETS("[WS][%d][sendFrame] text: %s\n", client->num, payload); + DEBUG_WEBSOCKETS("[WS][%d][sendFrame] text: %s\n", client->num, (payload + (headerToPayload ? 14 : 0))); } uint8_t maskKey[4] = { 0 }; - uint8_t buffer[16] = { 0 }; - uint8_t i = 0; + uint8_t buffer[14] = { 0 }; - //create header + uint8_t headerSize; + uint8_t * headerPtr; + + // calculate header Size + if(length < 126) { + headerSize = 2; + } else if(length < 0xFFFF) { + headerSize = 4; + } else { + headerSize = 10; + } + + if(mask) { + headerSize += 4; + } + + // set Header Pointer + if(headerToPayload) { + // calculate offset in payload + headerPtr = (payload + (14 - headerSize)); + } else { + headerPtr = &buffer[0]; + } + + // create header // byte 0 - buffer[i] = 0x00; + *headerPtr = 0x00; if(fin) { - buffer[i] |= bit(7); ///< set Fin + *headerPtr |= bit(7); ///< set Fin } - buffer[i++] |= opcode; ///< set opcode + *headerPtr |= opcode; ///< set opcode + headerPtr++; // byte 1 - buffer[i] = 0x00; + *headerPtr = 0x00; if(mask) { - buffer[i] |= bit(7); ///< set mask + *headerPtr |= bit(7); ///< set mask } if(length < 126) { - buffer[i++] |= length; - + *headerPtr |= length; headerPtr++; } else if(length < 0xFFFF) { - buffer[i++] |= 126; - buffer[i++] = ((length >> 8) & 0xFF); - buffer[i++] = (length & 0xFF); + *headerPtr |= 126; headerPtr++; + *headerPtr = ((length >> 8) & 0xFF); headerPtr++; + *headerPtr = (length & 0xFF); headerPtr++; } else { // normaly we never get here (to less memory) - buffer[i++] |= 127; - buffer[i++] = 0x00; - buffer[i++] = 0x00; - buffer[i++] = 0x00; - buffer[i++] = 0x00; - buffer[i++] = ((length >> 24) & 0xFF); - buffer[i++] = ((length >> 16) & 0xFF); - buffer[i++] = ((length >> 8) & 0xFF); - buffer[i++] = (length & 0xFF); + *headerPtr |= 127; headerPtr++; + *headerPtr = 0x00; headerPtr++; + *headerPtr = 0x00; headerPtr++; + *headerPtr = 0x00; headerPtr++; + *headerPtr = 0x00; headerPtr++; + *headerPtr = ((length >> 24) & 0xFF); headerPtr++; + *headerPtr = ((length >> 16) & 0xFF); headerPtr++; + *headerPtr = ((length >> 8) & 0xFF); headerPtr++; + *headerPtr = (length & 0xFF); headerPtr++; } if(mask) { @@ -124,23 +150,29 @@ void WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay for(uint8_t x = 0; x < sizeof(maskKey); x++) { // maskKey[x] = random(0xFF); maskKey[x] = 0x00; // fake xor (0x00 0x00 0x00 0x00) - buffer[i++] = maskKey[x]; + *headerPtr = maskKey[x]; headerPtr++; } - // todo encode XOR + // todo encode XOR (note: using payload not working for static content from flash) //for(size_t x = 0; x < length; x++) { // payload[x] = (payload[x] ^ maskKey[x % 4]); //} } - // send header - client->tcp.write(&buffer[0], i); + if(headerToPayload) { + // header has be added to payload + // payload is forced to reserved 14 Byte but we may not need all based on the length and mask settings + // offset in payload is calculatetd 14 - headerSize + client->tcp.write(&payload[(14 - headerSize)], (length + headerSize)); + } else { + // send header + client->tcp.write(&buffer[0], headerSize); - if(payload && length > 0) { - // send payload - client->tcp.write(&payload[0], length); + if(payload && length > 0) { + // send payload + client->tcp.write(&payload[0], length); + } } - } /** diff --git a/src/WebSockets.h b/src/WebSockets.h index 2ae5575..b52f135 100644 --- a/src/WebSockets.h +++ b/src/WebSockets.h @@ -106,7 +106,7 @@ class WebSockets { virtual void messageRecived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length); void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0); - void sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, bool mask = false, bool fin = true); + void sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, bool mask = false, bool fin = true, bool headerToPayload = false); void handleWebsocket(WSclient_t * client); diff --git a/src/WebSocketsClient.cpp b/src/WebSocketsClient.cpp index dc9e022..ef64448 100644 --- a/src/WebSocketsClient.cpp +++ b/src/WebSocketsClient.cpp @@ -103,13 +103,14 @@ void WebSocketsClient::onEvent(WebSocketClientEvent cbEvent) { * @param num uint8_t client id * @param payload uint8_t * * @param length size_t + * @param headerToPayload bool (see sendFrame for more details) */ -void WebSocketsClient::sendTXT(uint8_t * payload, size_t length) { +void WebSocketsClient::sendTXT(uint8_t * payload, size_t length, bool headerToPayload) { if(length == 0) { length = strlen((const char *) payload); } if(clientIsConnected(&_client)) { - sendFrame(&_client, WSop_text, payload, length, true); + sendFrame(&_client, WSop_text, payload, length, true, true, headerToPayload); } } @@ -117,8 +118,8 @@ void WebSocketsClient::sendTXT(const uint8_t * payload, size_t length) { sendTXT((uint8_t *) payload, length); } -void WebSocketsClient::sendTXT(char * payload, size_t length) { - sendTXT((uint8_t *) payload, length); +void WebSocketsClient::sendTXT(char * payload, size_t length, bool headerToPayload) { + sendTXT((uint8_t *) payload, length, headerToPayload); } void WebSocketsClient::sendTXT(const char * payload, size_t length) { @@ -134,10 +135,11 @@ void WebSocketsClient::sendTXT(String payload) { * @param num uint8_t client id * @param payload uint8_t * * @param length size_t + * @param headerToPayload bool (see sendFrame for more details) */ -void WebSocketsClient::sendBIN(uint8_t * payload, size_t length) { +void WebSocketsClient::sendBIN(uint8_t * payload, size_t length, bool headerToPayload) { if(clientIsConnected(&_client)) { - sendFrame(&_client, WSop_binary, payload, length, true); + sendFrame(&_client, WSop_binary, payload, length, true, true, headerToPayload); } } diff --git a/src/WebSocketsClient.h b/src/WebSocketsClient.h index 7fa716c..75b2567 100644 --- a/src/WebSocketsClient.h +++ b/src/WebSocketsClient.h @@ -54,13 +54,13 @@ class WebSocketsClient: private WebSockets { void onEvent(WebSocketClientEvent cbEvent); - void sendTXT(uint8_t * payload, size_t length = 0); + void sendTXT(uint8_t * payload, size_t length = 0, bool headerToPayload = false); void sendTXT(const uint8_t * payload, size_t length = 0); - void sendTXT(char * payload, size_t length = 0); + void sendTXT(char * payload, size_t length = 0, bool headerToPayload = false); void sendTXT(const char * payload, size_t length = 0); void sendTXT(String payload); - void sendBIN(uint8_t * payload, size_t length); + void sendBIN(uint8_t * payload, size_t length, bool headerToPayload = false); void sendBIN(const uint8_t * payload, size_t length); void disconnect(void); diff --git a/src/WebSocketsServer.cpp b/src/WebSocketsServer.cpp index 94a7c72..725c60a 100644 --- a/src/WebSocketsServer.cpp +++ b/src/WebSocketsServer.cpp @@ -85,8 +85,9 @@ void WebSocketsServer::onEvent(WebSocketServerEvent cbEvent) { * @param num uint8_t client id * @param payload uint8_t * * @param length size_t + * @param headerToPayload bool (see sendFrame for more details) */ -void WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length) { +void WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) { if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) { return; } @@ -95,7 +96,7 @@ void WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length) { } WSclient_t * client = &_clients[num]; if(clientIsConnected(client)) { - sendFrame(client, WSop_text, payload, length); + sendFrame(client, WSop_text, payload, length, false, true, headerToPayload); } } @@ -103,8 +104,8 @@ void WebSocketsServer::sendTXT(uint8_t num, const uint8_t * payload, size_t leng sendTXT(num, (uint8_t *) payload, length); } -void WebSocketsServer::sendTXT(uint8_t num, char * payload, size_t length) { - sendTXT(num, (uint8_t *) payload, length); +void WebSocketsServer::sendTXT(uint8_t num, char * payload, size_t length, bool headerToPayload) { + sendTXT(num, (uint8_t *) payload, length, headerToPayload); } void WebSocketsServer::sendTXT(uint8_t num, const char * payload, size_t length) { @@ -119,8 +120,9 @@ void WebSocketsServer::sendTXT(uint8_t num, String payload) { * send text data to client all * @param payload uint8_t * * @param length size_t + * @param headerToPayload bool (see sendFrame for more details) */ -void WebSocketsServer::broadcastTXT(uint8_t * payload, size_t length) { +void WebSocketsServer::broadcastTXT(uint8_t * payload, size_t length, bool headerToPayload) { WSclient_t * client; if(length == 0) { length = strlen((const char *) payload); @@ -129,7 +131,7 @@ void WebSocketsServer::broadcastTXT(uint8_t * payload, size_t length) { for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { client = &_clients[i]; if(clientIsConnected(client)) { - sendFrame(client, WSop_text, payload, length); + sendFrame(client, WSop_text, payload, length, false, true, headerToPayload); } #ifdef ESP8266 delay(0); @@ -141,8 +143,8 @@ void WebSocketsServer::broadcastTXT(const uint8_t * payload, size_t length) { broadcastTXT((uint8_t *) payload, length); } -void WebSocketsServer::broadcastTXT(char * payload, size_t length) { - broadcastTXT((uint8_t *) payload, length); +void WebSocketsServer::broadcastTXT(char * payload, size_t length, bool headerToPayload) { + broadcastTXT((uint8_t *) payload, length, headerToPayload); } void WebSocketsServer::broadcastTXT(const char * payload, size_t length) { @@ -158,14 +160,15 @@ void WebSocketsServer::broadcastTXT(String payload) { * @param num uint8_t client id * @param payload uint8_t * * @param length size_t + * @param headerToPayload bool (see sendFrame for more details) */ -void WebSocketsServer::sendBIN(uint8_t num, uint8_t * payload, size_t length) { +void WebSocketsServer::sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) { if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) { return; } WSclient_t * client = &_clients[num]; if(clientIsConnected(client)) { - sendFrame(client, WSop_binary, payload, length); + sendFrame(client, WSop_binary, payload, length, false, true, headerToPayload); } } @@ -177,13 +180,14 @@ void WebSocketsServer::sendBIN(uint8_t num, const uint8_t * payload, size_t leng * send binary data to client all * @param payload uint8_t * * @param length size_t + * @param headerToPayload bool (see sendFrame for more details) */ -void WebSocketsServer::broadcastBIN(uint8_t * payload, size_t length) { +void WebSocketsServer::broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload) { WSclient_t * client; for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { client = &_clients[i]; if(clientIsConnected(client)) { - sendFrame(client, WSop_binary, payload, length); + sendFrame(client, WSop_binary, payload, length, false, true, headerToPayload); } #ifdef ESP8266 delay(0); diff --git a/src/WebSocketsServer.h b/src/WebSocketsServer.h index 6ad6d54..5d21197 100644 --- a/src/WebSocketsServer.h +++ b/src/WebSocketsServer.h @@ -58,22 +58,22 @@ public: void onEvent(WebSocketServerEvent cbEvent); - void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0); + void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0, bool headerToPayload = false); void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0); - void sendTXT(uint8_t num, char * payload, size_t length = 0); + void sendTXT(uint8_t num, char * payload, size_t length = 0, bool headerToPayload = false); void sendTXT(uint8_t num, const char * payload, size_t length = 0); void sendTXT(uint8_t num, String payload); - void broadcastTXT(uint8_t * payload, size_t length = 0); + void broadcastTXT(uint8_t * payload, size_t length = 0, bool headerToPayload = false); void broadcastTXT(const uint8_t * payload, size_t length = 0); - void broadcastTXT(char * payload, size_t length = 0); + void broadcastTXT(char * payload, size_t length = 0, bool headerToPayload = false); void broadcastTXT(const char * payload, size_t length = 0); void broadcastTXT(String payload); - void sendBIN(uint8_t num, uint8_t * payload, size_t length); + void sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload = false); void sendBIN(uint8_t num, const uint8_t * payload, size_t length); - void broadcastBIN(uint8_t * payload, size_t length); + void broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload = false); void broadcastBIN(const uint8_t * payload, size_t length); void disconnect(void);