Skip to content

Commit a14a58d

Browse files
committed
message browser to client working
1 parent e7a33be commit a14a58d

File tree

5 files changed

+293
-85
lines changed

5 files changed

+293
-85
lines changed

src/WebSockets.cpp

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/**
2+
* @file WebSockets.cpp
3+
* @date 20.05.2015
4+
* @author Markus Sattler
5+
*
6+
* Copyright (c) 2015 Markus Sattler. All rights reserved.
7+
* This file is part of the WebSockets for Arduino.
8+
*
9+
* This library is free software; you can redistribute it and/or
10+
* modify it under the terms of the GNU Lesser General Public
11+
* License as published by the Free Software Foundation; either
12+
* version 2.1 of the License, or (at your option) any later version.
13+
*
14+
* This library is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17+
* Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public
20+
* License along with this library; if not, write to the Free Software
21+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22+
*
23+
*/
24+
25+
#include "WebSockets.h"
26+
27+
/**
28+
0 1 2 3
29+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
30+
+-+-+-+-+-------+-+-------------+-------------------------------+
31+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
32+
|I|S|S|S| (4) |A| (7) | (16/64) |
33+
|N|V|V|V| |S| | (if payload len==126/127) |
34+
| |1|2|3| |K| | |
35+
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
36+
| Extended payload length continued, if payload len == 127 |
37+
+ - - - - - - - - - - - - - - - +-------------------------------+
38+
| |Masking-key, if MASK set to 1 |
39+
+-------------------------------+-------------------------------+
40+
| Masking-key (continued) | Payload Data |
41+
+-------------------------------- - - - - - - - - - - - - - - - +
42+
: Payload Data continued ... :
43+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
44+
| Payload Data continued ... |
45+
+---------------------------------------------------------------+
46+
*
47+
*/
48+
49+
typedef enum {
50+
WSop_continuation = 0x00, ///< %x0 denotes a continuation frame
51+
WSop_text = 0x01, ///< %x1 denotes a text frame
52+
WSop_binary = 0x02, ///< %x2 denotes a binary frame
53+
///< %x3-7 are reserved for further non-control frames
54+
WSop_close = 0x08, ///< %x8 denotes a connection close
55+
WSop_ping = 0x09, ///< %x9 denotes a ping
56+
WSop_pong = 0x0A ///< %xA denotes a pong
57+
///< %xB-F are reserved for further control frames
58+
} WSopcode_t;
59+
60+
61+
62+
/**
63+
* handle the WebSocket stream
64+
* @param client WSclient_t * ptr to the client struct
65+
*/
66+
void WebSockets::handleWebsocket(WSclient_t * client) {
67+
68+
uint8_t buffer[8] = { 0 };
69+
70+
bool fin;
71+
bool rsv1;
72+
bool rsv2;
73+
bool rsv3;
74+
WSopcode_t opCode;
75+
bool mask;
76+
size_t payloadLen;
77+
78+
uint8_t maskKey[4];
79+
80+
uint8_t * payload = NULL;
81+
82+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] ------- read massage frame -------\n", client->num);
83+
84+
if(!readWait(client, buffer, 2)) {
85+
//timeout
86+
clientDisconnect(client);
87+
return;
88+
}
89+
90+
// split first 2 bytes in the data
91+
fin = ((buffer[0] >> 7) & 0x01);
92+
rsv1 = ((buffer[0] >> 6) & 0x01);
93+
rsv2 = ((buffer[0] >> 5) & 0x01);
94+
rsv3 = ((buffer[0] >> 4) & 0x01);
95+
opCode = (WSopcode_t)(buffer[0] & 0x0F);
96+
97+
mask = ((buffer[1] >> 7) & 0x01);
98+
payloadLen = (WSopcode_t)(buffer[1] & 0x7F);
99+
100+
if(payloadLen == 126) {
101+
if(!readWait(client, buffer, 2)) {
102+
//timeout
103+
clientDisconnect(client);
104+
return;
105+
}
106+
payloadLen = buffer[0] << 8 | buffer[1];
107+
} else if(payloadLen == 127) {
108+
// read 64bit inteager as Lenght
109+
if(!readWait(client, buffer, 8)) {
110+
//timeout
111+
clientDisconnect(client);
112+
return;
113+
}
114+
115+
if(buffer[0] != 0 || buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0) {
116+
// really to big!
117+
payloadLen = 0xFFFFFFFF;
118+
} else {
119+
payloadLen = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7];
120+
}
121+
}
122+
123+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] fin: %u rsv1: %u rsv2: %u rsv3 %u opCode: %u\n", client->num, fin, rsv1, rsv2, rsv3, opCode);
124+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] mask: %u payloadLen: %u\n", client->num, mask, payloadLen);
125+
126+
if(payloadLen > WEBSOCKETS_MAX_DATA_SIZE) {
127+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] payload to big! (%u)\n", client->num, payloadLen);
128+
clientDisconnect(client);
129+
return;
130+
}
131+
132+
if(mask) {
133+
client->tcp.read(maskKey, 4);
134+
}
135+
136+
if(payloadLen > 0) {
137+
// if text data we need one more
138+
payload = (uint8_t *) malloc(payloadLen+1);
139+
140+
if(!payload) {
141+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] to less memory to handle payload %d!\n", client->num, payloadLen);
142+
clientDisconnect(client);
143+
return;
144+
}
145+
146+
if(!readWait(client, payload, payloadLen)) {
147+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] missing data!\n", client->num);
148+
clientDisconnect(client);
149+
return;
150+
}
151+
152+
if(mask) {
153+
//decode XOR
154+
for (size_t i = 0; i < payloadLen; i++) {
155+
payload[i] = (payload[i] ^ maskKey[i % 4]);
156+
}
157+
}
158+
159+
if(opCode == WSop_text) {
160+
payload[payloadLen] = 0x00;
161+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] Text: %s\n", client->num, payload);
162+
} else {
163+
clientDisconnect(client);
164+
}
165+
}
166+
167+
}
168+
169+
bool WebSockets::readWait(WSclient_t * client, uint8_t *out, size_t n) {
170+
unsigned long t = millis();
171+
size_t len;
172+
173+
while(n > 0) {
174+
if(!client->tcp.connected()) {
175+
DEBUG_WEBSOCKETS("[readWait] Receive not connected - 1!\n");
176+
return false;
177+
}
178+
while(!client->tcp.available()) {
179+
if(!client->tcp.connected()) {
180+
DEBUG_WEBSOCKETS("[readWait] Receive not connected - 2!\n");
181+
return false;
182+
}
183+
if((millis() - t) > WEBSOCKETS_TCP_TIMEOUT) {
184+
DEBUG_WEBSOCKETS("[readWait] Receive TIMEOUT!\n");
185+
return false;
186+
}
187+
delay(0);
188+
}
189+
190+
len = client->tcp.read((uint8_t*) out, n);
191+
if(len) {
192+
t = millis();
193+
out += len;
194+
n -= len;
195+
//DEBUG_WEBSOCKETS("Receive %d left %d!\n", len, n);
196+
} else {
197+
//DEBUG_WEBSOCKETS("Receive %d left %d!\n", len, n);
198+
}
199+
delay(0);
200+
}
201+
return true;
202+
}

src/WebSockets.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,67 @@
2727

2828
#include <Arduino.h>
2929

30+
#ifdef ESP8266
31+
#include <ESP8266WiFi.h>
32+
#else
33+
#include <UIPEthernet.h>
34+
#ifndef UIPETHERNET_H
35+
#include <Ethernet.h>
36+
#include <SPI.h>
37+
#endif
38+
#endif
39+
3040
#define DEBUG_WEBSOCKETS(...) Serial1.printf( __VA_ARGS__ ); Serial1.flush()
3141

3242
#ifndef DEBUG_WEBSOCKETS
3343
#define DEBUG_WEBSOCKETS(...)
3444
#endif
3545

46+
#define WEBSOCKETS_MAX_DATA_SIZE (15*1024)
47+
#define WEBSOCKETS_TCP_TIMEOUT (1000)
48+
49+
typedef enum {
50+
WSC_NOT_CONNECTED,
51+
WSC_HEADER,
52+
WSC_CONNECTED
53+
} WSclientsStatus_t;
54+
55+
typedef struct {
56+
uint8_t num; ///< connection number
57+
58+
WSclientsStatus_t status;
59+
#ifdef ESP8266
60+
WiFiClient tcp;
61+
#else
62+
#ifdef UIPETHERNET_H
63+
UIPClient tcp;
64+
#else
65+
EthernetClient tcp;
66+
#endif
67+
#endif
68+
String cUrl; ///< http url
69+
70+
bool cIsUpgrade; ///< Connection == Upgrade
71+
bool cIsWebsocket; ///< Upgrade == websocket
72+
73+
String cKey; ///< client Sec-WebSocket-Key
74+
String cProtocol; ///< client Sec-WebSocket-Protocol
75+
String cExtensions; ///< client Sec-WebSocket-Extensions
76+
int cVersion; ///< client Sec-WebSocket-Version
77+
78+
String sKey; ///< server Sec-WebSocket-Key
79+
80+
} WSclient_t;
81+
82+
class WebSockets {
83+
protected:
84+
85+
void handleWebsocket(WSclient_t * client);
3686

87+
virtual void clientDisconnect(WSclient_t * client);
88+
virtual bool clientIsConnected(WSclient_t * client);
3789

90+
bool readWait(WSclient_t * client, uint8_t *out, size_t n);
91+
};
3892

3993
#endif /* WEBSOCKETS_H_ */

0 commit comments

Comments
 (0)