Skip to content

Commit cc60722

Browse files
committed
esp8266 to browser working
1 parent a14a58d commit cc60722

File tree

2 files changed

+132
-46
lines changed

2 files changed

+132
-46
lines changed

src/WebSockets.cpp

Lines changed: 114 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -25,39 +25,70 @@
2525
#include "WebSockets.h"
2626

2727
/**
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-
+---------------------------------------------------------------+
4628
*
29+
* @param client WSclient_t * ptr to the client struct
30+
* @param code
31+
* @param reason
32+
* @param reasonLen
4733
*/
34+
void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * reason, size_t reasonLen) {
35+
if(client->status == WSC_CONNECTED && code) {
36+
//todo send reason to client
37+
38+
if(reasonLen > 0 && reason) {
39+
40+
} else {
41+
42+
}
43+
}
44+
clientDisconnect(client);
45+
}
46+
47+
/**
48+
*
49+
* @param client WSclient_t * ptr to the client struct
50+
* @param opcode WSopcode_t
51+
* @param payload uint8_t *
52+
* @param lenght size_t
53+
*/
54+
void WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t lenght) {
55+
56+
uint8_t buffer[16] = { 0 };
57+
uint8_t i = 0;
58+
59+
//create header
4860

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;
61+
buffer[i] = bit(7); // set Fin
62+
buffer[i++] |= opcode; // set opcode
5963

64+
if(lenght < 126) {
65+
buffer[i++] = lenght;
6066

67+
} else if(lenght < 0xFFFF) {
68+
buffer[i++] = 126;
69+
buffer[i++] = ((lenght >> 8) & 0xFF);
70+
buffer[i++] = (lenght & 0xFF);
71+
} else {
72+
buffer[i++] = 127;
73+
buffer[i++] = 0x00;
74+
buffer[i++] = 0x00;
75+
buffer[i++] = 0x00;
76+
buffer[i++] = 0x00;
77+
buffer[i++] = ((lenght >> 24) & 0xFF);
78+
buffer[i++] = ((lenght >> 16) & 0xFF);
79+
buffer[i++] = ((lenght >> 8) & 0xFF);
80+
buffer[i++] = (lenght & 0xFF);
81+
}
82+
83+
// send header
84+
client->tcp.write(&buffer[0], i);
85+
86+
if(payload && lenght > 0) {
87+
// send payload
88+
client->tcp.write(&payload[0], lenght);
89+
}
90+
91+
}
6192

6293
/**
6394
* handle the WebSocket stream
@@ -83,7 +114,7 @@ void WebSockets::handleWebsocket(WSclient_t * client) {
83114

84115
if(!readWait(client, buffer, 2)) {
85116
//timeout
86-
clientDisconnect(client);
117+
clientDisconnect(client, 1002);
87118
return;
88119
}
89120

@@ -92,23 +123,23 @@ void WebSockets::handleWebsocket(WSclient_t * client) {
92123
rsv1 = ((buffer[0] >> 6) & 0x01);
93124
rsv2 = ((buffer[0] >> 5) & 0x01);
94125
rsv3 = ((buffer[0] >> 4) & 0x01);
95-
opCode = (WSopcode_t)(buffer[0] & 0x0F);
126+
opCode = (WSopcode_t) (buffer[0] & 0x0F);
96127

97128
mask = ((buffer[1] >> 7) & 0x01);
98-
payloadLen = (WSopcode_t)(buffer[1] & 0x7F);
129+
payloadLen = (WSopcode_t) (buffer[1] & 0x7F);
99130

100131
if(payloadLen == 126) {
101132
if(!readWait(client, buffer, 2)) {
102133
//timeout
103-
clientDisconnect(client);
134+
clientDisconnect(client, 1002);
104135
return;
105136
}
106137
payloadLen = buffer[0] << 8 | buffer[1];
107138
} else if(payloadLen == 127) {
108139
// read 64bit inteager as Lenght
109140
if(!readWait(client, buffer, 8)) {
110141
//timeout
111-
clientDisconnect(client);
142+
clientDisconnect(client, 1002);
112143
return;
113144
}
114145

@@ -125,7 +156,7 @@ void WebSockets::handleWebsocket(WSclient_t * client) {
125156

126157
if(payloadLen > WEBSOCKETS_MAX_DATA_SIZE) {
127158
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] payload to big! (%u)\n", client->num, payloadLen);
128-
clientDisconnect(client);
159+
clientDisconnect(client, 1009);
129160
return;
130161
}
131162

@@ -135,37 +166,77 @@ void WebSockets::handleWebsocket(WSclient_t * client) {
135166

136167
if(payloadLen > 0) {
137168
// if text data we need one more
138-
payload = (uint8_t *) malloc(payloadLen+1);
169+
payload = (uint8_t *) malloc(payloadLen + 1);
139170

140171
if(!payload) {
141172
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] to less memory to handle payload %d!\n", client->num, payloadLen);
142-
clientDisconnect(client);
173+
clientDisconnect(client, 1011);
143174
return;
144175
}
145176

146177
if(!readWait(client, payload, payloadLen)) {
147178
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] missing data!\n", client->num);
148-
clientDisconnect(client);
179+
clientDisconnect(client, 1002);
149180
return;
150181
}
151182

183+
payload[payloadLen] = 0x00;
184+
152185
if(mask) {
153186
//decode XOR
154-
for (size_t i = 0; i < payloadLen; i++) {
187+
for(size_t i = 0; i < payloadLen; i++) {
155188
payload[i] = (payload[i] ^ maskKey[i % 4]);
156189
}
157190
}
158191

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);
192+
switch(opCode) {
193+
case WSop_text:
194+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] text: %s\n", client->num, payload)
195+
;
196+
// todo API for user to get message may callback
197+
198+
// send the frame back!
199+
sendFrame(client, WSop_text, payload, payloadLen);
200+
201+
break;
202+
case WSop_binary:
203+
// todo API for user to get message may callback
204+
break;
205+
case WSop_ping:
206+
// todo send pong
207+
break;
208+
case WSop_pong:
209+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] get pong from Client (%s)\n", client->num, payload)
210+
;
211+
break;
212+
case WSop_close: {
213+
uint16_t reasonCode = buffer[0] << 8 | buffer[1];
214+
215+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleWebsocket] client ask for close. Code: %d (%s)\n", client->num, reasonCode, (payload + 2));
216+
217+
// todo send confimation to client
218+
clientDisconnect(client, 1000, (char *) (payload + 2), payloadLen - 2);
219+
}
220+
break;
221+
case WSop_continuation:
222+
// continuation is not supported
223+
clientDisconnect(client, 1003);
224+
break;
225+
default:
226+
clientDisconnect(client, 1002);
227+
break;
164228
}
165229
}
166230

167231
}
168232

233+
/**
234+
* read x byte from tcp or get timeout
235+
* @param client WSclient_t *
236+
* @param out uint8_t * data buffer
237+
* @param n size_t byte count
238+
* @return true if ok
239+
*/
169240
bool WebSockets::readWait(WSclient_t * client, uint8_t *out, size_t n) {
170241
unsigned long t = millis();
171242
size_t len;

src/WebSockets.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ typedef enum {
5252
WSC_CONNECTED
5353
} WSclientsStatus_t;
5454

55+
typedef enum {
56+
WSop_continuation = 0x00, ///< %x0 denotes a continuation frame
57+
WSop_text = 0x01, ///< %x1 denotes a text frame
58+
WSop_binary = 0x02, ///< %x2 denotes a binary frame
59+
///< %x3-7 are reserved for further non-control frames
60+
WSop_close = 0x08, ///< %x8 denotes a connection close
61+
WSop_ping = 0x09, ///< %x9 denotes a ping
62+
WSop_pong = 0x0A ///< %xA denotes a pong
63+
///< %xB-F are reserved for further control frames
64+
} WSopcode_t;
65+
5566
typedef struct {
5667
uint8_t num; ///< connection number
5768

@@ -81,12 +92,16 @@ typedef struct {
8192

8293
class WebSockets {
8394
protected:
84-
85-
void handleWebsocket(WSclient_t * client);
86-
8795
virtual void clientDisconnect(WSclient_t * client);
8896
virtual bool clientIsConnected(WSclient_t * client);
8997

98+
99+
void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0);
100+
void sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t lenght = 0);
101+
102+
103+
void handleWebsocket(WSclient_t * client);
104+
90105
bool readWait(WSclient_t * client, uint8_t *out, size_t n);
91106
};
92107

0 commit comments

Comments
 (0)