From 3d7352ea1c6b62bd5891f4582d61adfad9af5874 Mon Sep 17 00:00:00 2001 From: Duality <201292@live.nl> Date: Sat, 6 Jun 2015 18:28:53 +0200 Subject: [PATCH 1/5] added NOT_ON_TIMER and digitalPinToTimer defines to make a liquidcrystal library workd (that uses i2c) --- hardware/esp8266com/esp8266/cores/esp8266/Arduino.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h b/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h index 138aea96b5..89bf326854 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h @@ -209,6 +209,7 @@ void loop(void); // This comes from the pins_*.c file for the active board configuration. #define digitalPinToPort(pin) (0) #define digitalPinToBitMask(pin) (1UL << (pin)) +#define digitalPinToTimer(pin) (0) #define portOutputRegister(port) ((volatile uint32_t*) GPO) #define portInputRegister(port) ((volatile uint32_t*) GPI) #define portModeRegister(port) ((volatile uint32_t*) GPE) @@ -216,6 +217,7 @@ void loop(void); #define NOT_A_PIN -1 #define NOT_A_PORT -1 #define NOT_AN_INTERRUPT -1 +#define NOT_ON_TIMER 0 #ifdef __cplusplus } // extern "C" From 2d530a861ca295aa23594a9e42544e5239800572 Mon Sep 17 00:00:00 2001 From: Kristijan Novoselic Date: Sat, 6 Jun 2015 22:12:18 +0200 Subject: [PATCH 2/5] Added a DNSServer library --- README.md | 39 ++--- .../examples/DNSServer/DNSServer.ino | 28 ++++ .../libraries/DNSServer/library.properties | 9 ++ .../libraries/DNSServer/src/DNSServer.cpp | 133 ++++++++++++++++++ .../libraries/DNSServer/src/DNSServer.h | 72 ++++++++++ 5 files changed, 263 insertions(+), 18 deletions(-) create mode 100644 hardware/esp8266com/esp8266/libraries/DNSServer/examples/DNSServer/DNSServer.ino create mode 100644 hardware/esp8266com/esp8266/libraries/DNSServer/library.properties create mode 100644 hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.cpp create mode 100644 hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.h diff --git a/README.md b/README.md index 2f7d3ccf9c..02b9eaee11 100644 --- a/README.md +++ b/README.md @@ -102,9 +102,9 @@ This is mostly similar to WiFi shield library. Differences include: - ```WiFi.RSSI()``` doesn't work - ```WiFi.printDiag(Serial);``` will print out some diagnostic info - ```WiFiUDP``` class supports sending and receiving multicast packets on STA interface. -When sending a multicast packet, replace ```udp.beginPacket(addr, port)``` with +When sending a multicast packet, replace ```udp.beginPacket(addr, port)``` with ```udp.beginPacketMulticast(addr, port, WiFi.localIP())```. -When listening to multicast packets, replace ```udp.begin(port)``` with +When listening to multicast packets, replace ```udp.begin(port)``` with ```udp.beginMulticast(WiFi.localIP(), multicast_ip_addr, port)```. You can use ```udp.destinationIP()``` to tell whether the packet received was sent to the multicast or unicast address. @@ -117,7 +117,7 @@ Four samples are provided for this library. Library for calling functions repeatedly with a certain period. Two examples included. -It is currently not recommended to do blocking IO operations (network, serial, file) from Ticker +It is currently not recommended to do blocking IO operations (network, serial, file) from Ticker callback functions. Instead, set a flag inside the ticker callback and check for that flag inside the loop function. #### EEPROM #### @@ -183,6 +183,11 @@ Allows the sketch to respond to multicast DNS queries for domain names like "foo Currently the library only works on STA interface, AP interface is not supported. See attached example and library README file for details. +#### DNS server (DNSServer library) #### + +Implements a simple DNS server that can be used in both STA and AP modes. The DNS server currently supports only one domain (for all other domains it will reply with NXDOMAIN or custom status code). With it clients can open a web server running on ESP8266 using a domain name, not an IP address. +See attached example for details. + #### Servo #### This library exposes the ability to control RC (hobby) servo motors. It will support upto 24 servos on any available output pin. By defualt the first 12 servos will use Timer0 and currently this will not interfere with any other support. Servo counts above 12 will use Timer1 and features that use it will be effected. @@ -211,10 +216,10 @@ You need to put ESP8266 into bootloader mode before uploading code. For stable use of the ESP8266 a power supply with 3V3 and >= 250mA is required. * Note - - using Power from USB to Serial is may unstable, they not deliver enough current. - + - using Power from USB to Serial is may unstable, they not deliver enough current. + #### Serial Adapter #### - + There are many different USB to Serial adapters / boards. * Note @@ -223,17 +228,17 @@ There are many different USB to Serial adapters / boards. - not all board have all pins of the ICs as breakout (check before order) - CTS and DSR are not useful for upload (they are Inputs) -* Working ICs +* Working ICs - FT232RL - CP2102 - may others (drop a comment) - + #### Minimal hardware Setup for Bootloading and usage #### ESPxx Hardware | PIN | Resistor | Serial Adapter | -| ------------- | -------- | -------------- | +| ------------- | -------- | -------------- | | VCC | | VCC (3.3V) | | GND | | GND | | TX or GPIO2* | | RX | @@ -243,11 +248,11 @@ ESPxx Hardware | GPIO15* | PullDown | | | CH_PD | PullUp | | -* Note +* Note - GPIO15 is also named MTDO - Reset is also named RSBT or REST (adding PullUp improves the stability of the Module) - GPIO2 is alternative TX for the boot loader mode - + ###### esp to Serial ![ESP to Serial](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP_to_serial.png) @@ -255,7 +260,7 @@ ESPxx Hardware ESPxx Hardware | PIN | Resistor | Serial Adapter | -| ------------- | -------- | --------------- | +| ------------- | -------- | --------------- | | VCC | | VCC (3.3V) | | GND | | GND | | TX or GPIO2 | | RX | @@ -265,15 +270,15 @@ ESPxx Hardware | GPIO15 | PullDown | | | CH_PD | PullUp | | -* Note +* Note - if no RTS is used a manual power toggle is needed - + #### Minimal hardware Setup for running only #### ESPxx Hardware | PIN | Resistor | Power supply | -| ------------- | -------- | --------------- | +| ------------- | -------- | --------------- | | VCC | | VCC (3.3V) | | GND | | GND | | GPIO0 | PullUp | | @@ -284,7 +289,7 @@ ESPxx Hardware ![ESP min](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP_min.png) ###### improved stability -![ESP improved stability](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP_improved_stability.png) +![ESP improved stability](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP_improved_stability.png) ### Issues and support ### @@ -305,5 +310,3 @@ Esptool written by Christian Klippel is licensed under GPLv2, currently maintain ESP8266 core support, ESP8266WiFi, Ticker, ESP8266WebServer libraries were written by Ivan Grokhotkov, ivan@esp8266.com. [SPI Flash File System (SPIFFS)](https://github.com/pellepl/spiffs) written by Peter Andersson is used in this project. It is distributed under MIT license. - - diff --git a/hardware/esp8266com/esp8266/libraries/DNSServer/examples/DNSServer/DNSServer.ino b/hardware/esp8266com/esp8266/libraries/DNSServer/examples/DNSServer/DNSServer.ino new file mode 100644 index 0000000000..15951d629f --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/DNSServer/examples/DNSServer/DNSServer.ino @@ -0,0 +1,28 @@ +#include +#include + +const byte DNS_PORT = 53; +IPAddress apIP(192, 168, 1, 1); +DNSServer dnsServer; + +void setup() { + WiFi.mode(WIFI_AP); + WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); + WiFi.softAP("DNSServer example"); + + // modify TTL associated with the domain name (in seconds) + // default is 60 seconds + dnsServer.setTTL(300); + // set which return code will be used for all other domains (e.g. sending + // ServerFailure instead of NonExistentDomain will reduce number of queries + // sent by clients) + // default is DNSReplyCode::NonExistentDomain + dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure); + + //start DNS server for a specific domain name + dnsServer.start(DNS_PORT, "www.example.com", apIP); +} + +void loop() { + dnsServer.processNextRequest(); +} diff --git a/hardware/esp8266com/esp8266/libraries/DNSServer/library.properties b/hardware/esp8266com/esp8266/libraries/DNSServer/library.properties new file mode 100644 index 0000000000..b9fc670dd1 --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/DNSServer/library.properties @@ -0,0 +1,9 @@ +name=DNSServer +version=1.0.0 +author=Kristijan Novoselić +maintainer=Kristijan Novoselić, +sentence=A simple DNS server for ESP8266. +paragraph=This library implements a simple DNS server. +category=Communication +url= +architectures=esp8266 diff --git a/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.cpp b/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.cpp new file mode 100644 index 0000000000..5af48a3cec --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.cpp @@ -0,0 +1,133 @@ +#include "DNSServer.h" +#include +#include + +DNSServer::DNSServer() +{ + _ttl = htonl(60); + _errorReplyCode = DNSReplyCode::NonExistentDomain; +} + +bool DNSServer::start(const uint16_t &port, const String &domainName, + const IPAddress &resolvedIP) +{ + _port = port; + _domainName = domainName; + _resolvedIP[0] = resolvedIP[0]; + _resolvedIP[1] = resolvedIP[1]; + _resolvedIP[2] = resolvedIP[2]; + _resolvedIP[3] = resolvedIP[3]; + downcaseAndRemoveWwwPrefix(_domainName); + return _udp.begin(_port) == 1; +} + +void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode) +{ + _errorReplyCode = replyCode; +} + +void DNSServer::setTTL(const uint32_t &ttl) +{ + _ttl = htonl(ttl); +} + +void DNSServer::stop() +{ + _udp.stop(); +} + +void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName) +{ + domainName.toLowerCase(); + domainName.replace("www.", ""); +} + +void DNSServer::processNextRequest() +{ + _currentPacketSize = _udp.parsePacket(); + if (_currentPacketSize) + { + _buffer = (unsigned char*)malloc(_currentPacketSize * sizeof(char)); + _udp.read(_buffer, _currentPacketSize); + _dnsHeader = (DNSHeader*) _buffer; + + if (_dnsHeader->QR == DNS_QR_QUERY && + _dnsHeader->OPCode == DNS_OPCODE_QUERY && + requestIncludesOnlyOneQuestion() && + getDomainNameWithoutWwwPrefix() == _domainName) + { + replyWithIP(); + } + else if (_dnsHeader->QR == DNS_QR_QUERY) + { + replyWithCustomCode(); + } + + free(_buffer); + } +} + +bool DNSServer::requestIncludesOnlyOneQuestion() +{ + return ntohs(_dnsHeader->QDCount) == 1 && + _dnsHeader->ANCount == 0 && + _dnsHeader->NSCount == 0 && + _dnsHeader->ARCount == 0; +} + +String DNSServer::getDomainNameWithoutWwwPrefix() +{ + String parsedDomainName = ""; + unsigned char *start = _buffer + 12; + if (*start == 0) + { + return parsedDomainName; + } + int pos = 0; + while(true) + { + unsigned char labelLength = *(start + pos); + for(int i = 0; i < labelLength; i++) + { + pos++; + parsedDomainName += (char)*(start + pos); + } + pos++; + if (*(start + pos) == 0) + { + downcaseAndRemoveWwwPrefix(parsedDomainName); + return parsedDomainName; + } + else + { + parsedDomainName += "."; + } + } +} + +void DNSServer::replyWithIP() +{ + _dnsHeader->QR = DNS_QR_RESPONSE; + _dnsHeader->ANCount = _dnsHeader->QDCount; + _dnsHeader->QDCount = 0; + + _udp.beginPacket(_udp.remoteIP(), _udp.remotePort()); + _udp.write(_buffer, _currentPacketSize); + _udp.write((unsigned char*)&_ttl, 4); + // Length of RData is 4 bytes (because, in this case, RData is IPv4) + _udp.write((uint8_t)0); + _udp.write((uint8_t)4); + _udp.write(_resolvedIP, sizeof(_resolvedIP)); + _udp.endPacket(); +} + +void DNSServer::replyWithCustomCode() +{ + _dnsHeader->QR = DNS_QR_RESPONSE; + _dnsHeader->RCode = (unsigned char)_errorReplyCode; + _dnsHeader->QDCount = 0; + + _udp.beginPacket(_udp.remoteIP(), _udp.remotePort()); + _udp.write(_buffer, sizeof(DNSHeader)); + _udp.endPacket(); +} diff --git a/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.h b/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.h new file mode 100644 index 0000000000..df489402ad --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.h @@ -0,0 +1,72 @@ +#ifndef DNSServer_h +#define DNSServer_h +#include + +#define DNS_QR_QUERY 0 +#define DNS_QR_RESPONSE 1 +#define DNS_OPCODE_QUERY 0 + +enum class DNSReplyCode +{ + NoError = 0, + FormError = 1, + ServerFailure = 2, + NonExistentDomain = 3, + NotImplemented = 4, + Refused = 5, + YXDomain = 6, + YXRRSet = 7, + NXRRSet = 8 +}; + +struct DNSHeader +{ + uint16_t ID; // identification number + unsigned char RD : 1; // recursion desired + unsigned char TC : 1; // truncated message + unsigned char AA : 1; // authoritive answer + unsigned char OPCode : 4; // message_type + unsigned char QR : 1; // query/response flag + unsigned char RCode : 4; // response code + unsigned char Z : 3; // its z! reserved + unsigned char RA : 1; // recursion available + uint16_t QDCount; // number of question entries + uint16_t ANCount; // number of answer entries + uint16_t NSCount; // number of authority entries + uint16_t ARCount; // number of resource entries +}; + +class DNSServer +{ + public: + DNSServer(); + void processNextRequest(); + void setErrorReplyCode(const DNSReplyCode &replyCode); + void setTTL(const uint32_t &ttl); + + // Returns true if successful, false if there are no sockets available + bool start(const uint16_t &port, + const String &domainName, + const IPAddress &resolvedIP); + // stops the DNS server + void stop(); + + private: + WiFiUDP _udp; + uint16_t _port; + String _domainName; + unsigned char _resolvedIP[4]; + int _currentPacketSize; + unsigned char* _buffer; + DNSHeader* _dnsHeader; + uint32_t _ttl; + DNSReplyCode _errorReplyCode; + + + void downcaseAndRemoveWwwPrefix(String &domainName); + String getDomainNameWithoutWwwPrefix(); + bool requestIncludesOnlyOneQuestion(); + void replyWithIP(); + void replyWithCustomCode(); +}; +#endif From dc31da586d2a9a9e27bbbc2a85ebf4154b3e6b4d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 11 Jun 2015 18:01:08 +0300 Subject: [PATCH 3/5] Better handling of wifi disconnect (#231) When network interface is down, some nasty things happen, for instance tcp_connect returns without ever calling error callback. This change adds some workarounds for that: before doing a tcp connect and DNS resolve we check if there is a route available. Also added a listener for wifi events which stops (aborts) all the WiFiClients and WiFiUDPs when wifi is disconnected. This should help libraries detect disconnect properly. Conflicts: hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h --- .../libraries/ESP8266WiFi/src/ESP8266WiFi.cpp | 26 ++++++++++--- .../libraries/ESP8266WiFi/src/ESP8266WiFi.h | 1 + .../libraries/ESP8266WiFi/src/WiFiClient.cpp | 35 ++++++++++++++++- .../libraries/ESP8266WiFi/src/WiFiClient.h | 6 ++- .../libraries/ESP8266WiFi/src/WiFiUdp.cpp | 19 +++++++++- .../libraries/ESP8266WiFi/src/WiFiUdp.h | 5 ++- .../libraries/ESP8266WiFi/src/include/slist.h | 38 +++++++++++++++++++ 7 files changed, 118 insertions(+), 12 deletions(-) create mode 100644 hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/slist.h diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index ac22bf3a01..61cb74630b 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/hardware/esp8266com/esp8266/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() @@ -573,6 +576,17 @@ void ESP8266WiFiClass::_smartConfigDone(void* result) wifi_station_connect(); } +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) { diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h index 61fd395dd3..7234399054 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -314,6 +314,7 @@ class ESP8266WiFiClass static void _scanDone(void* result, int status); void * _getScanInfoByIndex(int i); static void _smartConfigDone(void* result); + static void _eventCallback(void *event); bool _smartConfigStarted = false; bool _useApMode; diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.cpp index 727e64fc1a..9117a41923 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.cpp +++ b/hardware/esp8266com/esp8266/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/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.h index a15cb1b68d..161ca0be1c 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.h +++ b/hardware/esp8266com/esp8266/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 @@ class WiFiClient : public Client { using Print::write; + static void stopAll(); + private: static int8_t _s_connected(void* arg, void* tpcb, int8_t err); @@ -99,7 +102,6 @@ class WiFiClient : public Client { ClientContext* _client; static uint16_t _localPort; - }; diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp index 7696d747b7..8e304abbb2 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp +++ b/hardware/esp8266com/esp8266/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/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h index f8d76cd057..16aa0a3be9 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h +++ b/hardware/esp8266com/esp8266/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 @@ class WiFiUDP : public UDP { // Return the local port for outgoing packets uint16_t localPort(); + static void stopAll(); + }; #endif //WIFIUDP_H diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/slist.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/slist.h new file mode 100644 index 0000000000..4ce42de6cc --- /dev/null +++ b/hardware/esp8266com/esp8266/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 From 86ab7b990a0a725bd55004da75a80286cf1dad72 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 11 Jun 2015 18:11:00 +0300 Subject: [PATCH 4/5] Fix tcp error handler --- .../ESP8266WiFi/src/include/ClientContext.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h index 79c68127f9..d1f728eefe 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h @@ -261,8 +261,17 @@ class ClientContext { } void _error(err_t err) { - DEBUGV(":er %d\r\n", err); - close(); + DEBUGV(":er %d %d %d\r\n", err, _size_sent, _send_waiting); + if (err != ERR_ABRT) { + abort(); + } + else { + tcp_arg(_pcb, NULL); + tcp_sent(_pcb, NULL); + tcp_recv(_pcb, NULL); + tcp_err(_pcb, NULL); + _pcb = NULL; + } if(_size_sent && _send_waiting) { esp_schedule(); } From 87d11ab2a7c197f113912234acbbee1a89ca1b90 Mon Sep 17 00:00:00 2001 From: Makuna Date: Thu, 11 Jun 2015 13:37:13 -0700 Subject: [PATCH 5/5] correct sync use rsil doesn't require a sync, isync needed for processor state register esync needed to get special register --- hardware/esp8266com/esp8266/cores/esp8266/Arduino.h | 6 +++--- hardware/esp8266com/esp8266/cores/esp8266/Esp.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h b/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h index 89bf326854..7d34df5a53 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h @@ -143,13 +143,13 @@ void ets_intr_unlock(); // level 15 will disable ALL interrupts, // level 0 will disable most software interrupts // -#define xt_disable_interrupts(state, level) __asm__ __volatile__("rsil %0," __STRINGIFY(level) "; esync; isync; dsync" : "=a" (state)) -#define xt_enable_interrupts(state) __asm__ __volatile__("wsr %0,ps; esync" :: "a" (state) : "memory") +#define xt_disable_interrupts(state, level) __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)) +#define xt_enable_interrupts(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory") extern uint32_t interruptsState; #define interrupts() xt_enable_interrupts(interruptsState) -#define noInterrupts() __asm__ __volatile__("rsil %0,15; esync; isync; dsync" : "=a" (interruptsState)) +#define noInterrupts() __asm__ __volatile__("rsil %0,15" : "=a" (interruptsState)) #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Esp.h b/hardware/esp8266com/esp8266/cores/esp8266/Esp.h index 2b58b79d1c..5cc75449d0 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Esp.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/Esp.h @@ -113,7 +113,7 @@ class EspClass { uint32_t EspClass::getCycleCount() { uint32_t ccount; - __asm__ __volatile__("rsr %0,ccount":"=a" (ccount)); + __asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount)); return ccount; }