diff --git a/examples/WebSocketClientStomp/WebSocketClientStomp.ino b/examples/WebSocketClientStomp/WebSocketClientStomp.ino new file mode 100644 index 0000000..a0eb011 --- /dev/null +++ b/examples/WebSocketClientStomp/WebSocketClientStomp.ino @@ -0,0 +1,149 @@ +/* + WebSocketClientStomp.ino + + Example for connecting and maintining a connection with a STOMP websocket connection. + In this example, we connect to a Spring application (see https://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html). + + Created on: 25.09.2017 + Author: Martin Becker , Contact: becker@informatik.uni-wuerzburg.de +*/ + +// PRE + +#define USE_SERIAL Serial + + +// LIBRARIES + +#include +#include + +#include +#include + + +// SETTINGS + +const char* wlan_ssid = "yourssid"; +const char* wlan_password = "somepassword"; + +const char* ws_host = "the.host.net"; +const int ws_port = 80; + +// URL for STOMP endpoint. +// For the default config of Spring's STOMP support, the default URL is "/socketentry/websocket". +const char* stompUrl = "/socketentry/websocket"; // don't forget the leading "/" !!! + + +// VARIABLES + +WebSocketsClient webSocket; + + +// FUNCTIONS + +/** + * STOMP messages need to be NULL-terminated (i.e., \0 or \u0000). + * However, when we send a String or a char[] array without specifying + * a length, the size of the message payload is derived by strlen() internally, + * thus dropping any NULL values appended to the "msg"-String. + * + * To solve this, we first convert the String to a NULL terminated char[] array + * via "c_str" and set the length of the payload to include the NULL value. + */ +void sendMessage(String & msg) { + webSocket.sendTXT(msg.c_str(), msg.length() + 1); +} + +void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { + + switch (type) { + case WStype_DISCONNECTED: + USE_SERIAL.printf("[WSc] Disconnected!\n"); + break; + case WStype_CONNECTED: + { + USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); + + String msg = "CONNECT\r\naccept-version:1.1,1.0\r\nheart-beat:10000,10000\r\n\r\n"; + sendMessage(msg); + } + break; + case WStype_TEXT: + { + // ##################### + // handle STOMP protocol + // ##################### + + String text = (char*) payload; + USE_SERIAL.printf("[WSc] get text: %s\n", payload); + + if (text.startsWith("CONNECTED")) { + + // subscribe to some channels + + String msg = "SUBSCRIBE\nid:sub-0\ndestination:/user/queue/messages\n\n"; + sendMessage(msg); + delay(1000); + + // and send a message + + msg = "SEND\ndestination:/app/message\n\n{\"user\":\"esp\",\"message\":\"Hello!\"}"; + sendMessage(msg); + delay(1000); + + } else { + + // do something with messages + + } + + break; + } + case WStype_BIN: + USE_SERIAL.printf("[WSc] get binary length: %u\n", length); + hexdump(payload, length); + + // send data to server + // webSocket.sendBIN(payload, length); + break; + } + +} + +void setup() { + + // setup serial + + // USE_SERIAL.begin(921600); + USE_SERIAL.begin(115200); + + // USE_SERIAL.setDebugOutput(true); + + USE_SERIAL.println(); + + + // connect to WiFi + + USE_SERIAL.print("Logging into WLAN: "); Serial.print(wlan_ssid); Serial.print(" ..."); + WiFi.mode(WIFI_STA); + WiFi.begin(wlan_ssid, wlan_password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + USE_SERIAL.print("."); + } + USE_SERIAL.println(" success."); + USE_SERIAL.print("IP: "); USE_SERIAL.println(WiFi.localIP()); + + + // connect to websocket + webSocket.begin(ws_host, ws_port, stompUrl); + webSocket.setExtraHeaders(); // remove "Origin: file://" header because it breaks the connection with Spring's default websocket config + // webSocket.setExtraHeaders("foo: I am so funny\r\nbar: not"); // some headers, in case you feel funny + webSocket.onEvent(webSocketEvent); +} + +void loop() { + webSocket.loop(); +} diff --git a/examples/WebSocketClientSockJsAndStomp/WebSocketClientSockJsAndStomp.ino b/examples/WebSocketClientStompOverSockJs/WebSocketClientStompOverSockJs.ino similarity index 92% rename from examples/WebSocketClientSockJsAndStomp/WebSocketClientSockJsAndStomp.ino rename to examples/WebSocketClientStompOverSockJs/WebSocketClientStompOverSockJs.ino index 493a949..cb0c45b 100644 --- a/examples/WebSocketClientSockJsAndStomp/WebSocketClientSockJsAndStomp.ino +++ b/examples/WebSocketClientStompOverSockJs/WebSocketClientStompOverSockJs.ino @@ -1,8 +1,8 @@ /* - WebSocketClientSockJsAndStomp.ino + WebSocketClientStompOverSockJs.ino Example for connecting and maintining a connection with a SockJS+STOMP websocket connection. - In this example we connect to a Spring application (see https://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html). + In this example, we connect to a Spring application (see https://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html). Created on: 18.07.2017 Author: Martin Becker , Contact: becker@informatik.uni-wuerzburg.de @@ -33,7 +33,7 @@ const int ws_port = 80; // base URL for SockJS (websocket) connection // The complete URL will look something like this(cf. http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html#section-36): // ws://://<3digits>//websocket -// For the default config of Spring's SockJS/STOMP support the default base URL is "/socketentry/". +// For the default config of Spring's SockJS/STOMP support, the default base URL is "/socketentry/". const char* ws_baseurl = "/socketentry/"; // don't forget leading and trailing "/" !!! @@ -58,7 +58,7 @@ void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { case WStype_TEXT: { // ##################### - // handle STOMP protocol + // handle SockJs+STOMP protocol // ##################### String text = (char*) payload; diff --git a/examples/WebSocketServer_LEDcontrol/WebSocketServer_LEDcontrol.ino b/examples/WebSocketServer_LEDcontrol/WebSocketServer_LEDcontrol.ino index f737d7f..913b799 100644 --- a/examples/WebSocketServer_LEDcontrol/WebSocketServer_LEDcontrol.ino +++ b/examples/WebSocketServer_LEDcontrol/WebSocketServer_LEDcontrol.ino @@ -23,7 +23,7 @@ ESP8266WiFiMulti WiFiMulti; -ESP8266WebServer server = ESP8266WebServer(80); +ESP8266WebServer server(80); WebSocketsServer webSocket = WebSocketsServer(81); void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { diff --git a/src/WebSockets.cpp b/src/WebSockets.cpp index 254e3cd..44ddbb1 100644 --- a/src/WebSockets.cpp +++ b/src/WebSockets.cpp @@ -48,12 +48,13 @@ extern "C" { #endif + /** * * @param client WSclient_t * ptr to the client struct * @param code uint16_t see RFC - * @param reason - * @param reasonLen + * @param reason ptr to the disconnect reason message + * @param reasonLen length of the disconnect reason message */ void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * reason, size_t reasonLen) { DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] clientDisconnect code: %u\n", client->num, code); @@ -74,8 +75,8 @@ void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * rea * * @param client WSclient_t * ptr to the client struct * @param opcode WSopcode_t - * @param payload uint8_t * - * @param length size_t + * @param payload uint8_t * ptr to the payload + * @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) * @param headerToPayload bool set true if the payload has reserved 14 Byte at the beginning to dynamically add the Header (payload neet to be in RAM!) @@ -93,7 +94,7 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay return false; } - DEBUG_WEBSOCKETS("[WS][%d][sendFrame] ------- send massage frame -------\n", client->num); + DEBUG_WEBSOCKETS("[WS][%d][sendFrame] ------- send message frame -------\n", client->num); DEBUG_WEBSOCKETS("[WS][%d][sendFrame] fin: %u opCode: %u mask: %u length: %u headerToPayload: %u\n", client->num, fin, opcode, mask, length, headerToPayload); if(opcode == WSop_text) { diff --git a/src/WebSocketsClient.cpp b/src/WebSocketsClient.cpp index 2c154dd..68e24fa 100644 --- a/src/WebSocketsClient.cpp +++ b/src/WebSocketsClient.cpp @@ -373,7 +373,6 @@ void WebSocketsClient::clientDisconnect(WSclient_t * client) { client->cCode = 0; client->cKey = ""; client->cAccept = ""; - client->cProtocol = ""; client->cVersion = 0; client->cIsUpgrade = false; client->cIsWebsocket = false; diff --git a/src/WebSocketsClient.h b/src/WebSocketsClient.h index 2560e47..b56cff8 100644 --- a/src/WebSocketsClient.h +++ b/src/WebSocketsClient.h @@ -37,7 +37,7 @@ class WebSocketsClient: private WebSockets { WebSocketsClient(void); - ~WebSocketsClient(void); + virtual ~WebSocketsClient(void); void begin(const char *host, uint16_t port, const char * url = "/", const char * protocol = "arduino"); void begin(String host, uint16_t port, String url = "/", String protocol = "arduino"); diff --git a/src/WebSocketsServer.cpp b/src/WebSocketsServer.cpp index 40c24f5..1e60f97 100644 --- a/src/WebSocketsServer.cpp +++ b/src/WebSocketsServer.cpp @@ -43,6 +43,8 @@ WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol _httpHeaderValidationFunc = NULL; _mandatoryHttpHeaders = NULL; _mandatoryHttpHeaderCount = 0; + + memset(&_clients[0], 0x00, (sizeof(WSclient_t) * WEBSOCKETS_SERVER_CLIENT_MAX)); } diff --git a/src/WebSocketsServer.h b/src/WebSocketsServer.h index 72169df..cd38fd6 100644 --- a/src/WebSocketsServer.h +++ b/src/WebSocketsServer.h @@ -44,7 +44,7 @@ class WebSocketsServer: protected WebSockets { #endif WebSocketsServer(uint16_t port, String origin = "", String protocol = "arduino"); - ~WebSocketsServer(void); + virtual ~WebSocketsServer(void); void begin(void);