Skip to content

Commit f95c014

Browse files
committed
basic event sending works
1 parent 8967356 commit f95c014

File tree

6 files changed

+199
-65
lines changed

6 files changed

+199
-65
lines changed

src/SocketIOclient.cpp

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,68 @@ void SocketIOclient::begin(String host, uint16_t port, String url, String protoc
2525
WebSocketsClient::beginSocketIO(host, port, url, protocol);
2626
}
2727

28+
bool SocketIOclient::isConnected(void) {
29+
return WebSocketsClient::isConnected();
30+
}
31+
32+
/**
33+
* send text data to client
34+
* @param num uint8_t client id
35+
* @param payload uint8_t *
36+
* @param length size_t
37+
* @param headerToPayload bool (see sendFrame for more details)
38+
* @return true if ok
39+
*/
40+
bool SocketIOclient::sendEVENT(uint8_t * payload, size_t length, bool headerToPayload) {
41+
bool ret = false;
42+
if(length == 0) {
43+
length = strlen((const char *) payload);
44+
}
45+
if(clientIsConnected(&_client)) {
46+
47+
if(!headerToPayload) {
48+
// webSocket Header
49+
ret = WebSocketsClient::sendFrameHeader(&_client, WSop_text, length + 2, true, true);
50+
// Engine.IO / Socket.IO Header
51+
if(ret) {
52+
uint8_t buf[3] = { eIOtype_MESSAGE, sIOtype_EVENT, 0x00 };
53+
ret = WebSocketsClient::write(&_client, buf, 2);
54+
}
55+
if(ret) {
56+
ret = WebSocketsClient::write(&_client, payload, length );
57+
}
58+
return ret;
59+
} else {
60+
// TODO implement
61+
}
62+
63+
// return WebSocketsClient::sendFrame(&_client, WSop_text, payload, length, true, true, headerToPayload);
64+
}
65+
return false;
66+
}
67+
68+
bool SocketIOclient::sendEVENT(const uint8_t * payload, size_t length) {
69+
return sendEVENT((uint8_t *) payload, length);
70+
}
71+
72+
bool SocketIOclient::sendEVENT(char * payload, size_t length, bool headerToPayload) {
73+
return sendEVENT((uint8_t *) payload, length, headerToPayload);
74+
}
75+
76+
bool SocketIOclient::sendEVENT(const char * payload, size_t length) {
77+
return sendEVENT((uint8_t *) payload, length);
78+
}
79+
80+
bool SocketIOclient::sendEVENT(String & payload) {
81+
return sendEVENT((uint8_t *) payload.c_str(), payload.length());
82+
}
83+
2884
void SocketIOclient::loop(void) {
2985
WebSocketsClient::loop();
3086
unsigned long t = millis();
3187
if((t - _lastConnectionFail) > EIO_HEARTBEAT_INTERVAL) {
3288
_lastConnectionFail = t;
33-
sendTXT(eIOtype_PING);
89+
//WebSocketsClient::sendTXT(eIOtype_PING);
3490
}
3591
}
3692

@@ -43,7 +99,7 @@ void SocketIOclient::runCbEvent(WStype_t type, uint8_t * payload, size_t length)
4399
DEBUG_WEBSOCKETS("[wsIOc] Connected to url: %s\n", payload);
44100
// send message to server when Connected
45101
// Engine.io upgrade confirmation message (required)
46-
sendTXT(eIOtype_UPGRADE);
102+
WebSocketsClient::sendTXT(eIOtype_UPGRADE);
47103
}
48104
break;
49105
case WStype_TEXT: {
@@ -57,7 +113,7 @@ void SocketIOclient::runCbEvent(WStype_t type, uint8_t * payload, size_t length)
57113
case eIOtype_PING:
58114
payload[0] = eIOtype_PONG;
59115
DEBUG_WEBSOCKETS("[wsIOc] get ping send pong (%s)\n", payload);
60-
sendTXT(payload, length);
116+
WebSocketsClient::sendTXT(payload, length, false);
61117
break;
62118
case eIOtype_PONG:
63119
DEBUG_WEBSOCKETS("[wsIOc] get pong\n");

src/SocketIOclient.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
#define EIO_HEARTBEAT_INTERVAL 10000
1414

15+
#define EIO_MAX_HEADER_SIZE (WEBSOCKETS_MAX_HEADER_SIZE + 1)
16+
#define SIO_MAX_HEADER_SIZE (EIO_MAX_HEADER_SIZE + 1)
17+
1518
typedef enum {
1619
eIOtype_OPEN = '0', ///< Sent from the server when a new transport is opened (recheck)
1720
eIOtype_CLOSE = '1', ///< Request the close of this transport but does not shutdown the connection itself.
@@ -33,7 +36,7 @@ typedef enum {
3336
sIOtype_BINARY_ACK = '6',
3437
} socketIOmessageType_t;
3538

36-
class SocketIOclient: private WebSocketsClient {
39+
class SocketIOclient: protected WebSocketsClient {
3740

3841
public:
3942
#ifdef __AVR__
@@ -48,9 +51,17 @@ class SocketIOclient: private WebSocketsClient {
4851
void begin(const char *host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
4952
void begin(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
5053

54+
bool isConnected(void);
55+
56+
bool sendEVENT(uint8_t * payload, size_t length = 0, bool headerToPayload = false);
57+
bool sendEVENT(const uint8_t * payload, size_t length = 0);
58+
bool sendEVENT(char * payload, size_t length = 0, bool headerToPayload = false);
59+
bool sendEVENT(const char * payload, size_t length = 0);
60+
bool sendEVENT(String & payload);
5161

5262
void loop(void);
53-
private:
63+
64+
protected:
5465
void runCbEvent(WStype_t type, uint8_t * payload, size_t length);
5566
uint64_t _lastHeartbeat = 0;
5667
};

src/WebSockets.cpp

Lines changed: 110 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,115 @@ void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * rea
7171
clientDisconnect(client);
7272
}
7373

74+
/**
75+
*
76+
* @param buf uint8_t * ptr to the buffer for writing
77+
* @param opcode WSopcode_t
78+
* @param length size_t length of the payload
79+
* @param mask bool add dummy mask to the frame (needed for web browser)
80+
* @param maskkey uint8_t[4] key used for payload
81+
* @param fin bool can be used to send data in more then one frame (set fin on the last frame)
82+
*/
83+
uint8_t WebSockets::createHeader(uint8_t * headerPtr, WSopcode_t opcode, size_t length, bool mask, uint8_t maskKey[4], bool fin) {
84+
uint8_t headerSize;
85+
// calculate header Size
86+
if(length < 126) {
87+
headerSize = 2;
88+
} else if(length < 0xFFFF) {
89+
headerSize = 4;
90+
} else {
91+
headerSize = 10;
92+
}
93+
94+
if(mask) {
95+
headerSize += 4;
96+
}
97+
98+
// create header
99+
100+
// byte 0
101+
*headerPtr = 0x00;
102+
if(fin) {
103+
*headerPtr |= bit(7); ///< set Fin
104+
}
105+
*headerPtr |= opcode; ///< set opcode
106+
headerPtr++;
107+
108+
// byte 1
109+
*headerPtr = 0x00;
110+
if(mask) {
111+
*headerPtr |= bit(7); ///< set mask
112+
}
113+
114+
if(length < 126) {
115+
*headerPtr |= length;
116+
headerPtr++;
117+
} else if(length < 0xFFFF) {
118+
*headerPtr |= 126;
119+
headerPtr++;
120+
*headerPtr = ((length >> 8) & 0xFF);
121+
headerPtr++;
122+
*headerPtr = (length & 0xFF);
123+
headerPtr++;
124+
} else {
125+
// Normally we never get here (to less memory)
126+
*headerPtr |= 127;
127+
headerPtr++;
128+
*headerPtr = 0x00;
129+
headerPtr++;
130+
*headerPtr = 0x00;
131+
headerPtr++;
132+
*headerPtr = 0x00;
133+
headerPtr++;
134+
*headerPtr = 0x00;
135+
headerPtr++;
136+
*headerPtr = ((length >> 24) & 0xFF);
137+
headerPtr++;
138+
*headerPtr = ((length >> 16) & 0xFF);
139+
headerPtr++;
140+
*headerPtr = ((length >> 8) & 0xFF);
141+
headerPtr++;
142+
*headerPtr = (length & 0xFF);
143+
headerPtr++;
144+
}
145+
146+
if(mask) {
147+
*headerPtr = maskKey[0];
148+
headerPtr++;
149+
*headerPtr = maskKey[1];
150+
headerPtr++;
151+
*headerPtr = maskKey[2];
152+
headerPtr++;
153+
*headerPtr = maskKey[3];
154+
headerPtr++;
155+
}
156+
return headerSize;
157+
}
158+
159+
/**
160+
*
161+
* @param client WSclient_t * ptr to the client struct
162+
* @param opcode WSopcode_t
163+
* @param length size_t length of the payload
164+
* @param mask bool add dummy mask to the frame (needed for web browser)
165+
* @param fin bool can be used to send data in more then one frame (set fin on the last frame)
166+
* @return true if ok
167+
*/
168+
bool WebSockets::sendFrameHeader(WSclient_t * client, WSopcode_t opcode, size_t length, bool mask, bool fin) {
169+
uint8_t maskKey[4] = { 0x00, 0x00, 0x00, 0x00 };
170+
uint8_t buffer[WEBSOCKETS_MAX_HEADER_SIZE] = { 0 };
171+
172+
uint8_t headerSize = createHeader(&buffer[0], opcode, length, mask, maskKey, fin);
173+
174+
if(write(client, &buffer[0], headerSize) != headerSize) {
175+
return false;
176+
}
177+
178+
return true;
179+
}
180+
181+
182+
74183
/**
75184
*
76185
* @param client WSclient_t * ptr to the client struct
@@ -146,62 +255,14 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
146255
headerPtr = &buffer[0];
147256
}
148257

149-
// create header
150-
151-
// byte 0
152-
*headerPtr = 0x00;
153-
if(fin) {
154-
*headerPtr |= bit(7); ///< set Fin
155-
}
156-
*headerPtr |= opcode; ///< set opcode
157-
headerPtr++;
158-
159-
// byte 1
160-
*headerPtr = 0x00;
161-
if(mask) {
162-
*headerPtr |= bit(7); ///< set mask
163-
}
164-
165-
if(length < 126) {
166-
*headerPtr |= length;
167-
headerPtr++;
168-
} else if(length < 0xFFFF) {
169-
*headerPtr |= 126;
170-
headerPtr++;
171-
*headerPtr = ((length >> 8) & 0xFF);
172-
headerPtr++;
173-
*headerPtr = (length & 0xFF);
174-
headerPtr++;
175-
} else {
176-
// Normally we never get here (to less memory)
177-
*headerPtr |= 127;
178-
headerPtr++;
179-
*headerPtr = 0x00;
180-
headerPtr++;
181-
*headerPtr = 0x00;
182-
headerPtr++;
183-
*headerPtr = 0x00;
184-
headerPtr++;
185-
*headerPtr = 0x00;
186-
headerPtr++;
187-
*headerPtr = ((length >> 24) & 0xFF);
188-
headerPtr++;
189-
*headerPtr = ((length >> 16) & 0xFF);
190-
headerPtr++;
191-
*headerPtr = ((length >> 8) & 0xFF);
192-
headerPtr++;
193-
*headerPtr = (length & 0xFF);
194-
headerPtr++;
195-
}
258+
createHeader(headerPtr, opcode, length, mask, maskKey, fin);
196259

197260
if(mask) {
198261
if(useInternBuffer) {
199262
// if we use a Intern Buffer we can modify the data
200263
// by this fact its possible the do the masking
201264
for(uint8_t x = 0; x < sizeof(maskKey); x++) {
202265
maskKey[x] = random(0xFF);
203-
*headerPtr = maskKey[x];
204-
headerPtr++;
205266
}
206267

207268
uint8_t * dataMaskPtr;
@@ -215,16 +276,6 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
215276
for(size_t x = 0; x < length; x++) {
216277
dataMaskPtr[x] = (dataMaskPtr[x] ^ maskKey[x % 4]);
217278
}
218-
219-
} else {
220-
*headerPtr = maskKey[0];
221-
headerPtr++;
222-
*headerPtr = maskKey[1];
223-
headerPtr++;
224-
*headerPtr = maskKey[2];
225-
headerPtr++;
226-
*headerPtr = maskKey[3];
227-
headerPtr++;
228279
}
229280
}
230281

src/WebSockets.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,9 @@ class WebSockets {
285285
virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) = 0;
286286

287287
void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0);
288+
289+
uint8_t createHeader(uint8_t * buf, WSopcode_t opcode, size_t length, bool mask, uint8_t maskKey[4], bool fin);
290+
bool sendFrameHeader(WSclient_t * client, WSopcode_t opcode, size_t length = 0, bool mask = false, bool fin = true);
288291
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);
289292

290293
void headerDone(WSclient_t * client);

src/WebSocketsClient.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,10 @@ void WebSocketsClient::setReconnectInterval(unsigned long time) {
310310
_reconnectInterval = time;
311311
}
312312

313+
bool WebSocketsClient::isConnected(void) {
314+
return (_client.status == WSC_CONNECTED);
315+
}
316+
313317
//#################################################################################
314318
//#################################################################################
315319
//#################################################################################
@@ -666,6 +670,13 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
666670
runCbEvent(WStype_CONNECTED, (uint8_t *) client->cUrl.c_str(), client->cUrl.length());
667671

668672
} else if(clientIsConnected(client) && client->isSocketIO && client->cSessionId.length() > 0) {
673+
if(_client.tcp->available()) {
674+
// read not needed data
675+
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] still data in buffer (%d), clean up.\n", _client.tcp->available());
676+
while(_client.tcp->available() > 0) {
677+
_client.tcp->read();
678+
}
679+
}
669680
sendHeader(client);
670681
} else {
671682
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");

src/WebSocketsClient.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
#include "WebSockets.h"
2929

30-
class WebSocketsClient: private WebSockets {
30+
class WebSocketsClient: protected WebSockets {
3131
public:
3232
#ifdef __AVR__
3333
typedef void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length);
@@ -87,6 +87,8 @@ class WebSocketsClient: private WebSockets {
8787

8888
void setReconnectInterval(unsigned long time);
8989

90+
bool isConnected(void);
91+
9092
protected:
9193
String _host;
9294
uint16_t _port;

0 commit comments

Comments
 (0)