From 2bd58c26983b108ac079034f70d6c8583f8d697b Mon Sep 17 00:00:00 2001 From: david gauchard Date: Mon, 10 Aug 2020 19:20:42 +0200 Subject: [PATCH 1/9] hook: split WebSocketsServer --- .../WebSocketServerHooked.ino | 89 +++++++++ src/WebSocketsServer.cpp | 178 ++++++++++-------- src/WebSocketsServer.h | 52 +++-- 3 files changed, 221 insertions(+), 98 deletions(-) create mode 100644 examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino diff --git a/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino b/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino new file mode 100644 index 0000000..306a8bf --- /dev/null +++ b/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino @@ -0,0 +1,89 @@ +/* + * WebSocketServer.ino + * + * Created on: 22.05.2015 + * + */ + +#include + +#include +#include +#include +#include + +ESP8266WiFiMulti WiFiMulti; + +ESP8266WebServer server(80); +WebSockets4WebServer webSocket; + +#define USE_SERIAL Serial + +void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { + + switch(type) { + case WStype_DISCONNECTED: + USE_SERIAL.printf("[%u] Disconnected!\n", num); + break; + case WStype_CONNECTED: + { + IPAddress ip = webSocket.remoteIP(num); + USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); + + // send message to client + webSocket.sendTXT(num, "Connected"); + } + break; + case WStype_TEXT: + USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); + + // send message to client + // webSocket.sendTXT(num, "message here"); + + // send data to all connected clients + // webSocket.broadcastTXT("message here"); + break; + case WStype_BIN: + USE_SERIAL.printf("[%u] get binary length: %u\n", num, length); + hexdump(payload, length); + + // send message to client + // webSocket.sendBIN(num, payload, length); + break; + } + +} + +void setup() { + // USE_SERIAL.begin(921600); + USE_SERIAL.begin(115200); + + //Serial.setDebugOutput(true); + USE_SERIAL.setDebugOutput(true); + + USE_SERIAL.println(); + USE_SERIAL.println(); + USE_SERIAL.println(); + + for(uint8_t t = 4; t > 0; t--) { + USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); + USE_SERIAL.flush(); + delay(1000); + } + + WiFiMulti.addAP("SSID", "passpasspass"); + + while(WiFiMulti.run() != WL_CONNECTED) { + delay(100); + } + + server.addHook(webSocket.hookForWebserver(webSocketEvent)); + server.begin(); + Serial.println("HTTP server started"); + Serial.println("WebSocket server started onthe same port"); +} + +void loop() { + server.handleClient(); +} + diff --git a/src/WebSocketsServer.cpp b/src/WebSocketsServer.cpp index a682ec9..c648dbf 100644 --- a/src/WebSocketsServer.cpp +++ b/src/WebSocketsServer.cpp @@ -25,8 +25,7 @@ #include "WebSockets.h" #include "WebSocketsServer.h" -WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol) { - _port = port; +WebSocketsServerCore::WebSocketsServerCore(const String& origin, const String& protocol) { _origin = origin; _protocol = protocol; _runnning = false; @@ -34,15 +33,6 @@ WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol _pongTimeout = 0; _disconnectTimeoutCount = 0; - _server = new WEBSOCKETS_NETWORK_SERVER_CLASS(port); - -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) - _server->onClient([](void * s, AsyncClient * c) { - ((WebSocketsServer *)s)->newClient(new AsyncTCPbuffer(c)); - }, - this); -#endif - _cbEvent = NULL; _httpHeaderValidationFunc = NULL; @@ -52,7 +42,21 @@ WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol memset(&_clients[0], 0x00, (sizeof(WSclient_t) * WEBSOCKETS_SERVER_CLIENT_MAX)); } -WebSocketsServer::~WebSocketsServer() { +WebSocketsServer::WebSocketsServer(uint16_t port, const String& origin, const String& protocol): + WebSocketsServerCore(origin, protocol) { + _port = port; + + _server = new WEBSOCKETS_NETWORK_SERVER_CLASS(port); + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + _server->onClient([](void * s, AsyncClient * c) { + ((WebSocketsServerCore *)s)->newClient(new AsyncTCPbuffer(c)); + }, + this); +#endif +} + +WebSocketsServerCore::~WebSocketsServerCore() { // disconnect all clients close(); @@ -65,7 +69,7 @@ WebSocketsServer::~WebSocketsServer() { /** * called to initialize the Websocket server */ -void WebSocketsServer::begin(void) { +void WebSocketsServerCore::begin(void) { WSclient_t * client; // init client storage @@ -111,43 +115,18 @@ void WebSocketsServer::begin(void) { #endif _runnning = true; - _server->begin(); - - DEBUG_WEBSOCKETS("[WS-Server] Server Started.\n"); } -void WebSocketsServer::close(void) { +void WebSocketsServerCore::close(void) { _runnning = false; disconnect(); - -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) - _server->close(); -#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) - _server->end(); -#else - // TODO how to close server? -#endif } -#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) -/** - * called in arduino loop - */ -void WebSocketsServer::loop(void) { - if(_runnning) { - WEBSOCKETS_YIELD(); - handleNewClients(); - WEBSOCKETS_YIELD(); - handleClientData(); - } -} -#endif - /** * set callback function * @param cbEvent WebSocketServerEvent */ -void WebSocketsServer::onEvent(WebSocketServerEvent cbEvent) { +void WebSocketsServerCore::onEvent(WebSocketServerEvent cbEvent) { _cbEvent = cbEvent; } @@ -157,7 +136,7 @@ void WebSocketsServer::onEvent(WebSocketServerEvent cbEvent) { * @param mandatoryHttpHeaders[] const char* ///< the array of named http headers considered to be mandatory / must be present in order for websocket upgrade to succeed * @param mandatoryHttpHeaderCount size_t ///< the number of items in the mandatoryHttpHeaders array */ -void WebSocketsServer::onValidateHttpHeader( +void WebSocketsServerCore::onValidateHttpHeader( WebSocketServerHttpHeaderValFunc validationFunc, const char * mandatoryHttpHeaders[], size_t mandatoryHttpHeaderCount) { @@ -182,7 +161,7 @@ void WebSocketsServer::onValidateHttpHeader( * @param headerToPayload bool (see sendFrame for more details) * @return true if ok */ -bool WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) { +bool WebSocketsServerCore::sendTXT(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) { if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) { return false; } @@ -196,19 +175,19 @@ bool WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bo return false; } -bool WebSocketsServer::sendTXT(uint8_t num, const uint8_t * payload, size_t length) { +bool WebSocketsServerCore::sendTXT(uint8_t num, const uint8_t * payload, size_t length) { return sendTXT(num, (uint8_t *)payload, length); } -bool WebSocketsServer::sendTXT(uint8_t num, char * payload, size_t length, bool headerToPayload) { +bool WebSocketsServerCore::sendTXT(uint8_t num, char * payload, size_t length, bool headerToPayload) { return sendTXT(num, (uint8_t *)payload, length, headerToPayload); } -bool WebSocketsServer::sendTXT(uint8_t num, const char * payload, size_t length) { +bool WebSocketsServerCore::sendTXT(uint8_t num, const char * payload, size_t length) { return sendTXT(num, (uint8_t *)payload, length); } -bool WebSocketsServer::sendTXT(uint8_t num, String & payload) { +bool WebSocketsServerCore::sendTXT(uint8_t num, String & payload) { return sendTXT(num, (uint8_t *)payload.c_str(), payload.length()); } @@ -219,7 +198,7 @@ bool WebSocketsServer::sendTXT(uint8_t num, String & payload) { * @param headerToPayload bool (see sendFrame for more details) * @return true if ok */ -bool WebSocketsServer::broadcastTXT(uint8_t * payload, size_t length, bool headerToPayload) { +bool WebSocketsServerCore::broadcastTXT(uint8_t * payload, size_t length, bool headerToPayload) { WSclient_t * client; bool ret = true; if(length == 0) { @@ -238,19 +217,19 @@ bool WebSocketsServer::broadcastTXT(uint8_t * payload, size_t length, bool heade return ret; } -bool WebSocketsServer::broadcastTXT(const uint8_t * payload, size_t length) { +bool WebSocketsServerCore::broadcastTXT(const uint8_t * payload, size_t length) { return broadcastTXT((uint8_t *)payload, length); } -bool WebSocketsServer::broadcastTXT(char * payload, size_t length, bool headerToPayload) { +bool WebSocketsServerCore::broadcastTXT(char * payload, size_t length, bool headerToPayload) { return broadcastTXT((uint8_t *)payload, length, headerToPayload); } -bool WebSocketsServer::broadcastTXT(const char * payload, size_t length) { +bool WebSocketsServerCore::broadcastTXT(const char * payload, size_t length) { return broadcastTXT((uint8_t *)payload, length); } -bool WebSocketsServer::broadcastTXT(String & payload) { +bool WebSocketsServerCore::broadcastTXT(String & payload) { return broadcastTXT((uint8_t *)payload.c_str(), payload.length()); } @@ -262,7 +241,7 @@ bool WebSocketsServer::broadcastTXT(String & payload) { * @param headerToPayload bool (see sendFrame for more details) * @return true if ok */ -bool WebSocketsServer::sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) { +bool WebSocketsServerCore::sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) { if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) { return false; } @@ -273,7 +252,7 @@ bool WebSocketsServer::sendBIN(uint8_t num, uint8_t * payload, size_t length, bo return false; } -bool WebSocketsServer::sendBIN(uint8_t num, const uint8_t * payload, size_t length) { +bool WebSocketsServerCore::sendBIN(uint8_t num, const uint8_t * payload, size_t length) { return sendBIN(num, (uint8_t *)payload, length); } @@ -284,7 +263,7 @@ bool WebSocketsServer::sendBIN(uint8_t num, const uint8_t * payload, size_t leng * @param headerToPayload bool (see sendFrame for more details) * @return true if ok */ -bool WebSocketsServer::broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload) { +bool WebSocketsServerCore::broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload) { WSclient_t * client; bool ret = true; for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { @@ -299,7 +278,7 @@ bool WebSocketsServer::broadcastBIN(uint8_t * payload, size_t length, bool heade return ret; } -bool WebSocketsServer::broadcastBIN(const uint8_t * payload, size_t length) { +bool WebSocketsServerCore::broadcastBIN(const uint8_t * payload, size_t length) { return broadcastBIN((uint8_t *)payload, length); } @@ -310,7 +289,7 @@ bool WebSocketsServer::broadcastBIN(const uint8_t * payload, size_t length) { * @param length size_t * @return true if ping is send out */ -bool WebSocketsServer::sendPing(uint8_t num, uint8_t * payload, size_t length) { +bool WebSocketsServerCore::sendPing(uint8_t num, uint8_t * payload, size_t length) { if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) { return false; } @@ -321,7 +300,7 @@ bool WebSocketsServer::sendPing(uint8_t num, uint8_t * payload, size_t length) { return false; } -bool WebSocketsServer::sendPing(uint8_t num, String & payload) { +bool WebSocketsServerCore::sendPing(uint8_t num, String & payload) { return sendPing(num, (uint8_t *)payload.c_str(), payload.length()); } @@ -331,7 +310,7 @@ bool WebSocketsServer::sendPing(uint8_t num, String & payload) { * @param length size_t * @return true if ping is send out */ -bool WebSocketsServer::broadcastPing(uint8_t * payload, size_t length) { +bool WebSocketsServerCore::broadcastPing(uint8_t * payload, size_t length) { WSclient_t * client; bool ret = true; for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { @@ -346,14 +325,14 @@ bool WebSocketsServer::broadcastPing(uint8_t * payload, size_t length) { return ret; } -bool WebSocketsServer::broadcastPing(String & payload) { +bool WebSocketsServerCore::broadcastPing(String & payload) { return broadcastPing((uint8_t *)payload.c_str(), payload.length()); } /** * disconnect all clients */ -void WebSocketsServer::disconnect(void) { +void WebSocketsServerCore::disconnect(void) { WSclient_t * client; for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { client = &_clients[i]; @@ -367,7 +346,7 @@ void WebSocketsServer::disconnect(void) { * disconnect one client * @param num uint8_t client id */ -void WebSocketsServer::disconnect(uint8_t num) { +void WebSocketsServerCore::disconnect(uint8_t num) { if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) { return; } @@ -382,7 +361,7 @@ void WebSocketsServer::disconnect(uint8_t num) { * @param user const char * * @param password const char * */ -void WebSocketsServer::setAuthorization(const char * user, const char * password) { +void WebSocketsServerCore::setAuthorization(const char * user, const char * password) { if(user && password) { String auth = user; auth += ":"; @@ -395,7 +374,7 @@ void WebSocketsServer::setAuthorization(const char * user, const char * password * set the Authorizatio for the http request * @param auth const char * base64 */ -void WebSocketsServer::setAuthorization(const char * auth) { +void WebSocketsServerCore::setAuthorization(const char * auth) { if(auth) { _base64Authorization = auth; } @@ -405,7 +384,7 @@ void WebSocketsServer::setAuthorization(const char * auth) { * count the connected clients (optional ping them) * @param ping bool ping the connected clients */ -int WebSocketsServer::connectedClients(bool ping) { +int WebSocketsServerCore::connectedClients(bool ping) { WSclient_t * client; int count = 0; for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { @@ -425,7 +404,7 @@ int WebSocketsServer::connectedClients(bool ping) { * @param num uint8_t client id * @return IPAddress */ -IPAddress WebSocketsServer::remoteIP(uint8_t num) { +IPAddress WebSocketsServerCore::remoteIP(uint8_t num) { if(num < WEBSOCKETS_SERVER_CLIENT_MAX) { WSclient_t * client = &_clients[num]; if(clientIsConnected(client)) { @@ -445,7 +424,7 @@ IPAddress WebSocketsServer::remoteIP(uint8_t num) { * handle new client connection * @param client */ -bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) { +bool WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) { WSclient_t * client; // search free list entry for client for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { @@ -474,7 +453,7 @@ bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) { #endif #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) - client->tcp->onDisconnect(std::bind([](WebSocketsServer * server, AsyncTCPbuffer * obj, WSclient_t * client) -> bool { + client->tcp->onDisconnect(std::bind([](WebSocketsServerCore * server, AsyncTCPbuffer * obj, WSclient_t * client) -> bool { DEBUG_WEBSOCKETS("[WS-Server][%d] Disconnect client\n", client->num); AsyncTCPbuffer ** sl = &server->_clients[client->num].tcp; @@ -486,7 +465,7 @@ bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) { }, this, std::placeholders::_1, client)); - client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServer::handleHeader, this, client, &(client->cHttpLine))); + client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServerCore::handleHeader, this, client, &(client->cHttpLine))); #endif client->pingInterval = _pingInterval; @@ -509,7 +488,7 @@ bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) { * @param payload uint8_t * * @param length size_t */ -void WebSocketsServer::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) { +void WebSocketsServerCore::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) { WStype_t type = WStype_ERROR; switch(opcode) { @@ -540,7 +519,7 @@ void WebSocketsServer::messageReceived(WSclient_t * client, WSopcode_t opcode, u * Disconnect an client * @param client WSclient_t * ptr to the client struct */ -void WebSocketsServer::clientDisconnect(WSclient_t * client) { +void WebSocketsServerCore::clientDisconnect(WSclient_t * client) { #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) if(client->isSSL && client->ssl) { if(client->ssl->connected()) { @@ -593,7 +572,7 @@ void WebSocketsServer::clientDisconnect(WSclient_t * client) { * @param client WSclient_t * ptr to the client struct * @return true = connected */ -bool WebSocketsServer::clientIsConnected(WSclient_t * client) { +bool WebSocketsServerCore::clientIsConnected(WSclient_t * client) { if(!client->tcp) { return false; } @@ -665,7 +644,7 @@ void WebSocketsServer::handleNewClients(void) { /** * Handel incomming data from Client */ -void WebSocketsServer::handleClientData(void) { +void WebSocketsServerCore::handleClientData(void) { WSclient_t * client; for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { client = &_clients[i]; @@ -699,7 +678,7 @@ void WebSocketsServer::handleClientData(void) { * returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection * @param headerName String ///< the name of the header being checked */ -bool WebSocketsServer::hasMandatoryHeader(String headerName) { +bool WebSocketsServerCore::hasMandatoryHeader(String headerName) { for(size_t i = 0; i < _mandatoryHttpHeaderCount; i++) { if(_mandatoryHttpHeaders[i].equalsIgnoreCase(headerName)) return true; @@ -712,7 +691,7 @@ bool WebSocketsServer::hasMandatoryHeader(String headerName) { * @param client WSclient_t * ///< pointer to the client struct * @param headerLine String ///< the header being read / processed */ -void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) { +void WebSocketsServerCore::handleHeader(WSclient_t * client, String * headerLine) { static const char * NEW_LINE = "\r\n"; headerLine->trim(); // remove \r @@ -771,7 +750,7 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) { (*headerLine) = ""; #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) - client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServer::handleHeader, this, client, &(client->cHttpLine))); + client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServerCore::handleHeader, this, client, &(client->cHttpLine))); #endif } else { DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Header read fin.\n", client->num); @@ -828,7 +807,7 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) { String handshake = WEBSOCKETS_STRING( "HTTP/1.1 101 Switching Protocols\r\n" - "Server: arduino-WebSocketsServer\r\n" + "Server: arduino-WebSocketsServerCore\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Version: 13\r\n" @@ -868,7 +847,7 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) { /** * send heartbeat ping to server in set intervals */ -void WebSocketsServer::handleHBPing(WSclient_t * client) { +void WebSocketsServerCore::handleHBPing(WSclient_t * client) { if(client->pingInterval == 0) return; uint32_t pi = millis() - client->lastPing; @@ -887,7 +866,7 @@ void WebSocketsServer::handleHBPing(WSclient_t * client) { * @param pongTimeout uint32_t millis after which pong should timout if not received * @param disconnectTimeoutCount uint8_t how many timeouts before disconnect, 0=> do not disconnect */ -void WebSocketsServer::enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) { +void WebSocketsServerCore::enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) { _pingInterval = pingInterval; _pongTimeout = pongTimeout; _disconnectTimeoutCount = disconnectTimeoutCount; @@ -902,7 +881,7 @@ void WebSocketsServer::enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeo /** * disable ping/pong heartbeat process */ -void WebSocketsServer::disableHeartbeat() { +void WebSocketsServerCore::disableHeartbeat() { _pingInterval = 0; WSclient_t * client; @@ -910,4 +889,43 @@ void WebSocketsServer::disableHeartbeat() { client = &_clients[i]; client->pingInterval = 0; } -} \ No newline at end of file +} + +//////////////////// +// WebSocketServer + +/** + * called to initialize the Websocket server + */ +void WebSocketsServer::begin(void) { + WebSocketsServerCore::begin(); + _server->begin(); + + DEBUG_WEBSOCKETS("[WS-Server] Server Started.\n"); +} + +void WebSocketsServer::close(void) { + WebSocketsServer::close(); +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) + _server->close(); +#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + _server->end(); +#else + // TODO how to close server? +#endif +} + +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) +/** + * called in arduino loop + */ +void WebSocketsServer::loop(void) { + if(_runnning) { + WEBSOCKETS_YIELD(); + handleNewClients(); + WEBSOCKETS_YIELD(); + handleClientData(); + } +} +#endif + diff --git a/src/WebSocketsServer.h b/src/WebSocketsServer.h index 19c934d..a5d4a9d 100644 --- a/src/WebSocketsServer.h +++ b/src/WebSocketsServer.h @@ -31,27 +31,21 @@ #define WEBSOCKETS_SERVER_CLIENT_MAX (5) #endif -class WebSocketsServer : protected WebSockets { +class WebSocketsServerCore : protected WebSockets { public: -#ifdef __AVR__ - typedef void (*WebSocketServerEvent)(uint8_t num, WStype_t type, uint8_t * payload, size_t length); - typedef bool (*WebSocketServerHttpHeaderValFunc)(String headerName, String headerValue); -#else - typedef std::function WebSocketServerEvent; - typedef std::function WebSocketServerHttpHeaderValFunc; -#endif - WebSocketsServer(uint16_t port, String origin = "", String protocol = "arduino"); - virtual ~WebSocketsServer(void); + WebSocketsServerCore(const String& origin = "", const String& protocol = "arduino"); + virtual ~WebSocketsServerCore(void); void begin(void); void close(void); -#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) - void loop(void); +#ifdef __AVR__ + typedef void (*WebSocketServerEvent)(uint8_t num, WStype_t type, uint8_t * payload, size_t length); + typedef bool (*WebSocketServerHttpHeaderValFunc)(String headerName, String headerValue); #else - // Async interface not need a loop call - void loop(void) __attribute__((deprecated)) {} + typedef std::function WebSocketServerEvent; + typedef std::function WebSocketServerHttpHeaderValFunc; #endif void onEvent(WebSocketServerEvent cbEvent); @@ -100,15 +94,12 @@ class WebSocketsServer : protected WebSockets { #endif protected: - uint16_t _port; String _origin; String _protocol; String _base64Authorization; ///< Base64 encoded Auth request String * _mandatoryHttpHeaders; size_t _mandatoryHttpHeaderCount; - WEBSOCKETS_NETWORK_SERVER_CLASS * _server; - WSclient_t _clients[WEBSOCKETS_SERVER_CLIENT_MAX]; WebSocketServerEvent _cbEvent; @@ -128,7 +119,6 @@ class WebSocketsServer : protected WebSockets { bool clientIsConnected(WSclient_t * client); #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) - void handleNewClients(void); void handleClientData(void); #endif @@ -212,4 +202,30 @@ class WebSocketsServer : protected WebSockets { bool hasMandatoryHeader(String headerName); }; +class WebSocketsServer: public WebSocketsServerCore { + public: + + WebSocketsServer(uint16_t port, const String& origin = "", const String& protocol = "arduino"); + virtual ~WebSocketsServer(void); + + void begin(void); + void close(void); + +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + void loop(void); +#else + // Async interface not need a loop call + void loop(void) __attribute__((deprecated)) {} +#endif + + protected: + +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + void handleNewClients(void); +#endif + + uint16_t _port; + WEBSOCKETS_NETWORK_SERVER_CLASS * _server; +}; + #endif /* WEBSOCKETSSERVER_H_ */ From 7a3be07e8139d304a183ab57d444d94db4d9eb3b Mon Sep 17 00:00:00 2001 From: david gauchard Date: Mon, 10 Aug 2020 19:23:17 +0200 Subject: [PATCH 2/9] ditto --- src/WebSockets4WebServer.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/WebSockets4WebServer.h diff --git a/src/WebSockets4WebServer.h b/src/WebSockets4WebServer.h new file mode 100644 index 0000000..a38dd3f --- /dev/null +++ b/src/WebSockets4WebServer.h @@ -0,0 +1,24 @@ + +#ifndef __WEBSOCKETS4WEBSERVER_H +#define __WEBSOCKETS4WEBSERVER_H + +#include +#include + +#if WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 + +class WebSockets4WebServer: public WebSocketsServerCore { + public: + + WebSockets4WebServer(const String& origin = "", const String& protocol = "arduino"): + WebSocketsServerCore(origin, protocol) + { + } + + ESP8266WebServer::HookFunction hookForWebserver (WebSocketServerEvent event); + +}; + +#endif // WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 + +#endif // __WEBSOCKETS4WEBSERVER_H From 667d7a8ca219efd65a5d3797cae1015e0f3bcb55 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 28 Oct 2020 23:06:23 +0100 Subject: [PATCH 3/9] continue splitting websocket server --- .../WebSocketServerHooked.ino | 14 +++-- src/WebSockets4WebServer.h | 31 +++++++-- src/WebSocketsServer.cpp | 63 ++++++++++++------- src/WebSocketsServer.h | 13 +++- 4 files changed, 88 insertions(+), 33 deletions(-) diff --git a/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino b/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino index 306a8bf..d52117b 100644 --- a/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino +++ b/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino @@ -1,7 +1,8 @@ /* - * WebSocketServer.ino + * WebSocketServerHooked.ino * * Created on: 22.05.2015 + * Hooked on: 28.10.2020 * */ @@ -29,7 +30,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length { IPAddress ip = webSocket.remoteIP(num); USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); - + // send message to client webSocket.sendTXT(num, "Connected"); } @@ -77,13 +78,18 @@ void setup() { delay(100); } - server.addHook(webSocket.hookForWebserver(webSocketEvent)); + server.addHook(webSocket.hookForWebserver("/ws", webSocketEvent)); + server.on("/", []() { + server.send(200, "text/plain", "I am a regular webserver!\r\n"); + }); + server.begin(); Serial.println("HTTP server started"); - Serial.println("WebSocket server started onthe same port"); + Serial.println("WebSocket server started on the same port"); } void loop() { server.handleClient(); + webSocket.loop(); } diff --git a/src/WebSockets4WebServer.h b/src/WebSockets4WebServer.h index a38dd3f..88256de 100644 --- a/src/WebSockets4WebServer.h +++ b/src/WebSockets4WebServer.h @@ -5,20 +5,41 @@ #include #include -#if WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 +#if WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK class WebSockets4WebServer: public WebSocketsServerCore { - public: + public: WebSockets4WebServer(const String& origin = "", const String& protocol = "arduino"): WebSocketsServerCore(origin, protocol) { } - ESP8266WebServer::HookFunction hookForWebserver (WebSocketServerEvent event); - + ESP8266WebServer::HookFunction hookForWebserver (const String& wsRootDir, WebSocketServerEvent event) + { + onEvent(event); + + return [&, wsRootDir](const String & method, const String & url, WiFiClient * tcpClient, ESP8266WebServer::ContentTypeFunction contentType) + { + if (!(method == "GET" && url.indexOf(wsRootDir) == 0)) { + return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE; + } + + WSclient_t * client = handleNewClient(tcpClient); + + // give "GET " + String headerLine; + headerLine.reserve(url.length() + 5); + headerLine = "GET "; + headerLine += url; + handleHeader(client, &headerLine); + + // tell webserver to not close but forget about this client + return ESP8266WebServer::CLIENT_IS_GIVEN; + }; + } }; -#endif // WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 +#endif // WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK #endif // __WEBSOCKETS4WEBSERVER_H diff --git a/src/WebSocketsServer.cpp b/src/WebSocketsServer.cpp index 5bb57de..c699fae 100644 --- a/src/WebSocketsServer.cpp +++ b/src/WebSocketsServer.cpp @@ -402,7 +402,7 @@ int WebSocketsServerCore::connectedClients(bool ping) { * see if one client is connected * @param num uint8_t client id */ -bool WebSocketsServer::clientIsConnected(uint8_t num) { +bool WebSocketsServerCore::clientIsConnected(uint8_t num) { if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) { return false; } @@ -436,7 +436,7 @@ IPAddress WebSocketsServerCore::remoteIP(uint8_t num) { * handle new client connection * @param client */ -bool WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) { +WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) { WSclient_t * client; // search free list entry for client for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) { @@ -486,11 +486,11 @@ bool WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) { client->lastPing = millis(); client->pongReceived = false; - return true; + return client; break; } } - return false; + return nullptr; } /** @@ -611,6 +611,31 @@ bool WebSocketsServerCore::clientIsConnected(WSclient_t * client) { return false; } #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) +/** + * Handle incoming Connection Request + */ +WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tcpClient) { + + WSclient_t * client = newClient(tcpClient); + + if(!client) { + // no free space to handle client +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) +#ifndef NODEBUG_WEBSOCKETS + IPAddress ip = tcpClient->remoteIP(); +#endif + DEBUG_WEBSOCKETS("[WS-Server] no free space new client from %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); +#else + DEBUG_WEBSOCKETS("[WS-Server] no free space new client\n"); +#endif + tcpClient->stop(); + } + + WEBSOCKETS_YIELD(); + + return client; +} + /** * Handle incoming Connection Request */ @@ -618,7 +643,6 @@ void WebSocketsServer::handleNewClients(void) { #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) while(_server->hasClient()) { #endif - bool ok = false; #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) // store new connection @@ -632,22 +656,8 @@ void WebSocketsServer::handleNewClients(void) { return; } - ok = newClient(tcpClient); + handleNewClient(tcpClient); - if(!ok) { - // no free space to handle client -#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) -#ifndef NODEBUG_WEBSOCKETS - IPAddress ip = tcpClient->remoteIP(); -#endif - DEBUG_WEBSOCKETS("[WS-Server] no free space new client from %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); -#else - DEBUG_WEBSOCKETS("[WS-Server] no free space new client\n"); -#endif - tcpClient->stop(); - } - - WEBSOCKETS_YIELD(); #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) } #endif @@ -929,6 +939,16 @@ void WebSocketsServer::close(void) { } #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) +/** + * called in arduino loop + */ +void WebSocketsServerCore::loop(void) { + if(_runnning) { + WEBSOCKETS_YIELD(); + handleClientData(); + } +} + /** * called in arduino loop */ @@ -936,8 +956,7 @@ void WebSocketsServer::loop(void) { if(_runnning) { WEBSOCKETS_YIELD(); handleNewClients(); - WEBSOCKETS_YIELD(); - handleClientData(); + WebSocketsServerCore::loop(); } } #endif diff --git a/src/WebSocketsServer.h b/src/WebSocketsServer.h index d215e9b..502c198 100644 --- a/src/WebSocketsServer.h +++ b/src/WebSocketsServer.h @@ -95,6 +95,10 @@ class WebSocketsServerCore : protected WebSockets { IPAddress remoteIP(uint8_t num); #endif +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + void loop(void); // handle client data only +#endif + protected: String _origin; String _protocol; @@ -113,7 +117,7 @@ class WebSocketsServerCore : protected WebSockets { uint32_t _pongTimeout; uint8_t _disconnectTimeoutCount; - bool newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient); + WSclient_t * newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient); void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin); @@ -196,12 +200,17 @@ class WebSocketsServerCore : protected WebSockets { return true; } +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + WSclient_t * handleNewClient(WEBSOCKETS_NETWORK_CLASS * tcpClient); +#endif + private: /* * returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection * @param headerName String ///< the name of the header being checked */ bool hasMandatoryHeader(String headerName); + }; class WebSocketsServer: public WebSocketsServerCore { @@ -214,7 +223,7 @@ class WebSocketsServer: public WebSocketsServerCore { void close(void); #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) - void loop(void); + void loop(void); // handle incoming client and client data #else // Async interface not need a loop call void loop(void) __attribute__((deprecated)) {} From a502edaf979fa38e499bc8954291c248fe5b4762 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 1 Nov 2020 22:48:08 +0100 Subject: [PATCH 4/9] testing --- .../WebSocketServer/WebSocketServer.ino | 2 +- .../WebSocketServerHooked.ino | 2 +- src/WebSockets.h | 5 +++++ src/WebSockets4WebServer.h | 19 ++++++++++++------- src/WebSocketsClient.cpp | 5 +++-- src/WebSocketsServer.cpp | 3 +++ tests/webSocket.html | 2 +- 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/examples/esp8266/WebSocketServer/WebSocketServer.ino b/examples/esp8266/WebSocketServer/WebSocketServer.ino index 5e266a2..35c0c45 100644 --- a/examples/esp8266/WebSocketServer/WebSocketServer.ino +++ b/examples/esp8266/WebSocketServer/WebSocketServer.ino @@ -44,7 +44,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length break; case WStype_BIN: USE_SERIAL.printf("[%u] get binary length: %u\n", num, length); - hexdump(payload, length); + //hexdump(payload, length); // send message to client // webSocket.sendBIN(num, payload, length); diff --git a/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino b/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino index d52117b..d4b676a 100644 --- a/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino +++ b/examples/esp8266/WebSocketServerHooked/WebSocketServerHooked.ino @@ -46,7 +46,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length break; case WStype_BIN: USE_SERIAL.printf("[%u] get binary length: %u\n", num, length); - hexdump(payload, length); + //hexdump(payload, length); // send message to client // webSocket.sendBIN(num, payload, length); diff --git a/src/WebSockets.h b/src/WebSockets.h index a858c84..ba56700 100644 --- a/src/WebSockets.h +++ b/src/WebSockets.h @@ -40,6 +40,9 @@ #include #endif +//#define NODEBUG_WEBSOCKETS +#define DEBUG_ESP_PORT Serial + #ifndef NODEBUG_WEBSOCKETS #ifdef DEBUG_ESP_PORT #define DEBUG_WEBSOCKETS(...) DEBUG_ESP_PORT.printf(__VA_ARGS__) @@ -50,8 +53,10 @@ #ifndef DEBUG_WEBSOCKETS #define DEBUG_WEBSOCKETS(...) +#error #ifndef NODEBUG_WEBSOCKETS #define NODEBUG_WEBSOCKETS +#error #endif #endif diff --git a/src/WebSockets4WebServer.h b/src/WebSockets4WebServer.h index 88256de..9236ba7 100644 --- a/src/WebSockets4WebServer.h +++ b/src/WebSockets4WebServer.h @@ -21,18 +21,23 @@ class WebSockets4WebServer: public WebSocketsServerCore { return [&, wsRootDir](const String & method, const String & url, WiFiClient * tcpClient, ESP8266WebServer::ContentTypeFunction contentType) { +printf("hook '%s' '%s' '%s'\n", method.c_str(), url.c_str(), wsRootDir.c_str()); if (!(method == "GET" && url.indexOf(wsRootDir) == 0)) { return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE; } WSclient_t * client = handleNewClient(tcpClient); - - // give "GET " - String headerLine; - headerLine.reserve(url.length() + 5); - headerLine = "GET "; - headerLine += url; - handleHeader(client, &headerLine); + + if (client) + { + // give "GET " + String headerLine; + headerLine.reserve(url.length() + 5); + headerLine = "GET "; + headerLine += url; + handleHeader(client, &headerLine); + } +printf("conn? %i \n", tcpClient->connected()); // tell webserver to not close but forget about this client return ESP8266WebServer::CLIENT_IS_GIVEN; diff --git a/src/WebSocketsClient.cpp b/src/WebSocketsClient.cpp index bc6a42e..ea5e097 100644 --- a/src/WebSocketsClient.cpp +++ b/src/WebSocketsClient.cpp @@ -741,15 +741,16 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) { if(ok) { switch(client->cCode) { case 101: ///< Switching Protocols - break; case 200: if(client->isSocketIO) { break; } + // falls through case 403: ///< Forbidden // todo handle login - default: ///< Server dont unterstand requrst + // falls through + default: ///< Server don't unterstand request ok = false; DEBUG_WEBSOCKETS("[WS-Client][handleHeader] serverCode is not 101 (%d)\n", client->cCode); clientDisconnect(client); diff --git a/src/WebSocketsServer.cpp b/src/WebSocketsServer.cpp index c699fae..5af4aec 100644 --- a/src/WebSocketsServer.cpp +++ b/src/WebSocketsServer.cpp @@ -66,6 +66,9 @@ WebSocketsServerCore::~WebSocketsServerCore() { _mandatoryHttpHeaderCount = 0; } +WebSocketsServer::~WebSocketsServer() { +} + /** * called to initialize the Websocket server */ diff --git a/tests/webSocket.html b/tests/webSocket.html index 1dc4f6b..b0869cc 100644 --- a/tests/webSocket.html +++ b/tests/webSocket.html @@ -2,7 +2,7 @@