basic event sending works

This commit is contained in:
Links
2018-05-12 16:53:34 +02:00
parent 8967356af3
commit f95c014342
6 changed files with 199 additions and 65 deletions

View File

@ -25,12 +25,68 @@ void SocketIOclient::begin(String host, uint16_t port, String url, String protoc
WebSocketsClient::beginSocketIO(host, port, url, protocol); WebSocketsClient::beginSocketIO(host, port, url, protocol);
} }
bool SocketIOclient::isConnected(void) {
return WebSocketsClient::isConnected();
}
/**
* send text data to client
* @param num uint8_t client id
* @param payload uint8_t *
* @param length size_t
* @param headerToPayload bool (see sendFrame for more details)
* @return true if ok
*/
bool SocketIOclient::sendEVENT(uint8_t * payload, size_t length, bool headerToPayload) {
bool ret = false;
if(length == 0) {
length = strlen((const char *) payload);
}
if(clientIsConnected(&_client)) {
if(!headerToPayload) {
// webSocket Header
ret = WebSocketsClient::sendFrameHeader(&_client, WSop_text, length + 2, true, true);
// Engine.IO / Socket.IO Header
if(ret) {
uint8_t buf[3] = { eIOtype_MESSAGE, sIOtype_EVENT, 0x00 };
ret = WebSocketsClient::write(&_client, buf, 2);
}
if(ret) {
ret = WebSocketsClient::write(&_client, payload, length );
}
return ret;
} else {
// TODO implement
}
// return WebSocketsClient::sendFrame(&_client, WSop_text, payload, length, true, true, headerToPayload);
}
return false;
}
bool SocketIOclient::sendEVENT(const uint8_t * payload, size_t length) {
return sendEVENT((uint8_t *) payload, length);
}
bool SocketIOclient::sendEVENT(char * payload, size_t length, bool headerToPayload) {
return sendEVENT((uint8_t *) payload, length, headerToPayload);
}
bool SocketIOclient::sendEVENT(const char * payload, size_t length) {
return sendEVENT((uint8_t *) payload, length);
}
bool SocketIOclient::sendEVENT(String & payload) {
return sendEVENT((uint8_t *) payload.c_str(), payload.length());
}
void SocketIOclient::loop(void) { void SocketIOclient::loop(void) {
WebSocketsClient::loop(); WebSocketsClient::loop();
unsigned long t = millis(); unsigned long t = millis();
if((t - _lastConnectionFail) > EIO_HEARTBEAT_INTERVAL) { if((t - _lastConnectionFail) > EIO_HEARTBEAT_INTERVAL) {
_lastConnectionFail = t; _lastConnectionFail = t;
sendTXT(eIOtype_PING); //WebSocketsClient::sendTXT(eIOtype_PING);
} }
} }
@ -43,7 +99,7 @@ void SocketIOclient::runCbEvent(WStype_t type, uint8_t * payload, size_t length)
DEBUG_WEBSOCKETS("[wsIOc] Connected to url: %s\n", payload); DEBUG_WEBSOCKETS("[wsIOc] Connected to url: %s\n", payload);
// send message to server when Connected // send message to server when Connected
// Engine.io upgrade confirmation message (required) // Engine.io upgrade confirmation message (required)
sendTXT(eIOtype_UPGRADE); WebSocketsClient::sendTXT(eIOtype_UPGRADE);
} }
break; break;
case WStype_TEXT: { case WStype_TEXT: {
@ -57,7 +113,7 @@ void SocketIOclient::runCbEvent(WStype_t type, uint8_t * payload, size_t length)
case eIOtype_PING: case eIOtype_PING:
payload[0] = eIOtype_PONG; payload[0] = eIOtype_PONG;
DEBUG_WEBSOCKETS("[wsIOc] get ping send pong (%s)\n", payload); DEBUG_WEBSOCKETS("[wsIOc] get ping send pong (%s)\n", payload);
sendTXT(payload, length); WebSocketsClient::sendTXT(payload, length, false);
break; break;
case eIOtype_PONG: case eIOtype_PONG:
DEBUG_WEBSOCKETS("[wsIOc] get pong\n"); DEBUG_WEBSOCKETS("[wsIOc] get pong\n");

View File

@ -12,6 +12,9 @@
#define EIO_HEARTBEAT_INTERVAL 10000 #define EIO_HEARTBEAT_INTERVAL 10000
#define EIO_MAX_HEADER_SIZE (WEBSOCKETS_MAX_HEADER_SIZE + 1)
#define SIO_MAX_HEADER_SIZE (EIO_MAX_HEADER_SIZE + 1)
typedef enum { typedef enum {
eIOtype_OPEN = '0', ///< Sent from the server when a new transport is opened (recheck) eIOtype_OPEN = '0', ///< Sent from the server when a new transport is opened (recheck)
eIOtype_CLOSE = '1', ///< Request the close of this transport but does not shutdown the connection itself. eIOtype_CLOSE = '1', ///< Request the close of this transport but does not shutdown the connection itself.
@ -33,7 +36,7 @@ typedef enum {
sIOtype_BINARY_ACK = '6', sIOtype_BINARY_ACK = '6',
} socketIOmessageType_t; } socketIOmessageType_t;
class SocketIOclient: private WebSocketsClient { class SocketIOclient: protected WebSocketsClient {
public: public:
#ifdef __AVR__ #ifdef __AVR__
@ -48,9 +51,17 @@ class SocketIOclient: private WebSocketsClient {
void begin(const char *host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino"); void begin(const char *host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
void begin(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino"); void begin(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
bool isConnected(void);
bool sendEVENT(uint8_t * payload, size_t length = 0, bool headerToPayload = false);
bool sendEVENT(const uint8_t * payload, size_t length = 0);
bool sendEVENT(char * payload, size_t length = 0, bool headerToPayload = false);
bool sendEVENT(const char * payload, size_t length = 0);
bool sendEVENT(String & payload);
void loop(void); void loop(void);
private:
protected:
void runCbEvent(WStype_t type, uint8_t * payload, size_t length); void runCbEvent(WStype_t type, uint8_t * payload, size_t length);
uint64_t _lastHeartbeat = 0; uint64_t _lastHeartbeat = 0;
}; };

View File

@ -71,6 +71,115 @@ void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * rea
clientDisconnect(client); clientDisconnect(client);
} }
/**
*
* @param buf uint8_t * ptr to the buffer for writing
* @param opcode WSopcode_t
* @param length size_t length of the payload
* @param mask bool add dummy mask to the frame (needed for web browser)
* @param maskkey uint8_t[4] key used for payload
* @param fin bool can be used to send data in more then one frame (set fin on the last frame)
*/
uint8_t WebSockets::createHeader(uint8_t * headerPtr, WSopcode_t opcode, size_t length, bool mask, uint8_t maskKey[4], bool fin) {
uint8_t headerSize;
// calculate header Size
if(length < 126) {
headerSize = 2;
} else if(length < 0xFFFF) {
headerSize = 4;
} else {
headerSize = 10;
}
if(mask) {
headerSize += 4;
}
// create header
// byte 0
*headerPtr = 0x00;
if(fin) {
*headerPtr |= bit(7); ///< set Fin
}
*headerPtr |= opcode; ///< set opcode
headerPtr++;
// byte 1
*headerPtr = 0x00;
if(mask) {
*headerPtr |= bit(7); ///< set mask
}
if(length < 126) {
*headerPtr |= length;
headerPtr++;
} else if(length < 0xFFFF) {
*headerPtr |= 126;
headerPtr++;
*headerPtr = ((length >> 8) & 0xFF);
headerPtr++;
*headerPtr = (length & 0xFF);
headerPtr++;
} else {
// Normally we never get here (to less memory)
*headerPtr |= 127;
headerPtr++;
*headerPtr = 0x00;
headerPtr++;
*headerPtr = 0x00;
headerPtr++;
*headerPtr = 0x00;
headerPtr++;
*headerPtr = 0x00;
headerPtr++;
*headerPtr = ((length >> 24) & 0xFF);
headerPtr++;
*headerPtr = ((length >> 16) & 0xFF);
headerPtr++;
*headerPtr = ((length >> 8) & 0xFF);
headerPtr++;
*headerPtr = (length & 0xFF);
headerPtr++;
}
if(mask) {
*headerPtr = maskKey[0];
headerPtr++;
*headerPtr = maskKey[1];
headerPtr++;
*headerPtr = maskKey[2];
headerPtr++;
*headerPtr = maskKey[3];
headerPtr++;
}
return headerSize;
}
/**
*
* @param client WSclient_t * ptr to the client struct
* @param opcode WSopcode_t
* @param length size_t length of the payload
* @param mask bool add dummy mask to the frame (needed for web browser)
* @param fin bool can be used to send data in more then one frame (set fin on the last frame)
* @return true if ok
*/
bool WebSockets::sendFrameHeader(WSclient_t * client, WSopcode_t opcode, size_t length, bool mask, bool fin) {
uint8_t maskKey[4] = { 0x00, 0x00, 0x00, 0x00 };
uint8_t buffer[WEBSOCKETS_MAX_HEADER_SIZE] = { 0 };
uint8_t headerSize = createHeader(&buffer[0], opcode, length, mask, maskKey, fin);
if(write(client, &buffer[0], headerSize) != headerSize) {
return false;
}
return true;
}
/** /**
* *
* @param client WSclient_t * ptr to the client struct * @param client WSclient_t * ptr to the client struct
@ -146,53 +255,7 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
headerPtr = &buffer[0]; headerPtr = &buffer[0];
} }
// create header createHeader(headerPtr, opcode, length, mask, maskKey, fin);
// byte 0
*headerPtr = 0x00;
if(fin) {
*headerPtr |= bit(7); ///< set Fin
}
*headerPtr |= opcode; ///< set opcode
headerPtr++;
// byte 1
*headerPtr = 0x00;
if(mask) {
*headerPtr |= bit(7); ///< set mask
}
if(length < 126) {
*headerPtr |= length;
headerPtr++;
} else if(length < 0xFFFF) {
*headerPtr |= 126;
headerPtr++;
*headerPtr = ((length >> 8) & 0xFF);
headerPtr++;
*headerPtr = (length & 0xFF);
headerPtr++;
} else {
// Normally we never get here (to less memory)
*headerPtr |= 127;
headerPtr++;
*headerPtr = 0x00;
headerPtr++;
*headerPtr = 0x00;
headerPtr++;
*headerPtr = 0x00;
headerPtr++;
*headerPtr = 0x00;
headerPtr++;
*headerPtr = ((length >> 24) & 0xFF);
headerPtr++;
*headerPtr = ((length >> 16) & 0xFF);
headerPtr++;
*headerPtr = ((length >> 8) & 0xFF);
headerPtr++;
*headerPtr = (length & 0xFF);
headerPtr++;
}
if(mask) { if(mask) {
if(useInternBuffer) { if(useInternBuffer) {
@ -200,8 +263,6 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
// by this fact its possible the do the masking // by this fact its possible the do the masking
for(uint8_t x = 0; x < sizeof(maskKey); x++) { for(uint8_t x = 0; x < sizeof(maskKey); x++) {
maskKey[x] = random(0xFF); maskKey[x] = random(0xFF);
*headerPtr = maskKey[x];
headerPtr++;
} }
uint8_t * dataMaskPtr; uint8_t * dataMaskPtr;
@ -215,16 +276,6 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
for(size_t x = 0; x < length; x++) { for(size_t x = 0; x < length; x++) {
dataMaskPtr[x] = (dataMaskPtr[x] ^ maskKey[x % 4]); dataMaskPtr[x] = (dataMaskPtr[x] ^ maskKey[x % 4]);
} }
} else {
*headerPtr = maskKey[0];
headerPtr++;
*headerPtr = maskKey[1];
headerPtr++;
*headerPtr = maskKey[2];
headerPtr++;
*headerPtr = maskKey[3];
headerPtr++;
} }
} }

View File

@ -285,6 +285,9 @@ class WebSockets {
virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) = 0; virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) = 0;
void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0); void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0);
uint8_t createHeader(uint8_t * buf, WSopcode_t opcode, size_t length, bool mask, uint8_t maskKey[4], bool fin);
bool sendFrameHeader(WSclient_t * client, WSopcode_t opcode, size_t length = 0, bool mask = false, bool fin = true);
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); 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);
void headerDone(WSclient_t * client); void headerDone(WSclient_t * client);

View File

@ -310,6 +310,10 @@ void WebSocketsClient::setReconnectInterval(unsigned long time) {
_reconnectInterval = time; _reconnectInterval = time;
} }
bool WebSocketsClient::isConnected(void) {
return (_client.status == WSC_CONNECTED);
}
//################################################################################# //#################################################################################
//################################################################################# //#################################################################################
//################################################################################# //#################################################################################
@ -666,6 +670,13 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
runCbEvent(WStype_CONNECTED, (uint8_t *) client->cUrl.c_str(), client->cUrl.length()); runCbEvent(WStype_CONNECTED, (uint8_t *) client->cUrl.c_str(), client->cUrl.length());
} else if(clientIsConnected(client) && client->isSocketIO && client->cSessionId.length() > 0) { } else if(clientIsConnected(client) && client->isSocketIO && client->cSessionId.length() > 0) {
if(_client.tcp->available()) {
// read not needed data
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] still data in buffer (%d), clean up.\n", _client.tcp->available());
while(_client.tcp->available() > 0) {
_client.tcp->read();
}
}
sendHeader(client); sendHeader(client);
} else { } else {
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n"); DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");

View File

@ -27,7 +27,7 @@
#include "WebSockets.h" #include "WebSockets.h"
class WebSocketsClient: private WebSockets { class WebSocketsClient: protected WebSockets {
public: public:
#ifdef __AVR__ #ifdef __AVR__
typedef void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length); typedef void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length);
@ -87,6 +87,8 @@ class WebSocketsClient: private WebSockets {
void setReconnectInterval(unsigned long time); void setReconnectInterval(unsigned long time);
bool isConnected(void);
protected: protected:
String _host; String _host;
uint16_t _port; uint16_t _port;