diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index b589ef737..958dade69 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -33,6 +33,8 @@ extern "C" { #include "lwip/dns.h" } +#include "WiFiClient.h" +#include "WiFiUdp.h" extern "C" void esp_schedule(); extern "C" void esp_yield(); @@ -42,6 +44,7 @@ ESP8266WiFiClass::ESP8266WiFiClass() , _useClientMode(false) , _useStaticIp(false) { + wifi_set_event_handler_cb((wifi_event_handler_cb_t)&ESP8266WiFiClass::_eventCallback); } void ESP8266WiFiClass::mode(WiFiMode m) @@ -104,8 +107,8 @@ int ESP8266WiFiClass::begin(const char* ssid, const char *passphrase, int32_t ch wifi_set_channel(channel); } - if(!_useStaticIp) - wifi_station_dhcpc_start(); + if(!_useStaticIp) + wifi_station_dhcpc_start(); return status(); } @@ -128,8 +131,8 @@ void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress s wifi_station_dhcpc_stop(); wifi_set_ip_info(STATION_IF, &info); - - _useStaticIp = true; + + _useStaticIp = true; } void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns) @@ -146,8 +149,8 @@ void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress s ip_addr_t d; d.addr = static_cast(dns); dns_setserver(0,&d); - - _useStaticIp = true; + + _useStaticIp = true; } int ESP8266WiFiClass::disconnect() @@ -588,6 +591,17 @@ void ESP8266WiFiClass::_smartConfigCallback(uint32_t st, void* result) } } +void ESP8266WiFiClass::_eventCallback(void* arg) +{ + System_Event_t* event = reinterpret_cast(arg); + DEBUGV("wifi evt: %d\r\n", event->event); + + if (event->event == EVENT_STAMODE_DISCONNECTED) { + WiFiClient::stopAll(); + WiFiUDP::stopAll(); + } +} + void ESP8266WiFiClass::printDiag(Print& p) { const char* modes[] = {"NULL", "STA", "AP", "STA+AP"}; diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/libraries/ESP8266WiFi/src/ESP8266WiFi.h index 5591343ab..a97ed934d 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -313,6 +313,7 @@ protected: static void _scanDone(void* result, int status); void * _getScanInfoByIndex(int i); static void _smartConfigCallback(uint32_t status, void* result); + static void _eventCallback(void *event); bool _smartConfigStarted = false; bool _smartConfigDone = false; diff --git a/libraries/ESP8266WiFi/src/WiFiClient.cpp b/libraries/ESP8266WiFi/src/WiFiClient.cpp index 727e64fc1..9117a4192 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClient.cpp @@ -34,26 +34,35 @@ extern "C" #include "WiFiClient.h" #include "WiFiServer.h" #include "lwip/opt.h" +#include "lwip/ip.h" #include "lwip/tcp.h" #include "lwip/inet.h" +#include "lwip/netif.h" #include "cbuf.h" #include "include/ClientContext.h" #include "c_types.h" uint16_t WiFiClient::_localPort = 0; +template<> +WiFiClient* SList::_s_first = 0; + + WiFiClient::WiFiClient() : _client(0) { + WiFiClient::_add(this); } WiFiClient::WiFiClient(ClientContext* client) : _client(client) { _client->ref(); + WiFiClient::_add(this); } WiFiClient::~WiFiClient() { + WiFiClient::_remove(this); if (_client) _client->unref(); } @@ -63,6 +72,7 @@ WiFiClient::WiFiClient(const WiFiClient& other) _client = other._client; if (_client) _client->ref(); + WiFiClient::_add(this); } WiFiClient& WiFiClient::operator=(const WiFiClient& other) @@ -88,9 +98,21 @@ int WiFiClient::connect(const char* host, uint16_t port) int WiFiClient::connect(IPAddress ip, uint16_t port) { + ip_addr_t addr; + addr.addr = ip; + if (_client) stop(); + // if the default interface is down, tcp_connect exits early without + // ever calling tcp_err + // http://lists.gnu.org/archive/html/lwip-devel/2010-05/msg00001.html + netif* interface = ip_route(&addr); + if (!interface) { + DEBUGV("no route to host\r\n"); + return 1; + } + tcp_pcb* pcb = tcp_new(); if (!pcb) return 0; @@ -99,8 +121,6 @@ int WiFiClient::connect(IPAddress ip, uint16_t port) pcb->local_port = _localPort++; } - ip_addr_t addr; - addr.addr = ip; tcp_arg(pcb, this); tcp_err(pcb, &WiFiClient::_s_err); tcp_connect(pcb, &addr, port, reinterpret_cast(&WiFiClient::_s_connected)); @@ -257,3 +277,14 @@ void WiFiClient::_s_err(void* arg, int8_t err) reinterpret_cast(arg)->_err(err); } +void WiFiClient::stopAll() +{ + for (WiFiClient* it = _s_first; it; it = it->_next) { + ClientContext* c = it->_client; + if (c) { + c->abort(); + c->unref(); + it->_client = 0; + } + } +} diff --git a/libraries/ESP8266WiFi/src/WiFiClient.h b/libraries/ESP8266WiFi/src/WiFiClient.h index a15cb1b68..161ca0be1 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.h +++ b/libraries/ESP8266WiFi/src/WiFiClient.h @@ -26,11 +26,12 @@ #include "Client.h" #include "IPAddress.h" #include +#include "include/slist.h" class ClientContext; class WiFiServer; -class WiFiClient : public Client { +class WiFiClient : public Client, public SList { protected: WiFiClient(ClientContext* client); @@ -89,6 +90,8 @@ public: using Print::write; + static void stopAll(); + private: static int8_t _s_connected(void* arg, void* tpcb, int8_t err); @@ -99,7 +102,6 @@ private: ClientContext* _client; static uint16_t _localPort; - }; diff --git a/libraries/ESP8266WiFi/src/WiFiUdp.cpp b/libraries/ESP8266WiFi/src/WiFiUdp.cpp index 7696d747b..8e304abbb 100644 --- a/libraries/ESP8266WiFi/src/WiFiUdp.cpp +++ b/libraries/ESP8266WiFi/src/WiFiUdp.cpp @@ -40,14 +40,22 @@ extern "C" #include "lwip/mem.h" #include "include/UdpContext.h" + +template<> +WiFiUDP* SList::_s_first = 0; + /* Constructor */ -WiFiUDP::WiFiUDP() : _ctx(0) {} +WiFiUDP::WiFiUDP() : _ctx(0) +{ + WiFiUDP::_add(this); +} WiFiUDP::WiFiUDP(const WiFiUDP& other) { _ctx = other._ctx; if (_ctx) _ctx->ref(); + WiFiUDP::_add(this); } WiFiUDP& WiFiUDP::operator=(const WiFiUDP& rhs) @@ -60,6 +68,7 @@ WiFiUDP& WiFiUDP::operator=(const WiFiUDP& rhs) WiFiUDP::~WiFiUDP() { + WiFiUDP::_remove(this); if (_ctx) _ctx->unref(); } @@ -258,3 +267,11 @@ uint16_t WiFiUDP::localPort() return _ctx->getLocalPort(); } + +void WiFiUDP::stopAll() +{ + for (WiFiUDP* it = _s_first; it; it = it->_next) { + it->stop(); + } +} + diff --git a/libraries/ESP8266WiFi/src/WiFiUdp.h b/libraries/ESP8266WiFi/src/WiFiUdp.h index f8d76cd05..16aa0a3be 100644 --- a/libraries/ESP8266WiFi/src/WiFiUdp.h +++ b/libraries/ESP8266WiFi/src/WiFiUdp.h @@ -23,12 +23,13 @@ #define WIFIUDP_H #include +#include #define UDP_TX_PACKET_MAX_SIZE 8192 class UdpContext; -class WiFiUDP : public UDP { +class WiFiUDP : public UDP, public SList { private: UdpContext* _ctx; @@ -103,6 +104,8 @@ public: // Return the local port for outgoing packets uint16_t localPort(); + static void stopAll(); + }; #endif //WIFIUDP_H diff --git a/libraries/ESP8266WiFi/src/include/slist.h b/libraries/ESP8266WiFi/src/include/slist.h new file mode 100644 index 000000000..4ce42de6c --- /dev/null +++ b/libraries/ESP8266WiFi/src/include/slist.h @@ -0,0 +1,38 @@ +#ifndef SLIST_H +#define SLIST_H + +template +class SList { +public: + SList() : _next(0) { } + +protected: + + static void _add(T* self) { + T* tmp = _s_first; + _s_first = self; + self->_next = tmp; + } + + static void _remove(T* self) { + if (_s_first == self) { + _s_first = self->_next; + self->_next = 0; + return; + } + + for (T* prev = _s_first; prev->_next; _s_first = _s_first->_next) { + if (prev->_next == self) { + prev->_next = self->_next; + self->_next = 0; + return; + } + } + } + + static T* _s_first; + T* _next; +}; + + +#endif //SLIST_H