try to send data in one TCP packed if possible,

add random mask support for short frames.
may helps with #34
This commit is contained in:
Markus Sattler
2015-12-28 02:52:55 +01:00
parent 848979ecf0
commit ff33056309
3 changed files with 58 additions and 17 deletions

View File

@ -17,7 +17,7 @@ a WebSocket Server and Client for Arduino based on RFC6455.
##### Limitations ##### ##### Limitations #####
- max input length is limited to the ram size and the ```WEBSOCKETS_MAX_DATA_SIZE``` define - max input length is limited to the ram size and the ```WEBSOCKETS_MAX_DATA_SIZE``` define
- max output length has no limit (the hardware is the limit) - max output length has no limit (the hardware is the limit)
- Client send masked frames always with mask 0x00000000 - Client send masked send big frames with mask 0x00000000 (on AVR all frames)
##### Supported Hardware ##### ##### Supported Hardware #####
- ESP8266 [Arduino for ESP8266](https://github.com/Links2004/Arduino) - ESP8266 [Arduino for ESP8266](https://github.com/Links2004/Arduino)

View File

@ -46,6 +46,8 @@ extern "C" {
#endif #endif
#define WEBSOCKETS_MAX_HEADER_SIZE (14)
/** /**
* *
* @param client WSclient_t * ptr to the client struct * @param client WSclient_t * ptr to the client struct
@ -97,11 +99,13 @@ void WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] text: %s\n", client->num, (payload + (headerToPayload ? 14 : 0))); DEBUG_WEBSOCKETS("[WS][%d][sendFrame] text: %s\n", client->num, (payload + (headerToPayload ? 14 : 0)));
} }
uint8_t maskKey[4] = { 0 }; uint8_t maskKey[4] = { 0x00, 0x00, 0x00, 0x00 };
uint8_t buffer[14] = { 0 }; uint8_t buffer[WEBSOCKETS_MAX_HEADER_SIZE] = { 0 };
uint8_t headerSize; uint8_t headerSize;
uint8_t * headerPtr; uint8_t * headerPtr;
uint8_t * payloadPtr = payload;
bool useInternBuffer = false;
// calculate header Size // calculate header Size
if(length < 126) { if(length < 126) {
@ -116,10 +120,26 @@ void WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
headerSize += 4; headerSize += 4;
} }
#ifdef WEBSOCKETS_USE_BIG_MEM
// only for ESP since AVR has less HEAP
// try to send data in one TCP package (only if some free Heap is there)
if(!headerToPayload && ((length > 0) && (length < 1400)) && (ESP.getFreeHeap() > 6000)) {
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] pack to one TCP package...\n", client->num);
uint8_t * dataPtr = (uint8_t *) malloc(length + WEBSOCKETS_MAX_HEADER_SIZE);
if(dataPtr) {
memcpy((dataPtr + WEBSOCKETS_MAX_HEADER_SIZE), payload, length);
headerToPayload = true;
useInternBuffer = true;
payloadPtr = dataPtr;
}
}
#endif
// set Header Pointer // set Header Pointer
if(headerToPayload) { if(headerToPayload) {
// calculate offset in payload // calculate offset in payload
headerPtr = (payload + (14 - headerSize)); headerPtr = (payloadPtr + (WEBSOCKETS_MAX_HEADER_SIZE - headerSize));
} else { } else {
headerPtr = &buffer[0]; headerPtr = &buffer[0];
} }
@ -160,33 +180,53 @@ void WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
} }
if(mask) { if(mask) {
// todo generate random mask key if(useInternBuffer) {
for(uint8_t x = 0; x < sizeof(maskKey); x++) { for(uint8_t x = 0; x < sizeof(maskKey); x++) {
// maskKey[x] = random(0xFF); maskKey[x] = random(0xFF);
maskKey[x] = 0x00; // fake xor (0x00 0x00 0x00 0x00) *headerPtr = maskKey[x]; headerPtr++;
*headerPtr = maskKey[x]; headerPtr++; }
}
// todo encode XOR (note: using payload not working for static content from flash) uint8_t * dataMaskPtr;
//for(size_t x = 0; x < length; x++) {
// payload[x] = (payload[x] ^ maskKey[x % 4]); if(headerToPayload) {
//} dataMaskPtr = (payloadPtr + WEBSOCKETS_MAX_HEADER_SIZE);
} else {
dataMaskPtr = payloadPtr;
}
for(size_t x = 0; x < length; x++) {
dataMaskPtr[x] = (dataMaskPtr[x] ^ maskKey[x % 4]);
}
} else {
*headerPtr = maskKey[0]; headerPtr++;
*headerPtr = maskKey[1]; headerPtr++;
*headerPtr = maskKey[2]; headerPtr++;
*headerPtr = maskKey[3]; headerPtr++;
}
} }
if(headerToPayload) { if(headerToPayload) {
// header has be added to payload // 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 // 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 // offset in payload is calculatetd 14 - headerSize
client->tcp->write(&payload[(14 - headerSize)], (length + headerSize)); client->tcp->write(&payloadPtr[(WEBSOCKETS_MAX_HEADER_SIZE - headerSize)], (length + headerSize));
} else { } else {
// send header // send header
client->tcp->write(&buffer[0], headerSize); client->tcp->write(&buffer[0], headerSize);
if(payload && length > 0) { if(payloadPtr && length > 0) {
// send payload // send payload
client->tcp->write(&payload[0], length); client->tcp->write(&payloadPtr[0], length);
} }
} }
#ifdef WEBSOCKETS_USE_BIG_MEM
if(useInternBuffer && payloadPtr) {
free(payloadPtr);
}
#endif
} }
/** /**

View File

@ -35,6 +35,7 @@
#ifdef ESP8266 #ifdef ESP8266
#define WEBSOCKETS_MAX_DATA_SIZE (15*1024) #define WEBSOCKETS_MAX_DATA_SIZE (15*1024)
#define WEBSOCKETS_USE_BIG_MEM
#else #else
//atmega328p has only 2KB ram! //atmega328p has only 2KB ram!
#define WEBSOCKETS_MAX_DATA_SIZE (1024) #define WEBSOCKETS_MAX_DATA_SIZE (1024)