8000 add support for Fragmentation / continuation opcode Receive · Intrising/arduinoWebSockets@e93a323 · GitHub
[go: up one dir, main page]

Skip to content

Commit e93a323

Browse files
committed
add support for Fragmentation / continuation opcode Receive
1 parent 6da0bc9 commit e93a323

File tree

8 files changed

+137
-35
lines changed

8 files changed

+137
-35
lines changed

README.md

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,47 @@ WebSocket Server and Client for Arduino
33

44
a WebSocket Server and Client for Arduino based on RFC6455.
55

6-
6+
77
##### Supported features of RFC6455 #####
88
- text frame
99
- binary frame
1010
- connection close
1111
- ping
1212
- pong
13-
14-
##### Not supported features of RFC6455 #####
1513
- continuation frame
16-
14+
1715
##### Limitations #####
1816
- max input length is limited to the ram size and the ```WEBSOCKETS_MAX_DATA_SIZE``` define
1917
- max output length has no limit (the hardware is the limit)
2018
- Client send big frames with mask 0x00000000 (on AVR all frames)
21-
19+
- continuation frame reassembly need to be handled in the application code
20+
2221
##### Limitations for Async #####
2322
- Functions called from within the context of the websocket event might not honor `yield()` and/or `delay()`. See [this issue](https://github.com/Links2004/arduinoWebSockets/issues/58#issuecomment-192376395) for more info and a potential workaround.
2423
- wss / SSL is not possible.
25-
24+
2625
##### Supported Hardware #####
2726
- ESP8266 [Arduino for ESP8266](https://github.com/Links2004/Arduino)
2827
- ESP31B
29-
- ATmega328 with Ethernet Shield (ATmega branch)
30-
- ATmega328 with enc28j60 (ATmega branch)
31-
- ATmega2560 with Ethernet Shield (ATmega branch)
32-
- ATmega2560 with enc28j60 (ATmega branch)
33-
28+
- Particle with STM32 ARM Cortex M3
29+
- ATmega328 with Ethernet Shield (ATmega branch)
30+
- ATmega328 with enc28j60 (ATmega branch)
31+
- ATmega2560 with Ethernet Shield (ATmega branch)
32+
- ATmega2560 with enc28j60 (ATmega branch)
33+
3434
###### Note: ######
3535

3636
version 2.0 and up is not compatible with AVR/ATmega, check ATmega branch.
37-
37+
3838
Arduino for AVR not supports std namespace of c++.
39-
39+
4040
### wss / SSL ###
4141
supported for:
4242
- wss client on the ESP8266
4343
- wss / SSL is not natively supported in WebSocketsServer however it is possible to achieve secure websockets
4444
by running the device behind an SSL proxy. See [Nginx](examples/Nginx/esp8266.ssl.reverse.proxy.conf) for a
45-
sample Nginx server configuration file to enable this.
46-
45+
sample Nginx server configuration file to enable this.
46+
4747
### ESP Async TCP ###
4848

4949
This libary can run in Async TCP mode on the ESP.
@@ -52,9 +52,6 @@ The mode can be activated in the ```WebSockets.h``` (see WEBSOCKETS_NETWORK_TYPE
5252

5353
[ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP) libary is required.
5454

55-
### Support for Particle devices ###
56-
- ESP.getFreeHeap() replaced by macro GET_FREE_HEAP, defined by the type of device (currently only for ESP and STM32-based/Particle devices).
57-
- Use Particle's TCPClient and TCPServer classes instead of Arduino's.
5855

5956
### Issues ###
6057
Submit issues to: https://github.com/Links2004/arduinoWebSockets/issues
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* WebSocketServer.ino
3+
*
4+
* Created on: 22.05.2015
5+
*
6+
*/
7+
8+
#include <Arduino.h>
9+
10+
#include <ESP8266WiFi.h>
11+
#include <ESP8266WiFiMulti.h>
12+
#include <WebSocketsServer.h>
13+
#include <Hash.h>
14+
15+
ESP8266WiFiMulti WiFiMulti;
16+
17+
WebSocketsServer webSocket = WebSocketsServer(81);
18+
19+
#define USE_SERIAL Serial
20+
21+
String fragmentBuffer = "";
22+
23+
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght) {
24+
25+
switch(type) {
26+
case WStype_DISCONNECTED:
27+
USE_SERIAL.printf("[%u] Disconnected!\n", num);
28+
break;
29+
case WStype_CONNECTED: {
30+
IPAddress ip = webSocket.remoteIP(num);
31+
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
32+
33+
// send message to client
34+
webSocket.sendTXT(num, "Connected");
35+
}
36+
break;
37+
case WStype_TEXT:
38+
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload);
39+
break;
40+
case WStype_BIN:
41+
USE_SERIAL.printf("[%u] get binary lenght: %u\n", num, lenght);
42+
hexdump(payload, lenght);
43+
break;
44+
45+
// Fragmentation / continuation opcode handling
46+
// case WStype_FRAGMENT_BIN_START:
47+
case WStype_FRAGMENT_TEXT_START:
48+
fragmentBuffer = (char*)payload;
49+
USE_SERIAL.printf("[%u] get start start of Textfragment: %s\n", num, payload);
50+
break;
51+
case WStype_FRAGMENT:
52+
fragmentBuffer += (char*)payload;
53+
USE_SERIAL.printf("[%u] get Textfragment : %s\n", num, payload);
54+
break;
55+
case WStype_FRAGMENT_FIN:
56+
fragmentBuffer += (char*)payload;
57+
USE_SERIAL.printf("[%u] get end of Textfragment: %s\n", num, payload);
58+
USE_SERIAL.printf("[%u] full frame: %s\n", num, fragmentBuffer.c_str());
59+
break;
60+
}
61+
62+
}
63+
64+
void setup() {
65+
// USE_SERIAL.begin(921600);
66+
USE_SERIAL.begin(115200);
67+
68+
//Serial.setDebugOutput(true);
69+
USE_SERIAL.setDebugOutput(true);
70+
71+
USE_SERIAL.println();
72+
USE_SERIAL.println();
73+
USE_SERIAL.println();
74+
75+
for(uint8_t t = 4; t > 0; t--) {
76+
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
77+
USE_SERIAL.flush();
78+
delay(1000);
79+
}
80+
81+
WiFiMulti.addAP("SSID", "passpasspass");
82+
83+
while(WiFiMulti.run() != WL_CONNECTED) {
84+
delay(100);
85+
}
86+
87+
webSocket.begin();
88+
webSocket.onEvent(webSocketEvent);
89+
}
90+
91+
void loop() {
92+
webSocket.loop();
93+
}
94+

src/WebSockets.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -426,14 +426,15 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
426426
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] text: %s\n", client->num, payload);
427427
// no break here!
428428
case WSop_binary:
429-
messageReceived(client, header->opCode, payload, header->payloadLen);
429+
case WSop_continuation:
430+
messageReceived(client, header->opCode, payload, header->payloadLen, header->fin);
430431
break;
431432
case WSop_ping:
432433
// send pong back
433434
sendFrame(client, WSop_pong, payload, header->payloadLen, true);
434435
break;
435436
case WSop_pong:
436-
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] get pong (%s)\n", client->num, payload);
437+
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] get pong (%s)\n", client->num, payload ? (const char*)payload : "");
437438
break;
438439
case WSop_close: {
439440
uint16_t reasonCode = 1000;
@@ -449,11 +450,7 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
449450
}
450451
clientDisconnect(client, 1000);
451452
}
452-
break;
453-
case WSop_continuation:
454-
// continuation is not supported
455-
clientDisconnect(client, 1003);
456-
break;
453+
break;
457454
default:
458455
clientDisconnect(client, 1002);
459456
break;

src/WebSockets.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@
3232
#include <Arduino.h>
3333
#endif
3434

35+
#ifdef DEBUG_ESP_PORT
36+
#define DEBUG_WEBSOCKETS(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ )
37+
#else
3538
//#define DEBUG_WEBSOCKETS(...) os_printf( __VA_ARGS__ )
39+
#endif
3640

3741
#ifndef DEBUG_WEBSOCKETS
3842
#define DEBUG_WEBSOCKETS(...)
@@ -142,7 +146,11 @@ typedef enum {
142146
WStype_DISCONNECTED,
143147
WStype_CONNECTED,
144148
WStype_TEXT,
145-
WStype_BIN
149+
WStype_BIN,
150+
WStype_FRAGMENT_TEXT_START,
151+
WStype_FRAGMENT_BIN_START,
152+
WStype_FRAGMENT,
153+
WStype_FRAGMENT_FIN,
146154
} WStype_t;
147155

148156
typedef enum {
@@ -227,7 +235,7 @@ class WebSockets {
227235
virtual void clientDisconnect(WSclient_t * client);
228236
virtual bool clientIsConnected(WSclient_t * client);
229237

230-
virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length);
238+
virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
231239

232240
void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0);
233241
bool sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, bool mask = false, bool fin = true, bool headerToPayload = false);

src/WebSocketsClient.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,16 +272,19 @@ void WebSocketsClient::setAuthorization(const char * auth) {
272272
* @param payload uint8_t *
273273
* @param lenght size_t
274274
*/
275-
void WebSocketsClient::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t lenght) {
275+
void WebSocketsClient::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t lenght, bool fin) {
276276
WStype_t type = WStype_ERROR;
277277

278278
switch(opcode) {
279279
case WSop_text:
280-
type = WStype_TEXT;
280+
type = fin ? WStype_TEXT : WStype_FRAGMENT_TEXT_START;
281281
break;
282282
case WSop_binary:
283-
type = WStype_BIN;
283+
type = fin ? WStype_BIN : WStype_FRAGMENT_BIN_START;
284284
break;
285+
case WSop_continuation:
286+
type = fin ? WStype_FRAGMENT_FIN : WStype_FRAGMENT;
287+
break;
285288
}
286289

287290
runCbEvent(type, payload, lenght);

src/WebSocketsClient.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class WebSocketsClient: private WebSockets {
8787

8888
WebSocketClientEvent _cbEvent;
8989

90-
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length);
90+
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
9191

9292
void clientDisconnect(WSclient_t * client);
9393
bool clientIsConnected(WSclient_t * client);

src/WebSocketsServer.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -470,15 +470,18 @@ bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) {
470470
* @param payload uint8_t *
471471
* @param lenght size_t
472472
*/
473-
void WebSocketsServer::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t lenght) {
473+
void WebSocketsServer::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t lenght, bool fin) {
474474
WStype_t type = WStype_ERROR;
475475

476476
switch(opcode) {
477477
case WSop_text:
478-
type = WStype_TEXT;
478+
type = fin ? WStype_TEXT : WStype_FRAGMENT_TEXT_START;
479479
break;
480480
case WSop_binary:
481-
type = WStype_BIN;
481+
type = fin ? WStype_BIN : WStype_FRAGMENT_BIN_START;
482+
break;
483+
case WSop_continuation:
484+
type = fin ? WStype_FRAGMENT_FIN : WStype_FRAGMENT;
482485
break;
483486
}
484487

src/WebSocketsServer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class WebSocketsServer: protected WebSockets {
113113

114114
bool newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient);
115115

116-
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length);
116+
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
117117

118118
void clientDisconnect(WSclient_t * client);
119119
bool clientIsConnected(WSclient_t * client);

0 commit comments

Comments
 (0)
0