Skip to content

Commit ff33056

Browse files
committed
try to send data in one TCP packed if possible,
add random mask support for short frames. may helps with Links2004#34
1 parent 848979e commit ff33056

File tree

3 files changed

+58
-17
lines changed

3 files changed

+58
-17
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ a WebSocket Server and Client for Arduino based on RFC6455.
1717
##### Limitations #####
1818
- max input length is limited to the ram size and the ```WEBSOCKETS_MAX_DATA_SIZE``` define
1919
- max output length has no limit (the hardware is the limit)
20-
- Client send masked frames always with mask 0x00000000
20+
- Client send masked send big frames with mask 0x00000000 (on AVR all frames)
2121

2222
##### Supported Hardware #####
2323
- ESP8266 [Arduino for ESP8266](https://github.com/Links2004/Arduino)

src/WebSockets.cpp

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ extern "C" {
4646

4747
#endif
4848

49+
#define WEBSOCKETS_MAX_HEADER_SIZE (14)
50+
4951
/**
5052
*
5153
* @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
9799
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] text: %s\n", client->num, (payload + (headerToPayload ? 14 : 0)));
98100
}
99101

100-
uint8_t maskKey[4] = { 0 };
101-
uint8_t buffer[14] = { 0 };
102+
uint8_t maskKey[4] = { 0x00, 0x00, 0x00, 0x00 };
103+
uint8_t buffer[WEBSOCKETS_MAX_HEADER_SIZE] = { 0 };
102104

103105
uint8_t headerSize;
104106
uint8_t * headerPtr;
107+
uint8_t * payloadPtr = payload;
108+
bool useInternBuffer = false;
105109

106110
// calculate header Size
107111
if(length < 126) {
@@ -116,10 +120,26 @@ void WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
116120
headerSize += 4;
117121
}
118122

123+
124+
#ifdef WEBSOCKETS_USE_BIG_MEM
125+
// only for ESP since AVR has less HEAP
126+
// try to send data in one TCP package (only if some free Heap is there)
127+
if(!headerToPayload && ((length > 0) && (length < 1400)) && (ESP.getFreeHeap() > 6000)) {
128+
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] pack to one TCP package...\n", client->num);
129+
uint8_t * dataPtr = (uint8_t *) malloc(length + WEBSOCKETS_MAX_HEADER_SIZE);
130+
if(dataPtr) {
131+
memcpy((dataPtr + WEBSOCKETS_MAX_HEADER_SIZE), payload, length);
132+
headerToPayload = true;
133+
useInternBuffer = true;
134+
payloadPtr = dataPtr;
135+
}
136+
}
137+
#endif
138+
119139
// set Header Pointer
120140
if(headerToPayload) {
121141
// calculate offset in payload
122-
headerPtr = (payload + (14 - headerSize));
142+
headerPtr = (payloadPtr + (WEBSOCKETS_MAX_HEADER_SIZE - headerSize));
123143
} else {
124144
headerPtr = &buffer[0];
125145
}
@@ -160,33 +180,53 @@ void WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
160180
}
161181

162182
if(mask) {
163-
// todo generate random mask key
164-
for(uint8_t x = 0; x < sizeof(maskKey); x++) {
165-
// maskKey[x] = random(0xFF);
166-
maskKey[x] = 0x00; // fake xor (0x00 0x00 0x00 0x00)
167-
*headerPtr = maskKey[x]; headerPtr++;
168-
}
183+
if(useInternBuffer) {
184+
for(uint8_t x = 0; x < sizeof(maskKey); x++) {
185+
maskKey[x] = random(0xFF);
186+
*headerPtr = maskKey[x]; headerPtr++;
187+
}
169188

170-
// todo encode XOR (note: using payload not working for static content from flash)
171-
//for(size_t x = 0; x < length; x++) {
172-
// payload[x] = (payload[x] ^ maskKey[x % 4]);
173-
//}
189+
uint8_t * dataMaskPtr;
190+
191+
if(headerToPayload) {
192+
dataMaskPtr = (payloadPtr + WEBSOCKETS_MAX_HEADER_SIZE);
193+
} else {
194+
dataMaskPtr = payloadPtr;
195+
}
196+
197+
for(size_t x = 0; x < length; x++) {
198+
dataMaskPtr[x] = (dataMaskPtr[x] ^ maskKey[x % 4]);
199+
}
200+
201+
} else {
202+
*headerPtr = maskKey[0]; headerPtr++;
203+
*headerPtr = maskKey[1]; headerPtr++;
204+
*headerPtr = maskKey[2]; headerPtr++;
205+
*headerPtr = maskKey[3]; headerPtr++;
206+
}
174207
}
175208

176209
if(headerToPayload) {
177210
// header has be added to payload
178211
// payload is forced to reserved 14 Byte but we may not need all based on the length and mask settings
179212
// offset in payload is calculatetd 14 - headerSize
180-
client->tcp->write(&payload[(14 - headerSize)], (length + headerSize));
213+
client->tcp->write(&payloadPtr[(WEBSOCKETS_MAX_HEADER_SIZE - headerSize)], (length + headerSize));
181214
} else {
182215
// send header
183216
client->tcp->write(&buffer[0], headerSize);
184217

185-
if(payload && length > 0) {
218+
if(payloadPtr && length > 0) {
186219
// send payload
187-
client->tcp->write(&payload[0], length);
220+
client->tcp->write(&payloadPtr[0], length);
188221
}
189222
}
223+
224+
#ifdef WEBSOCKETS_USE_BIG_MEM
225+
if(useInternBuffer && payloadPtr) {
226+
free(payloadPtr);
227+
}
228+
#endif
229+
190230
}
191231

192232
/**

src/WebSockets.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
#ifdef ESP8266
3737
#define WEBSOCKETS_MAX_DATA_SIZE (15*1024)
38+
#define WEBSOCKETS_USE_BIG_MEM
3839
#else
3940
//atmega328p has only 2KB ram!
4041
#define WEBSOCKETS_MAX_DATA_SIZE (1024)

0 commit comments

Comments
 (0)