25
25
#include " WebSockets.h"
26
26
27
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
28
*
29
+ * @param client WSclient_t * ptr to the client struct
30
+ * @param code
31
+ * @param reason
32
+ * @param reasonLen
47
33
*/
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
48
60
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
59
63
64
+ if (lenght < 126 ) {
65
+ buffer[i++] = lenght;
60
66
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
+ }
61
92
62
93
/* *
63
94
* handle the WebSocket stream
@@ -83,7 +114,7 @@ void WebSockets::handleWebsocket(WSclient_t * client) {
83
114
84
115
if (!readWait (client, buffer, 2 )) {
85
116
// timeout
86
- clientDisconnect (client);
117
+ clientDisconnect (client, 1002 );
87
118
return ;
88
119
}
89
120
@@ -92,23 +123,23 @@ void WebSockets::handleWebsocket(WSclient_t * client) {
92
123
rsv1 = ((buffer[0 ] >> 6 ) & 0x01 );
93
124
rsv2 = ((buffer[0 ] >> 5 ) & 0x01 );
94
125
rsv3 = ((buffer[0 ] >> 4 ) & 0x01 );
95
- opCode = (WSopcode_t)(buffer[0 ] & 0x0F );
126
+ opCode = (WSopcode_t) (buffer[0 ] & 0x0F );
96
127
97
128
mask = ((buffer[1 ] >> 7 ) & 0x01 );
98
- payloadLen = (WSopcode_t)(buffer[1 ] & 0x7F );
129
+ payloadLen = (WSopcode_t) (buffer[1 ] & 0x7F );
99
130
100
131
if (payloadLen == 126 ) {
101
132
if (!readWait (client, buffer, 2 )) {
102
133
// timeout
103
- clientDisconnect (client);
134
+ clientDisconnect (client, 1002 );
104
135
return ;
105
136
}
106
137
payloadLen = buffer[0 ] << 8 | buffer[1 ];
107
138
} else if (payloadLen == 127 ) {
108
139
// read 64bit inteager as Lenght
109
140
if (!readWait (client, buffer, 8 )) {
110
141
// timeout
111
- clientDisconnect (client);
142
+ clientDisconnect (client, 1002 );
112
143
return ;
113
144
}
114
145
@@ -125,7 +156,7 @@ void WebSockets::handleWebsocket(WSclient_t * client) {
125
156
126
157
if (payloadLen > WEBSOCKETS_MAX_DATA_SIZE) {
127
158
DEBUG_WEBSOCKETS (" [WS-Server][%d][handleWebsocket] payload to big! (%u)\n " , client->num , payloadLen);
128
- clientDisconnect (client);
159
+ clientDisconnect (client, 1009 );
129
160
return ;
130
161
}
131
162
@@ -135,37 +166,77 @@ void WebSockets::handleWebsocket(WSclient_t * client) {
135
166
136
167
if (payloadLen > 0 ) {
137
168
// if text data we need one more
138
- payload = (uint8_t *) malloc (payloadLen+ 1 );
169
+ payload = (uint8_t *) malloc (payloadLen + 1 );
139
170
140
171
if (!payload) {
141
172
DEBUG_WEBSOCKETS (" [WS-Server][%d][handleWebsocket] to less memory to handle payload %d!\n " , client->num , payloadLen);
142
- clientDisconnect (client);
173
+ clientDisconnect (client, 1011 );
143
174
return ;
144
175
}
145
176
146
177
if (!readWait (client, payload, payloadLen)) {
147
178
DEBUG_WEBSOCKETS (" [WS-Server][%d][handleWebsocket] missing data!\n " , client->num );
148
- clientDisconnect (client);
179
+ clientDisconnect (client, 1002 );
149
180
return ;
150
181
}
151
182
183
+ payload[payloadLen] = 0x00 ;
184
+
152
185
if (mask) {
153
186
// decode XOR
154
- for (size_t i = 0 ; i < payloadLen; i++) {
187
+ for (size_t i = 0 ; i < payloadLen; i++) {
155
188
payload[i] = (payload[i] ^ maskKey[i % 4 ]);
156
189
}
157
190
}
158
191
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 ;
164
228
}
165
229
}
166
230
167
231
}
168
232
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
+ */
169
240
bool WebSockets::readWait (WSclient_t * client, uint8_t *out, size_t n) {
170
241
unsigned long t = millis ();
171
242
size_t len;
0 commit comments