diff --git a/README.md b/README.md index 1004502e13..a0b9f4c0e0 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. @@ -118,7 +118,7 @@ You can see more commands here: [http://www.arduino.cc/en/Reference/WiFi](http:/ 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 #### @@ -184,6 +184,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. @@ -212,10 +217,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 @@ -224,17 +229,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 | @@ -244,11 +249,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) @@ -256,7 +261,7 @@ ESPxx Hardware ESPxx Hardware | PIN | Resistor | Serial Adapter | -| ------------- | -------- | --------------- | +| ------------- | -------- | --------------- | | VCC | | VCC (3.3V) | | GND | | GND | | TX or GPIO2 | | RX | @@ -266,15 +271,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 | | @@ -285,7 +290,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 ### @@ -306,5 +311,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/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" diff --git a/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_eboot_command.c b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_eboot_command.c index 60c92bf189..ee3ccb4809 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_eboot_command.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_eboot_command.c @@ -60,7 +60,7 @@ int eboot_command_read(struct eboot_command* cmd) } uint32_t crc32 = eboot_command_calculate_crc32(cmd); - if (cmd->magic & EBOOT_MAGIC_MASK != EBOOT_MAGIC || + if ((cmd->magic & EBOOT_MAGIC_MASK) != EBOOT_MAGIC || cmd->crc32 != crc32) { return 1; } diff --git a/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_flash_utils.c b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_flash_utils.c index 6f8a34f41c..0713998a6a 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_flash_utils.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_flash_utils.c @@ -28,7 +28,7 @@ int SPIEraseAreaEx(const uint32_t start, const uint32_t size) { - if (start & (FLASH_SECTOR_SIZE - 1) != 0) { + if ((start & (FLASH_SECTOR_SIZE - 1)) != 0) { return 1; } diff --git a/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp index 16902b15cb..b67543f8b6 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp @@ -129,7 +129,7 @@ void user_init(void) { uart_div_modify(0, UART_CLK_FREQ / (74480)); system_rtc_mem_read(0, &resetInfo, sizeof(struct rst_info)); - if(resetInfo.reason == WDT_RST_FLAG || resetInfo.reason == EXCEPTION_RST_FLAG) { + if(resetInfo.reason == REASON_WDT_RST || resetInfo.reason == REASON_EXCEPTION_RST) { os_printf("Last Reset:\n - flag=%d\n - Fatal exception (%d):\n - epc1=0x%08x,epc2=0x%08x,epc3=0x%08x,excvaddr=0x%08x,depc=0x%08x\n", resetInfo.reason, resetInfo.exccause, resetInfo.epc1, resetInfo.epc2, resetInfo.epc3, resetInfo.excvaddr, resetInfo.depc); } struct rst_info info = { 0 }; diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_config.h b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_config.h index d59ac80b16..fa4bbd7b1b 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_config.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_config.h @@ -19,8 +19,8 @@ #define c_memset os_memset typedef signed short file_t; -typedef long int s32_t; -typedef long unsigned int u32_t; +typedef int32_t s32_t; +typedef uint32_t u32_t; typedef int16_t s16_t; typedef uint16_t u16_t; typedef int8_t s8_t; 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 diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index 3fd09dace0..958dade693 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) @@ -69,7 +72,7 @@ int ESP8266WiFiClass::begin(const char* ssid, const char *passphrase, int32_t ch mode(WIFI_STA); } - if(!ssid || strlen(ssid) > 31) { + if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { // fail SSID to long or missing! return WL_CONNECT_FAILED; } @@ -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() @@ -178,7 +181,7 @@ void ESP8266WiFiClass::softAP(const char* ssid, const char* passphrase, int chan mode(WIFI_AP); } - if(!ssid || strlen(ssid) > 31) { + if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { // fail SSID to long or missing! return; } @@ -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/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h index 5591343ab8..a97ed934de 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -313,6 +313,7 @@ class ESP8266WiFiClass 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/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index 91f03bbc0d..34f249637e 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -25,6 +25,7 @@ #include "ESP8266WiFiMulti.h" #include +#include ESP8266WiFiMulti::ESP8266WiFiMulti() { } @@ -151,7 +152,7 @@ bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) { WifiAPlist_t newAP; - if(!ssid || strlen(ssid) > 31) { + if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { // fail SSID to long or missing! return false; } @@ -161,21 +162,18 @@ bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) { return false; } - newAP.ssid = (char*) malloc((strlen(ssid) + 1)); + newAP.ssid = strdup(ssid); if(!newAP.ssid) { return false; } - strcpy(newAP.ssid, ssid); - if(passphrase && *passphrase != 0x00) { - newAP.passphrase = (char*) malloc((strlen(passphrase) + 1)); + newAP.passphrase = strdup(passphrase); if(!newAP.passphrase) { free(newAP.ssid); return false; } - strcpy(newAP.passphrase, passphrase); } APlist.push_back(newAP); 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/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(); } 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 diff --git a/hardware/esp8266com/esp8266/platform.txt b/hardware/esp8266com/esp8266/platform.txt index 2695115c28..fe41377eef 100644 --- a/hardware/esp8266com/esp8266/platform.txt +++ b/hardware/esp8266com/esp8266/platform.txt @@ -16,7 +16,7 @@ compiler.sdk.path={runtime.platform.path}/tools/sdk/ compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c -Os -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=c99 +compiler.c.flags=-c -Os -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=c99 -pedantic compiler.S.cmd=xtensa-lx106-elf-gcc compiler.S.flags=-c -g -x assembler-with-cpp -MMD @@ -26,7 +26,7 @@ compiler.c.elf.cmd=xtensa-lx106-elf-gcc compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD +compiler.cpp.flags=-c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -pedantic compiler.as.cmd=xtensa-lx106-elf-as diff --git a/hardware/esp8266com/esp8266/tools/sdk/changelog.txt b/hardware/esp8266com/esp8266/tools/sdk/changelog.txt index b3faa0773b..1857506696 100644 --- a/hardware/esp8266com/esp8266/tools/sdk/changelog.txt +++ b/hardware/esp8266com/esp8266/tools/sdk/changelog.txt @@ -1,3 +1,54 @@ +esp_iot_sdk_v1.1.1_15_06_05 Release Note +------------------------------------------- + +Resolved Issues(Bugs below are eligible for Bug Bounty Program): +1.Too short timer which set by os_arm_timer_us may cause crash. [Tommy] +2.Call os_malloc in low heap situation may cause crash. [MeneerThijs] +3.Memory leak issue when SSL connection fail. [孙新虎] + +Optimization: +1.Update JSON parser to handle with illegal parameter and illegal calling progress. +2.Add parameter of user_esp_platform_check_ip in user_websever.c which in IOT_Demo. +3.Update UART driver to solve the problem that if send data through UART while ESP8266 startup may cause UART invalid. +4.Update smartconfig to version 2.2, corresponding phone APP v0.3.2. And update the description and example of smartconfig_start in document "2C_ESP8266__Programming Guide" +5.Update code in iram to solve the problem that space for text is not enough. +6.Update PWM driver and provide libpwm.a in esp_iot_sdk, update PWM APIs in "2C_ESP8266__Programming Guide", more details in "Added APIs" below. +7.Revised issue that multicast may fail in ESP8266 softAP mode. +8.Update folder "driver",add folder "driver_lib" in \esp_iot_sdk\examples , add "hw_timer.c" about frc1 hardware timer. +9.Remove useless driver code in IOT_Demo +10.Update IOT_Demo to use the latest PWM driver in light demo. +11.Provide liblwip_536.a of which MSS size is 536 +12.Revised issue that boot may fail when 80Mhz SPI clock selected +13.Update esp_init_data_default.bin about RF option in \esp_iot_sdk\bin + +Added APIs: +1.PWM APIs: +Updated: pwm_init,add parameter to set PWM channel and GPIO pin +Added: +(1)get_pwm_version:get version information of PWM driver +(2)pwm_set_period:set PWM period +(3)pwm_get_period:get PWM period +Deleted: +(1)pwm_set_freq:set PWM frequency +(2)pwm_get_freq:get PWM frequency +2.Read/write flash with protection +(1)system_param_save_with_protect:write data into flash with backup protection +(2)system_param_load:read data which saved into flash with backup protection +3.system_get_rst_info:get information about current startup,it is a normal startup or watch dog reset +4.at_response:set AT response +5.at_register_response_func:register a callback for user-define AT response. +6.Update document "2C_ESP8266__Programming Guide" to add description of interrupt definition in ets_sys.h + +AT_v0.25 Release Note: +Note: For AT firmware to support FOTA, flash size need to be 1024KB or more than that. +Optimization: +1.Add parameter about UDP local port in command "AT+SAVETRANSLINK" + +Added AT command: +1.AT+CIPDINFO:set configuration whether show remote IP and remote port with “+IPD” or not + + + esp_iot_sdk_v1.1.0_15_05_27_p1 Release Note ------------------------------------------- diff --git a/hardware/esp8266com/esp8266/tools/sdk/include/ets_sys.h b/hardware/esp8266com/esp8266/tools/sdk/include/ets_sys.h index 8b118b3416..c21826cbd7 100644 --- a/hardware/esp8266com/esp8266/tools/sdk/include/ets_sys.h +++ b/hardware/esp8266com/esp8266/tools/sdk/include/ets_sys.h @@ -74,6 +74,9 @@ inline uint32_t ETS_INTR_PENDING(void) #define ETS_FRC_TIMER1_INTR_ATTACH(func, arg) \ ets_isr_attach(ETS_FRC_TIMER1_INUM, (int_handler_t)(func), (void *)(arg)) +#define ETS_FRC_TIMER1_NMI_INTR_ATTACH(func) \ + NmiTimSetFunc(func) + #define ETS_GPIO_INTR_ATTACH(func, arg) \ ets_isr_attach(ETS_GPIO_INUM, (int_handler_t)(func), (void *)(arg)) diff --git a/hardware/esp8266com/esp8266/tools/sdk/include/smartconfig.h b/hardware/esp8266com/esp8266/tools/sdk/include/smartconfig.h index 4035ad39da..7b1ec90e1e 100644 --- a/hardware/esp8266com/esp8266/tools/sdk/include/smartconfig.h +++ b/hardware/esp8266com/esp8266/tools/sdk/include/smartconfig.h @@ -24,5 +24,6 @@ typedef void (*sc_callback_t)(sc_status status, void *pdata); const char *smartconfig_get_version(void); bool smartconfig_start(sc_type type, sc_callback_t cb, ...); bool smartconfig_stop(void); +bool esptouch_set_timeout(uint8 time_s); //15s~255s, offset:45s #endif diff --git a/hardware/esp8266com/esp8266/tools/sdk/include/user_interface.h b/hardware/esp8266com/esp8266/tools/sdk/include/user_interface.h index 7c4706dc4d..4e6dc34f77 100644 --- a/hardware/esp8266com/esp8266/tools/sdk/include/user_interface.h +++ b/hardware/esp8266com/esp8266/tools/sdk/include/user_interface.h @@ -23,11 +23,12 @@ #endif enum rst_reason { - DEFAULT_RST_FLAG = 0, - WDT_RST_FLAG = 1, - EXCEPTION_RST_FLAG = 2, - SOFT_RST_FLAG = 3, - DEEP_SLEEP_AWAKE_FLAG = 4 + REASON_DEFAULT_RST = 0, + REASON_WDT_RST = 1, + REASON_EXCEPTION_RST = 2, + REASON_SOFT_WDT_RST = 3, + REASON_SOFT_RESTART = 4, + REASON_DEEP_SLEEP_AWAKE = 5 }; struct rst_info { @@ -40,6 +41,8 @@ struct rst_info { uint32 depc; }; +struct rst_info* system_get_rst_info(void); + #define UPGRADE_FW_BIN1 0x00 #define UPGRADE_FW_BIN2 0x01 @@ -129,6 +132,9 @@ void system_phy_set_max_tpw(uint8 max_tpw); void system_phy_set_tpw_via_vdd33(uint16 vdd33); void system_phy_set_rfoption(uint8 option); +bool system_param_save_with_protect(uint16 start_sec, void *param, uint16 len); +bool system_param_load(uint16 start_sec, uint16 offset, void *param, uint16 len); + #define NULL_MODE 0x00 #define STATION_MODE 0x01 #define SOFTAP_MODE 0x02 diff --git a/hardware/esp8266com/esp8266/tools/sdk/lib/libjson.a b/hardware/esp8266com/esp8266/tools/sdk/lib/libjson.a index 5a889af733..e8fa9d8da2 100644 Binary files a/hardware/esp8266com/esp8266/tools/sdk/lib/libjson.a and b/hardware/esp8266com/esp8266/tools/sdk/lib/libjson.a differ diff --git a/hardware/esp8266com/esp8266/tools/sdk/lib/liblwip.a b/hardware/esp8266com/esp8266/tools/sdk/lib/liblwip.a index b4304413a9..a6c42f9e99 100644 Binary files a/hardware/esp8266com/esp8266/tools/sdk/lib/liblwip.a and b/hardware/esp8266com/esp8266/tools/sdk/lib/liblwip.a differ diff --git a/hardware/esp8266com/esp8266/tools/sdk/lib/libmain.a b/hardware/esp8266com/esp8266/tools/sdk/lib/libmain.a index ec7bb4cdfa..90caec3de7 100644 Binary files a/hardware/esp8266com/esp8266/tools/sdk/lib/libmain.a and b/hardware/esp8266com/esp8266/tools/sdk/lib/libmain.a differ diff --git a/hardware/esp8266com/esp8266/tools/sdk/lib/libnet80211.a b/hardware/esp8266com/esp8266/tools/sdk/lib/libnet80211.a index 0c634acfad..648852e52a 100644 Binary files a/hardware/esp8266com/esp8266/tools/sdk/lib/libnet80211.a and b/hardware/esp8266com/esp8266/tools/sdk/lib/libnet80211.a differ diff --git a/hardware/esp8266com/esp8266/tools/sdk/lib/libpp.a b/hardware/esp8266com/esp8266/tools/sdk/lib/libpp.a index c2e844b54c..e42233ab31 100644 Binary files a/hardware/esp8266com/esp8266/tools/sdk/lib/libpp.a and b/hardware/esp8266com/esp8266/tools/sdk/lib/libpp.a differ diff --git a/hardware/esp8266com/esp8266/tools/sdk/lib/libsmartconfig.a b/hardware/esp8266com/esp8266/tools/sdk/lib/libsmartconfig.a index b8feefc989..03f296fd90 100644 Binary files a/hardware/esp8266com/esp8266/tools/sdk/lib/libsmartconfig.a and b/hardware/esp8266com/esp8266/tools/sdk/lib/libsmartconfig.a differ diff --git a/hardware/esp8266com/esp8266/tools/sdk/lib/libssl.a b/hardware/esp8266com/esp8266/tools/sdk/lib/libssl.a index d68dc61bb1..1608d8484e 100644 Binary files a/hardware/esp8266com/esp8266/tools/sdk/lib/libssl.a and b/hardware/esp8266com/esp8266/tools/sdk/lib/libssl.a differ diff --git a/hardware/esp8266com/esp8266/tools/sdk/lib/libupgrade.a b/hardware/esp8266com/esp8266/tools/sdk/lib/libupgrade.a index 6eaebbd309..d0d2d5bdac 100644 Binary files a/hardware/esp8266com/esp8266/tools/sdk/lib/libupgrade.a and b/hardware/esp8266com/esp8266/tools/sdk/lib/libupgrade.a differ diff --git a/hardware/esp8266com/esp8266/tools/sdk/lib/libwpa.a b/hardware/esp8266com/esp8266/tools/sdk/lib/libwpa.a index 39de3f0013..c6f1bb620b 100644 Binary files a/hardware/esp8266com/esp8266/tools/sdk/lib/libwpa.a and b/hardware/esp8266com/esp8266/tools/sdk/lib/libwpa.a differ diff --git a/hardware/esp8266com/esp8266/tools/sdk/version b/hardware/esp8266com/esp8266/tools/sdk/version index a64d2ed43c..1aeff03a80 100644 --- a/hardware/esp8266com/esp8266/tools/sdk/version +++ b/hardware/esp8266com/esp8266/tools/sdk/version @@ -1 +1 @@ -1.1.0_15_05_27_p1 \ No newline at end of file +1.1.1_15_06_05 \ No newline at end of file