diff --git a/libraries/WiFi/examples/WiFiPagerServer/.skip.esp32h2 b/libraries/WiFi/examples/WiFiPagerServer/.skip.esp32h2 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/WiFi/examples/WiFiPagerServer/WiFiPagerServer.ino b/libraries/WiFi/examples/WiFiPagerServer/WiFiPagerServer.ino new file mode 100644 index 00000000000..cb7a6b76222 --- /dev/null +++ b/libraries/WiFi/examples/WiFiPagerServer/WiFiPagerServer.ino @@ -0,0 +1,59 @@ +/* + WiFi Pager Server - server.available + and print-to-all-clients example + + The example is a simple server that echoes any incoming + messages to all connected clients. Connect two or more + telnet sessions to see how server.available() and + server.print() work. + + created in September 2020 + by Juraj Andrassy + */ + +#include + +WiFiServer server(2323); + +#include "arduino_secrets.h" +///////please enter your sensitive data in the Secret tab/arduino_secrets.h +char ssid[] = SECRET_SSID; // your network SSID (name) +char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) + +void setup() { + + Serial.begin(115200); + while (!Serial); + + Serial.print("Attempting to connect to SSID \""); + Serial.print(ssid); + Serial.println("\" with DHCP ..."); + WiFi.begin(ssid, pass); + while (WiFi.status() != WL_CONNECTED) { + Serial.print('.'); + delay(1000); + } + Serial.println(); + + server.begin(); + + IPAddress ip = WiFi.localIP(); + Serial.println(); + Serial.println("Connected to WiFi network."); + Serial.print("To access the server, connect with Telnet client to "); + Serial.print(ip); + Serial.println(" 2323"); +} + +void loop() { + + WiFiClient client = server.available(); // returns first client which has data to read or a 'false' client + if (client) { // client is here true only if it is connected and has data to read + String s = client.readStringUntil('\n'); // read the message incoming from one of the clients + s.trim(); // trim eventual \r + Serial.println(s); // print the message to Serial Monitor + client.print("echo: "); // this is only for the sending client + server.println(s); // send the message to all connected clients + server.flush(); // flush the buffers + } +} diff --git a/libraries/WiFi/examples/WiFiPagerServer/arduino_secrets.h b/libraries/WiFi/examples/WiFiPagerServer/arduino_secrets.h new file mode 100644 index 00000000000..0c9fdd556a3 --- /dev/null +++ b/libraries/WiFi/examples/WiFiPagerServer/arduino_secrets.h @@ -0,0 +1,2 @@ +#define SECRET_SSID "" +#define SECRET_PASS "" diff --git a/libraries/WiFi/src/WiFiServer.cpp b/libraries/WiFi/src/WiFiServer.cpp index 9d79b5f7c46..8f5f8e1f699 100644 --- a/libraries/WiFi/src/WiFiServer.cpp +++ b/libraries/WiFi/src/WiFiServer.cpp @@ -23,6 +23,59 @@ #undef write #undef close +#if !CONFIG_DISABLE_HAL_LOCKS +#define WIFISERVER_MUTEX_LOCK() do {} while (xSemaphoreTake(_lock, portMAX_DELAY) != pdPASS) +#define WIFISERVER_MUTEX_UNLOCK() xSemaphoreGive(_lock) +#else +#define WIFISERVER_MUTEX_LOCK() +#define WIFISERVER_MUTEX_UNLOCK() +#endif + +WiFiServer::WiFiServer(uint16_t port, uint8_t max_clients) : + sockfd(-1), _accepted_sockfd(-1), _addr(), _port(port), _max_clients(max_clients), _listening(false), _noDelay(false) +#if !CONFIG_DISABLE_HAL_LOCKS + , _lock(NULL) +#endif +{ + log_v("WiFiServer::WiFiServer(port=%d, ...)", port); +#if !CONFIG_DISABLE_HAL_LOCKS + if (_lock == NULL) { + _lock = xSemaphoreCreateMutex(); + if (_lock == NULL) { + log_e("xSemaphoreCreateMutex failed"); + return; + } + } +#endif +} + +WiFiServer::WiFiServer(const IPAddress &addr, uint16_t port, uint8_t max_clients) : + sockfd(-1), _accepted_sockfd(-1), _addr(addr), _port(port), _max_clients(max_clients), _listening(false), _noDelay(false) +#if !CONFIG_DISABLE_HAL_LOCKS + , _lock(NULL) +#endif +{ + log_v("WiFiServer::WiFiServer(addr=%s, port=%d, ...)", addr.toString().c_str(), port); +#if !CONFIG_DISABLE_HAL_LOCKS + if (_lock == NULL) { + _lock = xSemaphoreCreateMutex(); + if (_lock == NULL) { + log_e("xSemaphoreCreateMutex failed"); + return; + } + } +#endif +} + +WiFiServer::~WiFiServer() { + end(); +#if !CONFIG_DISABLE_HAL_LOCKS + if (_lock != NULL) { + vSemaphoreDelete(_lock); + } +#endif +} + int WiFiServer::setTimeout(uint32_t seconds){ struct timeval tv; tv.tv_sec = seconds; @@ -33,13 +86,49 @@ int WiFiServer::setTimeout(uint32_t seconds){ } size_t WiFiServer::write(const uint8_t *data, size_t len){ - return 0; + WIFISERVER_MUTEX_LOCK(); + static uint32_t lastCheck; + uint32_t m = millis(); + if (m - lastCheck > 100) { + lastCheck = m; + acceptClients(); + } + size_t ret = 0; + if (len > 0) { + for (uint8_t i = 0; i < SERVER_MAX_MONITORED_CLIENTS; i++) { + if (connectedClients[i].connected()) { + ret += connectedClients[i].write(data, len); + } + } + } + WIFISERVER_MUTEX_UNLOCK(); + return ret; } void WiFiServer::stopAll(){} -WiFiClient WiFiServer::available(){ - return accept(); +// https://www.arduino.cc/en/Reference/WiFiServerAvailable +WiFiClient WiFiServer::available() { + WIFISERVER_MUTEX_LOCK(); + + acceptClients(); + + WiFiClient ret; + + // find next client with data available + for (uint8_t i = 0; i < SERVER_MAX_MONITORED_CLIENTS; i++) { + if (index == SERVER_MAX_MONITORED_CLIENTS) { + index = 0; + } + WiFiClient& client = connectedClients[index]; + index++; + if (client.available()) { + ret = client; + break; + } + } + WIFISERVER_MUTEX_UNLOCK(); + return ret; } WiFiClient WiFiServer::accept(){ @@ -138,6 +227,14 @@ void WiFiServer::end(){ #endif sockfd = -1; _listening = false; + + WIFISERVER_MUTEX_LOCK(); + for (uint8_t i = 0; i < SERVER_MAX_MONITORED_CLIENTS; i++) { + if (connectedClients[i]) { + connectedClients[i].stop(); + } + } + WIFISERVER_MUTEX_UNLOCK(); } void WiFiServer::close(){ @@ -147,3 +244,13 @@ void WiFiServer::close(){ void WiFiServer::stop(){ end(); } + +void WiFiServer::acceptClients() { + for (uint8_t i = 0; i < SERVER_MAX_MONITORED_CLIENTS; i++) { + WiFiClient& client = connectedClients[i]; + if (!client.connected() && !client.available()) { + client = accept(); + } + } +} + diff --git a/libraries/WiFi/src/WiFiServer.h b/libraries/WiFi/src/WiFiServer.h index 5a022d14829..788ed0b48c0 100644 --- a/libraries/WiFi/src/WiFiServer.h +++ b/libraries/WiFi/src/WiFiServer.h @@ -24,6 +24,10 @@ #include "WiFiClient.h" #include "IPAddress.h" +#ifndef SERVER_MAX_MONITORED_CLIENTS +#define SERVER_MAX_MONITORED_CLIENTS CONFIG_LWIP_MAX_SOCKETS +#endif + class WiFiServer : public Server { private: int sockfd; @@ -33,17 +37,23 @@ class WiFiServer : public Server { uint8_t _max_clients; bool _listening; bool _noDelay = false; + + WiFiClient connectedClients[SERVER_MAX_MONITORED_CLIENTS]; + uint8_t index = 0; + +#if !CONFIG_DISABLE_HAL_LOCKS + SemaphoreHandle_t _lock; +#endif + + void acceptClients(); public: void listenOnLocalhost(){} - WiFiServer(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { - log_v("WiFiServer::WiFiServer(port=%d, ...)", port); - } - WiFiServer(const IPAddress& addr, uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(addr),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { - log_v("WiFiServer::WiFiServer(addr=%s, port=%d, ...)", addr.toString().c_str(), port); - } - ~WiFiServer(){ end();} + WiFiServer(uint16_t port=80, uint8_t max_clients=4); + WiFiServer(const IPAddress& addr, uint16_t port=80, uint8_t max_clients=4); + ~WiFiServer(); + WiFiClient available(); WiFiClient accept(); void begin(uint16_t port=0);