3.0.0 Network Refactoring (#8760)

* Create ESP_NetworkInterface class and have Ethernet extending it

* Update CMakeLists.txt

* Split networking from WiFi (H2 can now use Ethernet)

Now all libs have been checked yet. More to do on WiFi side

* Fix build errors

* Guard WiFi classes and fix RMII ETH examples

* Decouple network related libraries from WiFi

* Fix examples and WiFiUpdate

* Guard WiFiProv lib to compile only on WiFi chips

* Add periman string for network and "fix" mdns on the first ETH

* Revert back location of Client/Server/Udp in order to accept some PRs

* Fix periman

* Some fixes from merging master

* Fix web server missing fs.h

* Move Client, Server and Udp out of WiFi

* More fixes

* more fixes

* Fix CMakekLists and rework lib menu dependencies

* Fix CMake issues

* move back WiFiClient to rebase with master

* Update ETH_TLK110.ino

* Move back WiFiClient

* Update progress

* Update WiFiGeneric.cpp

* More fixes

* Switch AP to the new interface

* Cleanup

* Rename AP methods

* Add extra interface info for Printable

* Rename IPv6 getters to clarify that they are returning LinkLocal address

cc @sgryphon

* Rename network classes

cc @sgryphon

* Update NetworkManager.h

* Rename WiFi Server and UDP

* Rename WiFiClient and WiFiClientSecure

* Update CMakeLists.txt

* Update on-push.sh

* Rename Network library

* Remove unnecessary guard

* Get the correct interface MAC address for mDND Workstation service

* Apply suggestions from code review

Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com>

---------

Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com>
This commit is contained in:
Me No Dev 2024-03-26 23:31:23 +02:00 committed by GitHub
parent e92b4ca62b
commit f2026f1e34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
119 changed files with 4124 additions and 3174 deletions

View file

@ -72,7 +72,7 @@ if [ "$BUILD_PIO" -eq 0 ]; then
FQBN_ESP32H2="espressif:esp32:esp32h2:PartitionScheme=huge_app" FQBN_ESP32H2="espressif:esp32:esp32h2:PartitionScheme=huge_app"
SKETCHES_ESP32="\ SKETCHES_ESP32="\
$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino\ $ARDUINO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino\
$ARDUINO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino\ $ARDUINO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino\
$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino\ $ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino\
$ARDUINO_ESP32_PATH/libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino\ $ARDUINO_ESP32_PATH/libraries/Insights/examples/MinimalDiagnostics/MinimalDiagnostics.ino\
@ -90,7 +90,7 @@ else
BOARD="esp32dev" BOARD="esp32dev"
OPTIONS="board_build.partitions = huge_app.csv" OPTIONS="board_build.partitions = huge_app.csv"
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \ build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \ build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/NetworkClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \ build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino" && \ build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BLE/examples/Server/Server.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino" build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"

View file

@ -93,6 +93,7 @@ set(ARDUINO_ALL_LIBRARIES
Insights Insights
LittleFS LittleFS
NetBIOS NetBIOS
Network
Preferences Preferences
RainMaker RainMaker
SD_MMC SD_MMC
@ -104,7 +105,7 @@ set(ARDUINO_ALL_LIBRARIES
Update Update
USB USB
WebServer WebServer
WiFiClientSecure NetworkClientSecure
WiFi WiFi
WiFiProv WiFiProv
Wire Wire
@ -198,20 +199,27 @@ set(ARDUINO_LIBRARY_WebServer_SRCS
libraries/WebServer/src/Parsing.cpp libraries/WebServer/src/Parsing.cpp
libraries/WebServer/src/detail/mimetable.cpp) libraries/WebServer/src/detail/mimetable.cpp)
set(ARDUINO_LIBRARY_WiFiClientSecure_SRCS set(ARDUINO_LIBRARY_NetworkClientSecure_SRCS
libraries/WiFiClientSecure/src/ssl_client.cpp libraries/NetworkClientSecure/src/ssl_client.cpp
libraries/WiFiClientSecure/src/WiFiClientSecure.cpp) libraries/NetworkClientSecure/src/NetworkClientSecure.cpp)
set(ARDUINO_LIBRARY_Network_SRCS
libraries/Network/src/NetworkInterface.cpp
libraries/Network/src/NetworkEvents.cpp
libraries/Network/src/NetworkManager.cpp
libraries/Network/src/NetworkClient.cpp
libraries/Network/src/NetworkServer.cpp
libraries/Network/src/NetworkUdp.cpp)
set(ARDUINO_LIBRARY_WiFi_SRCS set(ARDUINO_LIBRARY_WiFi_SRCS
libraries/WiFi/src/WiFiAP.cpp libraries/WiFi/src/WiFiAP.cpp
libraries/WiFi/src/WiFiClient.cpp
libraries/WiFi/src/WiFi.cpp libraries/WiFi/src/WiFi.cpp
libraries/WiFi/src/WiFiGeneric.cpp libraries/WiFi/src/WiFiGeneric.cpp
libraries/WiFi/src/WiFiMulti.cpp libraries/WiFi/src/WiFiMulti.cpp
libraries/WiFi/src/WiFiScan.cpp libraries/WiFi/src/WiFiScan.cpp
libraries/WiFi/src/WiFiServer.cpp
libraries/WiFi/src/WiFiSTA.cpp libraries/WiFi/src/WiFiSTA.cpp
libraries/WiFi/src/WiFiUdp.cpp) libraries/WiFi/src/STA.cpp
libraries/WiFi/src/AP.cpp)
set(ARDUINO_LIBRARY_WiFiProv_SRCS libraries/WiFiProv/src/WiFiProv.cpp) set(ARDUINO_LIBRARY_WiFiProv_SRCS libraries/WiFiProv/src/WiFiProv.cpp)

View file

@ -256,38 +256,14 @@ config ARDUINO_SELECTIVE_COMPILATION
bool "Include only specific Arduino libraries" bool "Include only specific Arduino libraries"
default n default n
config ARDUINO_SELECTIVE_ArduinoOTA config ARDUINO_SELECTIVE_SPI
bool "Enable ArduinoOTA" bool "Enable SPI"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
select ARDUINO_SELECTIVE_ESPmDNS
default y
config ARDUINO_SELECTIVE_AsyncUDP
bool "Enable AsyncUDP"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
default y default y
config ARDUINO_SELECTIVE_AzureIoT config ARDUINO_SELECTIVE_Wire
bool "Enable AzureIoT" bool "Enable Wire"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_HTTPClient
default y
config ARDUINO_SELECTIVE_BLE
bool "Enable BLE"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_BluetoothSerial
bool "Enable BluetoothSerial"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_DNSServer
bool "Enable DNSServer"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
default y default y
config ARDUINO_SELECTIVE_EEPROM config ARDUINO_SELECTIVE_EEPROM
@ -295,80 +271,11 @@ config ARDUINO_SELECTIVE_EEPROM
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
default y default y
config ARDUINO_SELECTIVE_ESP32
bool "Enable ESP32"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_ESPmDNS
bool "Enable ESPmDNS"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
default y
config ARDUINO_SELECTIVE_FFat
bool "Enable FFat"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_FS
bool "Enable FS"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_HTTPClient
bool "Enable HTTPClient"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
select ARDUINO_SELECTIVE_WiFiClientSecure
default y
config ARDUINO_SELECTIVE_LITTLEFS
bool "Enable LITTLEFS"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_NetBIOS
bool "Enable NetBIOS"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_WiFi
default y
config ARDUINO_SELECTIVE_Preferences config ARDUINO_SELECTIVE_Preferences
bool "Enable Preferences" bool "Enable Preferences"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
default y default y
config ARDUINO_SELECTIVE_SD
bool "Enable SD"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_SD_MMC
bool "Enable SD_MMC"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_SimpleBLE
bool "Enable SimpleBLE"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_SPI
bool "Enable SPI"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_SPIFFS
bool "Enable SPIFFS"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_Ticker config ARDUINO_SELECTIVE_Ticker
bool "Enable Ticker" bool "Enable Ticker"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
@ -379,34 +286,108 @@ config ARDUINO_SELECTIVE_Update
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
default y default y
config ARDUINO_SELECTIVE_FS
bool "Enable FS"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_SD
bool "Enable SD"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_SD_MMC
bool "Enable SD_MMC"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_SPIFFS
bool "Enable SPIFFS"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_FFat
bool "Enable FFat"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_LITTLEFS
bool "Enable LITTLEFS"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_Networking
bool "Enable Networking"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_ArduinoOTA
bool "Enable ArduinoOTA"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking
select ARDUINO_SELECTIVE_ESPmDNS
default y
config ARDUINO_SELECTIVE_AsyncUDP
bool "Enable AsyncUDP"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking
default y
config ARDUINO_SELECTIVE_DNSServer
bool "Enable DNSServer"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking
default y
config ARDUINO_SELECTIVE_ESPmDNS
bool "Enable ESPmDNS"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking
default y
config ARDUINO_SELECTIVE_HTTPClient
bool "Enable HTTPClient"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking
select ARDUINO_SELECTIVE_WiFiClientSecure
default y
config ARDUINO_SELECTIVE_NetBIOS
bool "Enable NetBIOS"
depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking
default y
config ARDUINO_SELECTIVE_WebServer config ARDUINO_SELECTIVE_WebServer
bool "Enable WebServer" bool "Enable WebServer"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking
default y default y
select ARDUINO_SELECTIVE_FS select ARDUINO_SELECTIVE_FS
config ARDUINO_SELECTIVE_WiFi config ARDUINO_SELECTIVE_WiFi
bool "Enable WiFi" bool "Enable WiFi"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking
default y default y
config ARDUINO_SELECTIVE_WiFiClientSecure config ARDUINO_SELECTIVE_WiFiClientSecure
bool "Enable WiFiClientSecure" bool "Enable WiFiClientSecure"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking
select ARDUINO_SELECTIVE_WiFi
default y default y
config ARDUINO_SELECTIVE_WiFiProv config ARDUINO_SELECTIVE_WiFiProv
bool "Enable WiFiProv" bool "Enable WiFiProv"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION && ARDUINO_SELECTIVE_Networking && ARDUINO_SELECTIVE_WiFi
select ARDUINO_SELECTIVE_WiFi
default y default y
config ARDUINO_SELECTIVE_Wire config ARDUINO_SELECTIVE_BLE
bool "Enable Wire" bool "Enable BLE"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION
default y default y
config ARDUINO_SELECTIVE_BluetoothSerial
bool "Enable BluetoothSerial"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
config ARDUINO_SELECTIVE_SimpleBLE
bool "Enable SimpleBLE"
depends on ARDUINO_SELECTIVE_COMPILATION
default y
endmenu endmenu

View file

@ -345,7 +345,7 @@ Function to get the IPv6 address.
.. code-block:: arduino .. code-block:: arduino
IPAddress softAPIPv6(); IPAddress softAPlinkLocalIPv6();
The function will return the AP IPv6 address in ``IPAddress`` format. The function will return the AP IPv6 address in ``IPAddress`` format.

View file

@ -1,6 +1,6 @@
#include <WiFi.h> #include <WiFi.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>
#include <WiFiUdp.h> #include <NetworkUdp.h>
#include <ArduinoOTA.h> #include <ArduinoOTA.h>
const char* ssid = ".........."; const char* ssid = "..........";

View file

@ -2,8 +2,8 @@
#define LWIP_OPEN_SRC #define LWIP_OPEN_SRC
#endif #endif
#include <functional> #include <functional>
#include <WiFiUdp.h>
#include "ArduinoOTA.h" #include "ArduinoOTA.h"
#include "NetworkClient.h"
#include "ESPmDNS.h" #include "ESPmDNS.h"
#include "MD5Builder.h" #include "MD5Builder.h"
#include "Update.h" #include "Update.h"
@ -128,7 +128,7 @@ void ArduinoOTAClass::begin() {
if (!_hostname.length()) { if (!_hostname.length()) {
char tmp[20]; char tmp[20];
uint8_t mac[6]; uint8_t mac[6];
WiFi.macAddress(mac); Network.macAddress(mac);
sprintf(tmp, "esp32-%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); sprintf(tmp, "esp32-%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
_hostname = tmp; _hostname = tmp;
} }
@ -266,7 +266,7 @@ void ArduinoOTAClass::_runUpdate() {
_progress_callback(0, _size); _progress_callback(0, _size);
} }
WiFiClient client; NetworkClient client;
if (!client.connect(_ota_ip, _ota_port)) { if (!client.connect(_ota_ip, _ota_port)) {
if (_error_callback) { if (_error_callback) {
_error_callback(OTA_CONNECT_ERROR); _error_callback(OTA_CONNECT_ERROR);

View file

@ -1,9 +1,9 @@
#ifndef __ARDUINO_OTA_H #ifndef __ARDUINO_OTA_H
#define __ARDUINO_OTA_H #define __ARDUINO_OTA_H
#include <WiFi.h> #include "Network.h"
#include <functional>
#include "Update.h" #include "Update.h"
#include <functional>
#define INT_BUFFER_SIZE 16 #define INT_BUFFER_SIZE 16
@ -86,7 +86,7 @@ class ArduinoOTAClass
String _hostname; String _hostname;
String _partition_label; String _partition_label;
String _nonce; String _nonce;
WiFiUDP _udp_ota; NetworkUDP _udp_ota;
bool _initialized; bool _initialized;
bool _rebootOnSuccess; bool _rebootOnSuccess;
bool _mdnsEnabled; bool _mdnsEnabled;

View file

@ -20,9 +20,13 @@ DNSServer::DNSServer(const String &domainName) : _port(DNS_DEFAULT_PORT), _ttl(h
bool DNSServer::start(){ bool DNSServer::start(){
if (_resolvedIP.operator uint32_t() == 0){ // no address is set, try to obtain AP interface's IP if (_resolvedIP.operator uint32_t() == 0){ // no address is set, try to obtain AP interface's IP
#if SOC_WIFI_SUPPORTED
if (WiFi.getMode() & WIFI_AP){ if (WiFi.getMode() & WIFI_AP){
_resolvedIP = WiFi.softAPIP(); _resolvedIP = WiFi.softAPIP();
} else return false; // won't run if WiFi is not in AP mode return true;
}
#endif
return false; // won't run if WiFi is not in AP mode
} }
_udp.close(); _udp.close();

View file

@ -26,13 +26,14 @@
// Face Detection will not work on boards without (or with disabled) PSRAM // Face Detection will not work on boards without (or with disabled) PSRAM
#ifdef BOARD_HAS_PSRAM #ifdef BOARD_HAS_PSRAM
#define CONFIG_ESP_FACE_DETECT_ENABLED 1
// Face Recognition takes upward from 15 seconds per frame on chips other than ESP32S3 // Face Recognition takes upward from 15 seconds per frame on chips other than ESP32S3
// Makes no sense to have it enabled for them // Makes no sense to have it enabled for them
#if CONFIG_IDF_TARGET_ESP32S3 #if CONFIG_IDF_TARGET_ESP32S3
#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 1 #define CONFIG_ESP_FACE_RECOGNITION_ENABLED 1
#define CONFIG_ESP_FACE_DETECT_ENABLED 1
#else #else
#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 0 #define CONFIG_ESP_FACE_RECOGNITION_ENABLED 0
#define CONFIG_ESP_FACE_DETECT_ENABLED 0
#endif #endif
#else #else
#define CONFIG_ESP_FACE_DETECT_ENABLED 0 #define CONFIG_ESP_FACE_DETECT_ENABLED 0

View file

@ -18,13 +18,13 @@
#include <WiFi.h> #include <WiFi.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>
#include <WiFiClient.h> #include <NetworkClient.h>
const char* ssid = "............"; const char* ssid = "............";
const char* password = ".............."; const char* password = "..............";
// TCP server at port 80 will respond to HTTP requests // TCP server at port 80 will respond to HTTP requests
WiFiServer server(80); NetworkServer server(80);
void setup(void) void setup(void)
{ {
@ -69,7 +69,7 @@ void setup(void)
void loop(void) void loop(void)
{ {
// Check if a client has connected // Check if a client has connected
WiFiClient client = server.accept(); NetworkClient client = server.accept();
if (!client) { if (!client) {
return; return;
} }

View file

@ -39,10 +39,9 @@ License (MIT license):
#endif #endif
#include "ESPmDNS.h" #include "ESPmDNS.h"
#include "WiFi.h"
#include <functional> #include <functional>
#include "esp_wifi.h" #include "esp_mac.h"
#include "esp_wifi_types.h" #include "soc/soc_caps.h"
// Add quotes around defined value // Add quotes around defined value
#ifdef __IN_ECLIPSE__ #ifdef __IN_ECLIPSE__
@ -52,6 +51,25 @@ License (MIT license):
#define STR(tok) tok #define STR(tok) tok
#endif #endif
// static void addInterface(NetworkInterface * iface){
// #if defined(CONFIG_MDNS_ADD_CUSTOM_NETIF) && !defined(CONFIG_MDNS_PREDEF_NETIF_STA) && !defined(CONFIG_MDNS_PREDEF_NETIF_ETH)
// /* Demonstration of adding a custom netif to mdns service, but we're adding the default example one,
// * so we must disable all predefined interfaces (PREDEF_NETIF_STA, AP and ETH) first
// */
// ESP_ERROR_CHECK(mdns_register_netif(iface->netif()));
// /* It is not enough to just register the interface, we have to enable is manually.
// * This is typically performed in "GOT_IP" event handler, but we call it here directly
// * since the `EXAMPLE_INTERFACE` netif is connected already, to keep the example simple.
// */
// ESP_ERROR_CHECK(mdns_netif_action(iface->netif(), MDNS_EVENT_ENABLE_IP4 | MDNS_EVENT_ENABLE_IP6));
// ESP_ERROR_CHECK(mdns_netif_action(iface->netif(), MDNS_EVENT_ANNOUNCE_IP4 | MDNS_EVENT_ANNOUNCE_IP6));
// #if defined(CONFIG_MDNS_RESPOND_REVERSE_QUERIES)
// ESP_ERROR_CHECK(mdns_netif_action(iface->netif(), MDNS_EVENT_IP4_REVERSE_LOOKUP | MDNS_EVENT_IP6_REVERSE_LOOKUP));
// #endif
// #endif // CONFIG_MDNS_ADD_CUSTOM_NETIF
// }
// static void _on_sys_event(arduino_event_t *event){ // static void _on_sys_event(arduino_event_t *event){
// mdns_handle_system_event(NULL, event); // mdns_handle_system_event(NULL, event);
// } // }
@ -115,7 +133,25 @@ void MDNSResponder::disableArduino(){
void MDNSResponder::enableWorkstation(esp_interface_t interface){ void MDNSResponder::enableWorkstation(esp_interface_t interface){
char winstance[21+_hostname.length()]; char winstance[21+_hostname.length()];
uint8_t mac[6]; uint8_t mac[6];
esp_wifi_get_mac((wifi_interface_t)interface, mac);
esp_mac_type_t mtype = ESP_MAC_ETH;
#if SOC_WIFI_SUPPORTED
switch(interface){
case ESP_IF_WIFI_STA:
mtype = ESP_MAC_WIFI_STA;
break;
case ESP_IF_WIFI_AP:
mtype = ESP_MAC_WIFI_SOFTAP;
break;
default:
break;
}
#endif
if(esp_read_mac(mac, mtype) != ESP_OK){
log_e("Failed to read the MAC address");
return;
}
sprintf(winstance, "%s [%02x:%02x:%02x:%02x:%02x:%02x]", _hostname.c_str(), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); sprintf(winstance, "%s [%02x:%02x:%02x:%02x:%02x:%02x]", _hostname.c_str(), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
if(mdns_service_add(NULL, "_workstation", "_tcp", 9, NULL, 0)) { if(mdns_service_add(NULL, "_workstation", "_tcp", 9, NULL, 0)) {

View file

@ -18,8 +18,8 @@
static bool eth_connected = false; static bool eth_connected = false;
// WARNING: WiFiEvent is called from a separate FreeRTOS task (thread)! // WARNING: onEvent is called from a separate FreeRTOS task (thread)!
void WiFiEvent(WiFiEvent_t event) void onEvent(arduino_event_id_t event)
{ {
switch (event) { switch (event) {
case ARDUINO_EVENT_ETH_START: case ARDUINO_EVENT_ETH_START:
@ -33,7 +33,7 @@ void WiFiEvent(WiFiEvent_t event)
break; break;
case ARDUINO_EVENT_ETH_GOT_IP: case ARDUINO_EVENT_ETH_GOT_IP:
Serial.println("ETH Got IP"); Serial.println("ETH Got IP");
ETH.printInfo(Serial); Serial.println(ETH);
eth_connected = true; eth_connected = true;
break; break;
case ARDUINO_EVENT_ETH_LOST_IP: case ARDUINO_EVENT_ETH_LOST_IP:
@ -58,7 +58,7 @@ void testClient(const char * host, uint16_t port)
Serial.print("\nconnecting to "); Serial.print("\nconnecting to ");
Serial.println(host); Serial.println(host);
WiFiClient client; NetworkClient client;
if (!client.connect(host, port)) { if (!client.connect(host, port)) {
Serial.println("connection failed"); Serial.println("connection failed");
return; return;
@ -76,7 +76,7 @@ void testClient(const char * host, uint16_t port)
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread. Network.onEvent(onEvent);
ETH.begin(); ETH.begin();
} }

View file

@ -16,8 +16,8 @@
static bool eth_connected = false; static bool eth_connected = false;
// WARNING: WiFiEvent is called from a separate FreeRTOS task (thread)! // WARNING: onEvent is called from a separate FreeRTOS task (thread)!
void WiFiEvent(WiFiEvent_t event) void onEvent(arduino_event_id_t event)
{ {
switch (event) { switch (event) {
case ARDUINO_EVENT_ETH_START: case ARDUINO_EVENT_ETH_START:
@ -31,7 +31,7 @@ void WiFiEvent(WiFiEvent_t event)
break; break;
case ARDUINO_EVENT_ETH_GOT_IP: case ARDUINO_EVENT_ETH_GOT_IP:
Serial.println("ETH Got IP"); Serial.println("ETH Got IP");
ETH.printInfo(Serial); Serial.println(ETH);
eth_connected = true; eth_connected = true;
break; break;
case ARDUINO_EVENT_ETH_LOST_IP: case ARDUINO_EVENT_ETH_LOST_IP:
@ -56,7 +56,7 @@ void testClient(const char * host, uint16_t port)
Serial.print("\nconnecting to "); Serial.print("\nconnecting to ");
Serial.println(host); Serial.println(host);
WiFiClient client; NetworkClient client;
if (!client.connect(host, port)) { if (!client.connect(host, port)) {
Serial.println("connection failed"); Serial.println("connection failed");
return; return;
@ -74,7 +74,7 @@ void testClient(const char * host, uint16_t port)
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread. Network.onEvent(onEvent); // Will call onEvent() from another thread.
ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_POWER, ETH_CLK_MODE); ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_POWER, ETH_CLK_MODE);
} }

View file

@ -49,9 +49,9 @@ void onEvent(arduino_event_id_t event, arduino_event_info_t info)
break; break;
case ARDUINO_EVENT_ETH_GOT_IP: case ARDUINO_EVENT_ETH_GOT_IP:
Serial.printf("ETH Got IP: '%s'\n", esp_netif_get_desc(info.got_ip.esp_netif)); Serial.printf("ETH Got IP: '%s'\n", esp_netif_get_desc(info.got_ip.esp_netif));
ETH.printInfo(Serial); Serial.println(ETH);
#if USE_TWO_ETH_PORTS #if USE_TWO_ETH_PORTS
ETH1.printInfo(Serial); Serial.println(ETH1);
#endif #endif
eth_connected = true; eth_connected = true;
break; break;
@ -77,7 +77,7 @@ void testClient(const char * host, uint16_t port)
Serial.print("\nconnecting to "); Serial.print("\nconnecting to ");
Serial.println(host); Serial.println(host);
WiFiClient client; NetworkClient client;
if (!client.connect(host, port)) { if (!client.connect(host, port)) {
Serial.println("connection failed"); Serial.println("connection failed");
return; return;
@ -95,7 +95,7 @@ void testClient(const char * host, uint16_t port)
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
WiFi.onEvent(onEvent); Network.onEvent(onEvent);
SPI.begin(ETH_SPI_SCK, ETH_SPI_MISO, ETH_SPI_MOSI); SPI.begin(ETH_SPI_SCK, ETH_SPI_MISO, ETH_SPI_MOSI);
ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_CS, ETH_PHY_IRQ, ETH_PHY_RST, SPI); ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_CS, ETH_PHY_IRQ, ETH_PHY_RST, SPI);

View file

@ -47,9 +47,9 @@ void onEvent(arduino_event_id_t event, arduino_event_info_t info)
break; break;
case ARDUINO_EVENT_ETH_GOT_IP: case ARDUINO_EVENT_ETH_GOT_IP:
Serial.printf("ETH Got IP: '%s'\n", esp_netif_get_desc(info.got_ip.esp_netif)); Serial.printf("ETH Got IP: '%s'\n", esp_netif_get_desc(info.got_ip.esp_netif));
ETH.printInfo(Serial); Serial.println(ETH);
#if USE_TWO_ETH_PORTS #if USE_TWO_ETH_PORTS
ETH1.printInfo(Serial); Serial.println(ETH1);
#endif #endif
eth_connected = true; eth_connected = true;
break; break;
@ -75,7 +75,7 @@ void testClient(const char * host, uint16_t port)
Serial.print("\nconnecting to "); Serial.print("\nconnecting to ");
Serial.println(host); Serial.println(host);
WiFiClient client; NetworkClient client;
if (!client.connect(host, port)) { if (!client.connect(host, port)) {
Serial.println("connection failed"); Serial.println("connection failed");
return; return;
@ -93,7 +93,7 @@ void testClient(const char * host, uint16_t port)
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
WiFi.onEvent(onEvent); Network.onEvent(onEvent);
ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_CS, ETH_PHY_IRQ, ETH_PHY_RST, ETH_PHY_SPI_HOST, ETH_PHY_SPI_SCK, ETH_PHY_SPI_MISO, ETH_PHY_SPI_MOSI); ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_CS, ETH_PHY_IRQ, ETH_PHY_RST, ETH_PHY_SPI_HOST, ETH_PHY_SPI_SCK, ETH_PHY_SPI_MISO, ETH_PHY_SPI_MOSI);
#if USE_TWO_ETH_PORTS #if USE_TWO_ETH_PORTS
// Since SPI bus is shared, we should skip the SPI pins when calling ETH1.begin() // Since SPI bus is shared, we should skip the SPI pins when calling ETH1.begin()

View file

@ -42,14 +42,81 @@
#include "esp_netif_defaults.h" #include "esp_netif_defaults.h"
#include "esp_eth_phy.h" #include "esp_eth_phy.h"
extern void tcpipInit(); static ETHClass * _ethernets[3] = { NULL, NULL, NULL };
extern void add_esp_interface_netif(esp_interface_t interface, esp_netif_t* esp_netif); /* from WiFiGeneric */ static esp_event_handler_instance_t _eth_ev_instance = NULL;
static void _eth_event_cb(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
if (event_base == ETH_EVENT){
esp_eth_handle_t eth_handle = *((esp_eth_handle_t*)event_data);
for(int i = 0; i < 3; ++i){
if(_ethernets[i] != NULL && _ethernets[i]->handle() == eth_handle){
_ethernets[i]->_onEthEvent(event_id, event_data);
}
}
}
}
// This callback needs to be aware of which interface it should match against
static void onEthConnected(arduino_event_id_t event, arduino_event_info_t info)
{
if(event == ARDUINO_EVENT_ETH_CONNECTED){
uint8_t index = 3;
for (int i = 0; i < 3; ++i) {
if(_ethernets[i] != NULL && _ethernets[i]->handle() == info.eth_connected){
index = i;
break;
}
}
if(index == 3){
log_e("Could not find ETH interface with that handle!");
return;
}
if (_ethernets[index]->getStatusBits() & ESP_NETIF_WANT_IP6_BIT){
esp_err_t err = esp_netif_create_ip6_linklocal(_ethernets[index]->netif());
if(err != ESP_OK){
log_e("Failed to enable IPv6 Link Local on ETH: [%d] %s", err, esp_err_to_name(err));
} else {
log_v("Enabled IPv6 Link Local on %s", _ethernets[index]->desc());
}
}
}
}
esp_eth_handle_t ETHClass::handle() const {
return _eth_handle;
}
void ETHClass::_onEthEvent(int32_t event_id, void* event_data){
arduino_event_t arduino_event;
arduino_event.event_id = ARDUINO_EVENT_MAX;
if (event_id == ETHERNET_EVENT_CONNECTED) {
log_v("%s Connected", desc());
arduino_event.event_id = ARDUINO_EVENT_ETH_CONNECTED;
arduino_event.event_info.eth_connected = handle();
setStatusBits(ESP_NETIF_CONNECTED_BIT);
} else if (event_id == ETHERNET_EVENT_DISCONNECTED) {
log_v("%s Disconnected", desc());
arduino_event.event_id = ARDUINO_EVENT_ETH_DISCONNECTED;
clearStatusBits(ESP_NETIF_CONNECTED_BIT | ESP_NETIF_HAS_IP_BIT | ESP_NETIF_HAS_LOCAL_IP6_BIT | ESP_NETIF_HAS_GLOBAL_IP6_BIT);
} else if (event_id == ETHERNET_EVENT_START) {
log_v("%s Started", desc());
arduino_event.event_id = ARDUINO_EVENT_ETH_START;
setStatusBits(ESP_NETIF_STARTED_BIT);
} else if (event_id == ETHERNET_EVENT_STOP) {
log_v("%s Stopped", desc());
arduino_event.event_id = ARDUINO_EVENT_ETH_STOP;
clearStatusBits(ESP_NETIF_STARTED_BIT | ESP_NETIF_CONNECTED_BIT | ESP_NETIF_HAS_IP_BIT | ESP_NETIF_HAS_LOCAL_IP6_BIT | ESP_NETIF_HAS_GLOBAL_IP6_BIT);
}
if(arduino_event.event_id < ARDUINO_EVENT_MAX){
Network.postEvent(&arduino_event);
}
}
ETHClass::ETHClass(uint8_t eth_index) ETHClass::ETHClass(uint8_t eth_index)
:_eth_started(false) :_eth_handle(NULL)
,_eth_handle(NULL)
,_esp_netif(NULL)
,_eth_index(eth_index) ,_eth_index(eth_index)
,_phy_type(ETH_PHY_MAX) ,_phy_type(ETH_PHY_MAX)
#if ETH_SPI_SUPPORTS_CUSTOM #if ETH_SPI_SUPPORTS_CUSTOM
@ -75,9 +142,7 @@ ETHClass::~ETHClass()
bool ETHClass::ethDetachBus(void * bus_pointer){ bool ETHClass::ethDetachBus(void * bus_pointer){
ETHClass *bus = (ETHClass *) bus_pointer; ETHClass *bus = (ETHClass *) bus_pointer;
if(bus->_eth_started){
bus->end(); bus->end();
}
return true; return true;
} }
@ -85,6 +150,9 @@ bool ETHClass::ethDetachBus(void * bus_pointer){
bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clock_mode) bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, int power, eth_clock_mode_t clock_mode)
{ {
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
if(_eth_index > 2){
return false;
}
if(_esp_netif != NULL){ if(_esp_netif != NULL){
return true; return true;
} }
@ -100,7 +168,12 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i
perimanSetBusDeinit(ESP32_BUS_TYPE_ETHERNET_PWR, ETHClass::ethDetachBus); perimanSetBusDeinit(ESP32_BUS_TYPE_ETHERNET_PWR, ETHClass::ethDetachBus);
} }
tcpipInit(); Network.begin();
_ethernets[_eth_index] = this;
if(_eth_ev_instance == NULL && esp_event_handler_instance_register(ETH_EVENT, ESP_EVENT_ANY_ID, &_eth_event_cb, NULL, &_eth_ev_instance)){
log_e("event_handler_instance_register for ETH_EVENT Failed!");
return false;
}
eth_esp32_emac_config_t mac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); eth_esp32_emac_config_t mac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
mac_config.clock_config.rmii.clock_mode = (clock_mode) ? EMAC_CLK_OUT : EMAC_CLK_EXT_IN; mac_config.clock_config.rmii.clock_mode = (clock_mode) ? EMAC_CLK_OUT : EMAC_CLK_EXT_IN;
@ -188,7 +261,11 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i
char if_desc_str[10]; char if_desc_str[10];
char num_str[3]; char num_str[3];
itoa(_eth_index, num_str, 10); itoa(_eth_index, num_str, 10);
if(_eth_index == 0){
strcpy(if_key_str, "ETH_DEF");
} else {
strcat(strcpy(if_key_str, "ETH_"), num_str); strcat(strcpy(if_key_str, "ETH_"), num_str);
}
strcat(strcpy(if_desc_str, "eth"), num_str); strcat(strcpy(if_desc_str, "eth"), num_str);
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
@ -207,15 +284,14 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i
return false; return false;
} }
/* attach to WiFiGeneric to receive events */ /* attach to receive events */
add_esp_interface_netif(ESP_IF_ETH, _esp_netif); initNetif((Network_Interface_ID)(ESP_NETIF_ID_ETH+_eth_index));
ret = esp_eth_start(_eth_handle); ret = esp_eth_start(_eth_handle);
if(ret != ESP_OK){ if(ret != ESP_OK){
log_e("esp_eth_start failed: %d", ret); log_e("esp_eth_start failed: %d", ret);
return false; return false;
} }
_eth_started = true;
if(!perimanSetPinBus(_pin_rmii_clock, ESP32_BUS_TYPE_ETHERNET_CLK, (void *)(this), -1, -1)){ goto err; } if(!perimanSetPinBus(_pin_rmii_clock, ESP32_BUS_TYPE_ETHERNET_CLK, (void *)(this), -1, -1)){ goto err; }
if(!perimanSetPinBus(_pin_mcd, ESP32_BUS_TYPE_ETHERNET_MCD, (void *)(this), -1, -1)){ goto err; } if(!perimanSetPinBus(_pin_mcd, ESP32_BUS_TYPE_ETHERNET_MCD, (void *)(this), -1, -1)){ goto err; }
@ -231,6 +307,9 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int mdc, int mdio, i
if(_pin_power != -1){ if(_pin_power != -1){
if(!perimanSetPinBus(_pin_power, ESP32_BUS_TYPE_ETHERNET_PWR, (void *)(this), -1, -1)){ goto err; } if(!perimanSetPinBus(_pin_power, ESP32_BUS_TYPE_ETHERNET_PWR, (void *)(this), -1, -1)){ goto err; }
} }
Network.onSysEvent(onEthConnected, ARDUINO_EVENT_ETH_CONNECTED);
// holds a few milliseconds to let DHCP start and enter into a good state // holds a few milliseconds to let DHCP start and enter into a good state
// FIX ME -- adresses issue https://github.com/espressif/arduino-esp32/issues/5733 // FIX ME -- adresses issue https://github.com/espressif/arduino-esp32/issues/5733
delay(50); delay(50);
@ -351,7 +430,7 @@ bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq,
int sck, int miso, int mosi, spi_host_device_t spi_host, uint8_t spi_freq_mhz){ int sck, int miso, int mosi, spi_host_device_t spi_host, uint8_t spi_freq_mhz){
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
if(_eth_started || _esp_netif != NULL || _eth_handle != NULL){ if(_esp_netif != NULL || _eth_handle != NULL){
log_w("ETH Already Started"); log_w("ETH Already Started");
return true; return true;
} }
@ -421,6 +500,11 @@ bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq,
buscfg.sclk_io_num = _pin_sck; buscfg.sclk_io_num = _pin_sck;
buscfg.quadwp_io_num = -1; buscfg.quadwp_io_num = -1;
buscfg.quadhd_io_num = -1; buscfg.quadhd_io_num = -1;
buscfg.data4_io_num = -1;
buscfg.data5_io_num = -1;
buscfg.data6_io_num = -1;
buscfg.data7_io_num = -1;
buscfg.max_transfer_sz = -1;
ret = spi_bus_initialize(spi_host, &buscfg, SPI_DMA_CH_AUTO); ret = spi_bus_initialize(spi_host, &buscfg, SPI_DMA_CH_AUTO);
if(ret != ESP_OK){ if(ret != ESP_OK){
log_e("SPI bus initialize failed: %d", ret); log_e("SPI bus initialize failed: %d", ret);
@ -428,7 +512,13 @@ bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq,
} }
} }
tcpipInit(); Network.begin();
_ethernets[_eth_index] = this;
if(_eth_ev_instance == NULL && esp_event_handler_instance_register(ETH_EVENT, ESP_EVENT_ANY_ID, &_eth_event_cb, NULL, &_eth_ev_instance)){
log_e("event_handler_instance_register for ETH_EVENT Failed!");
return false;
}
// Install GPIO ISR handler to be able to service SPI Eth modules interrupts // Install GPIO ISR handler to be able to service SPI Eth modules interrupts
ret = gpio_install_isr_service(0); ret = gpio_install_isr_service(0);
@ -556,7 +646,11 @@ bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq,
char if_desc_str[10]; char if_desc_str[10];
char num_str[3]; char num_str[3];
itoa(_eth_index, num_str, 10); itoa(_eth_index, num_str, 10);
if(_eth_index == 0){
strcpy(if_key_str, "ETH_DEF");
} else {
strcat(strcpy(if_key_str, "ETH_"), num_str); strcat(strcpy(if_key_str, "ETH_"), num_str);
}
strcat(strcpy(if_desc_str, "eth"), num_str); strcat(strcpy(if_desc_str, "eth"), num_str);
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
@ -584,8 +678,8 @@ bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq,
return false; return false;
} }
// attach to WiFiGeneric to receive events /* attach to receive events */
add_esp_interface_netif(ESP_IF_ETH, _esp_netif); initNetif((Network_Interface_ID)(ESP_NETIF_ID_ETH+_eth_index));
// Start Ethernet driver state machine // Start Ethernet driver state machine
ret = esp_eth_start(_eth_handle); ret = esp_eth_start(_eth_handle);
@ -594,8 +688,6 @@ bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq,
return false; return false;
} }
_eth_started = true;
// If Arduino's SPI is used, cs pin is in GPIO mode // If Arduino's SPI is used, cs pin is in GPIO mode
#if ETH_SPI_SUPPORTS_CUSTOM #if ETH_SPI_SUPPORTS_CUSTOM
if(_spi == NULL){ if(_spi == NULL){
@ -624,6 +716,8 @@ bool ETHClass::beginSPI(eth_phy_type_t type, int32_t phy_addr, int cs, int irq,
if(!perimanSetPinBus(_pin_rst, ESP32_BUS_TYPE_ETHERNET_SPI, (void *)(this), -1, -1)){ goto err; } if(!perimanSetPinBus(_pin_rst, ESP32_BUS_TYPE_ETHERNET_SPI, (void *)(this), -1, -1)){ goto err; }
} }
Network.onSysEvent(onEthConnected, ARDUINO_EVENT_ETH_CONNECTED);
return true; return true;
err: err:
@ -650,12 +744,15 @@ bool ETHClass::begin(eth_phy_type_t type, int32_t phy_addr, int cs, int irq, int
void ETHClass::end(void) void ETHClass::end(void)
{ {
_eth_started = false; destroyNetif();
if(_esp_netif != NULL){ if(_eth_ev_instance != NULL){
esp_netif_destroy(_esp_netif); if(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &_eth_event_cb) == ESP_OK){
_esp_netif = NULL; _eth_ev_instance = NULL;
} }
}
Network.removeEvent(onEthConnected, ARDUINO_EVENT_ETH_CONNECTED);
if(_eth_handle != NULL){ if(_eth_handle != NULL){
if(esp_eth_stop(_eth_handle) != ESP_OK){ if(esp_eth_stop(_eth_handle) != ESP_OK){
@ -722,255 +819,7 @@ void ETHClass::end(void)
} }
} }
bool ETHClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) bool ETHClass::fullDuplex() const
{
if(_esp_netif == NULL){
return false;
}
esp_err_t err = ESP_OK;
esp_netif_ip_info_t info;
esp_netif_dns_info_t d1;
esp_netif_dns_info_t d2;
d1.ip.type = IPADDR_TYPE_V4;
d2.ip.type = IPADDR_TYPE_V4;
if(static_cast<uint32_t>(local_ip) != 0){
info.ip.addr = static_cast<uint32_t>(local_ip);
info.gw.addr = static_cast<uint32_t>(gateway);
info.netmask.addr = static_cast<uint32_t>(subnet);
d1.ip.u_addr.ip4.addr = static_cast<uint32_t>(dns1);
d2.ip.u_addr.ip4.addr = static_cast<uint32_t>(dns2);
} else {
info.ip.addr = 0;
info.gw.addr = 0;
info.netmask.addr = 0;
d1.ip.u_addr.ip4.addr = 0;
d2.ip.u_addr.ip4.addr = 0;
}
// Stop DHCPC
err = esp_netif_dhcpc_stop(_esp_netif);
if(err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED){
log_e("DHCP could not be stopped! Error: %d", err);
return false;
}
// Set IPv4, Netmask, Gateway
err = esp_netif_set_ip_info(_esp_netif, &info);
if(err != ERR_OK){
log_e("ETH IP could not be configured! Error: %d", err);
return false;
}
// Set DNS1-Server
esp_netif_set_dns_info(_esp_netif, ESP_NETIF_DNS_MAIN, &d1);
// Set DNS2-Server
esp_netif_set_dns_info(_esp_netif, ESP_NETIF_DNS_BACKUP, &d2);
// Start DHCPC if static IP was set
if(info.ip.addr == 0){
err = esp_netif_dhcpc_start(_esp_netif);
if(err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED){
log_w("DHCP could not be started! Error: %d", err);
return false;
}
}
return true;
}
IPAddress ETHClass::localIP()
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return IPAddress();
}
return IPAddress(ip.ip.addr);
}
IPAddress ETHClass::subnetMask()
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return IPAddress();
}
return IPAddress(ip.netmask.addr);
}
IPAddress ETHClass::gatewayIP()
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return IPAddress();
}
return IPAddress(ip.gw.addr);
}
IPAddress ETHClass::dnsIP(uint8_t dns_no)
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_dns_info_t d;
if(esp_netif_get_dns_info(_esp_netif, dns_no?ESP_NETIF_DNS_BACKUP:ESP_NETIF_DNS_MAIN, &d) != ESP_OK){
return IPAddress();
}
return IPAddress(d.ip.u_addr.ip4.addr);
}
IPAddress ETHClass::broadcastIP()
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return IPAddress();
}
return WiFiGenericClass::calculateBroadcast(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr));
}
IPAddress ETHClass::networkID()
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return IPAddress();
}
return WiFiGenericClass::calculateNetworkID(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr));
}
uint8_t ETHClass::subnetCIDR()
{
if(_esp_netif == NULL){
return (uint8_t)0;
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return (uint8_t)0;
}
return WiFiGenericClass::calculateSubnetCIDR(IPAddress(ip.netmask.addr));
}
const char * ETHClass::getHostname()
{
if(_esp_netif == NULL){
return "";
}
const char * hostname;
if(esp_netif_get_hostname(_esp_netif, &hostname)){
return NULL;
}
return hostname;
}
bool ETHClass::setHostname(const char * hostname)
{
if(_esp_netif == NULL){
return false;
}
return esp_netif_set_hostname(_esp_netif, hostname) == 0;
}
bool ETHClass::enableIPv6(bool en)
{
// if(_esp_netif == NULL){
// return false;
// }
// return esp_netif_create_ip6_linklocal(_esp_netif) == 0;
if (en) {
WiFiGenericClass::setStatusBits(ETH_WANT_IP6_BIT);
} else {
WiFiGenericClass::clearStatusBits(ETH_WANT_IP6_BIT);
}
return true;
}
IPAddress ETHClass::localIPv6()
{
if(_esp_netif == NULL){
return IPAddress(IPv6);
}
static esp_ip6_addr_t addr;
if(esp_netif_get_ip6_linklocal(_esp_netif, &addr)){
return IPAddress(IPv6);
}
return IPAddress(IPv6, (const uint8_t *)addr.addr, addr.zone);
}
IPAddress ETHClass::globalIPv6()
{
if(_esp_netif == NULL){
return IPAddress(IPv6);
}
static esp_ip6_addr_t addr;
if(esp_netif_get_ip6_global(_esp_netif, &addr)){
return IPAddress(IPv6);
}
return IPAddress(IPv6, (const uint8_t *)addr.addr, addr.zone);
}
const char * ETHClass::ifkey(void)
{
if(_esp_netif == NULL){
return "";
}
return esp_netif_get_ifkey(_esp_netif);
}
const char * ETHClass::desc(void)
{
if(_esp_netif == NULL){
return "";
}
return esp_netif_get_desc(_esp_netif);
}
String ETHClass::impl_name(void)
{
if(_esp_netif == NULL){
return String("");
}
char netif_name[8];
esp_err_t err = esp_netif_get_netif_impl_name(_esp_netif, netif_name);
if(err != ESP_OK){
log_e("Failed to get netif impl_name: %d", err);
return String("");
}
return String(netif_name);
}
bool ETHClass::connected()
{
return WiFiGenericClass::getStatusBits() & ETH_CONNECTED_BIT;
}
bool ETHClass::hasIP()
{
return WiFiGenericClass::getStatusBits() & ETH_HAS_IP_BIT;
}
bool ETHClass::linkUp()
{
if(_esp_netif == NULL){
return false;
}
return esp_netif_is_netif_up(_esp_netif);
}
bool ETHClass::fullDuplex()
{ {
if(_eth_handle == NULL){ if(_eth_handle == NULL){
return false; return false;
@ -980,7 +829,7 @@ bool ETHClass::fullDuplex()
return (link_duplex == ETH_DUPLEX_FULL); return (link_duplex == ETH_DUPLEX_FULL);
} }
bool ETHClass::autoNegotiation() bool ETHClass::autoNegotiation() const
{ {
if(_eth_handle == NULL){ if(_eth_handle == NULL){
return false; return false;
@ -990,7 +839,7 @@ bool ETHClass::autoNegotiation()
return auto_nego; return auto_nego;
} }
uint32_t ETHClass::phyAddr() uint32_t ETHClass::phyAddr() const
{ {
if(_eth_handle == NULL){ if(_eth_handle == NULL){
return 0; return 0;
@ -1000,7 +849,7 @@ uint32_t ETHClass::phyAddr()
return phy_addr; return phy_addr;
} }
uint8_t ETHClass::linkSpeed() uint8_t ETHClass::linkSpeed() const
{ {
if(_eth_handle == NULL){ if(_eth_handle == NULL){
return 0; return 0;
@ -1010,91 +859,26 @@ uint8_t ETHClass::linkSpeed()
return (link_speed == ETH_SPEED_10M)?10:100; return (link_speed == ETH_SPEED_10M)?10:100;
} }
uint8_t * ETHClass::macAddress(uint8_t* mac) // void ETHClass::getMac(uint8_t* mac)
{ // {
if(_eth_handle == NULL){ // if(_eth_handle != NULL && mac != NULL){
return NULL; // esp_eth_ioctl(_eth_handle, ETH_CMD_G_MAC_ADDR, mac);
} // }
if(!mac){ // }
return NULL;
}
esp_eth_ioctl(_eth_handle, ETH_CMD_G_MAC_ADDR, mac);
return mac;
}
String ETHClass::macAddress(void) size_t ETHClass::printDriverInfo(Print & out) const {
{ size_t bytes = 0;
uint8_t mac[6] = {0,0,0,0,0,0}; bytes += out.print(",");
char macStr[18] = { 0 }; bytes += out.print(linkSpeed());
macAddress(mac); bytes += out.print("M");
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(macStr);
}
void ETHClass::printInfo(Print & out){
out.print(desc());
out.print(":");
if(linkUp()){
out.print(" <UP");
} else {
out.print(" <DOWN");
}
out.print(",");
out.print(linkSpeed());
out.print("M");
if(fullDuplex()){ if(fullDuplex()){
out.print(",FULL_DUPLEX"); bytes += out.print(",FULL_DUPLEX");
} }
if(autoNegotiation()){ if(autoNegotiation()){
out.print(",AUTO"); bytes += out.print(",AUTO");
} }
out.println(">"); bytes += out.printf(",ADDR:0x%lX", phyAddr());
return bytes;
out.print(" ");
out.print("ether ");
out.print(macAddress());
out.printf(" phy 0x%lX", phyAddr());
out.println();
out.print(" ");
out.print("inet ");
out.print(localIP());
out.print(" netmask ");
out.print(subnetMask());
out.print(" broadcast ");
out.print(broadcastIP());
out.println();
out.print(" ");
out.print("gateway ");
out.print(gatewayIP());
out.print(" dns ");
out.print(dnsIP());
out.println();
static const char * types[] = { "UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6" };
esp_ip6_addr_t if_ip6[CONFIG_LWIP_IPV6_NUM_ADDRESSES];
int v6addrs = esp_netif_get_all_ip6(_esp_netif, if_ip6);
for (int i = 0; i < v6addrs; ++i){
out.print(" ");
out.print("inet6 ");
IPAddress(IPv6, (const uint8_t *)if_ip6[i].addr, if_ip6[i].zone).printTo(out, true);
out.print(" type ");
out.print(types[esp_netif_ip6_get_addr_type(&if_ip6[i])]);
out.println();
}
// out.print(" ");
// out.print("inet6 ");
// localIPv6().printTo(out);
// out.println();
// out.print(" ");
// out.print("inet6 ");
// globalIPv6().printTo(out);
// out.println();
out.println();
} }
ETHClass ETH; ETHClass ETH;

View file

@ -63,7 +63,8 @@
// This will be uncommented once custom SPI support is available in ESP-IDF // This will be uncommented once custom SPI support is available in ESP-IDF
#define ETH_SPI_SUPPORTS_CUSTOM 1 #define ETH_SPI_SUPPORTS_CUSTOM 1
#include "WiFi.h" #include "Network.h"
#if ETH_SPI_SUPPORTS_CUSTOM #if ETH_SPI_SUPPORTS_CUSTOM
#include "SPI.h" #include "SPI.h"
#endif #endif
@ -105,7 +106,7 @@ typedef enum {
ETH_PHY_MAX ETH_PHY_MAX
} eth_phy_type_t; } eth_phy_type_t;
class ETHClass { class ETHClass: public NetworkInterface {
public: public:
ETHClass(uint8_t eth_index=0); ETHClass(uint8_t eth_index=0);
~ETHClass(); ~ETHClass();
@ -135,43 +136,13 @@ class ETHClass {
void end(); void end();
// Netif APIs
esp_netif_t * netif(void){ return _esp_netif; }
bool config(IPAddress local_ip = (uint32_t)0x00000000, IPAddress gateway = (uint32_t)0x00000000, IPAddress subnet = (uint32_t)0x00000000, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000);
const char * getHostname();
bool setHostname(const char * hostname);
IPAddress localIP();
IPAddress subnetMask();
IPAddress gatewayIP();
IPAddress dnsIP(uint8_t dns_no = 0);
IPAddress broadcastIP();
IPAddress networkID();
uint8_t subnetCIDR();
bool enableIPv6(bool en=true);
IPAddress localIPv6();
IPAddress globalIPv6();
const char * ifkey(void);
const char * desc(void);
String impl_name(void);
// Event based getters
bool connected();
bool hasIP();
// ETH Handle APIs // ETH Handle APIs
uint8_t * macAddress(uint8_t* mac); bool fullDuplex() const;
String macAddress(); uint8_t linkSpeed() const;
bool fullDuplex(); bool autoNegotiation() const;
bool linkUp(); uint32_t phyAddr() const;
uint8_t linkSpeed();
bool autoNegotiation();
uint32_t phyAddr();
// Info APIs esp_eth_handle_t handle() const;
void printInfo(Print & out);
friend class WiFiClient;
friend class WiFiServer;
#if ETH_SPI_SUPPORTS_CUSTOM #if ETH_SPI_SUPPORTS_CUSTOM
static esp_err_t _eth_spi_read(void *ctx, uint32_t cmd, uint32_t addr, void *data, uint32_t data_len); static esp_err_t _eth_spi_read(void *ctx, uint32_t cmd, uint32_t addr, void *data, uint32_t data_len);
@ -184,12 +155,15 @@ class ETHClass {
esp_err_t eth_spi_write(uint32_t cmd, uint32_t addr, const void *data, uint32_t data_len); esp_err_t eth_spi_write(uint32_t cmd, uint32_t addr, const void *data, uint32_t data_len);
#endif #endif
static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); // void getMac(uint8_t* mac);
size_t printDriverInfo(Print & out) const;
// static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
public:
void _onEthEvent(int32_t event_id, void* event_data);
private: private:
bool _eth_started;
esp_eth_handle_t _eth_handle; esp_eth_handle_t _eth_handle;
esp_netif_t *_esp_netif;
uint8_t _eth_index; uint8_t _eth_index;
eth_phy_type_t _phy_type; eth_phy_type_t _phy_type;
#if ETH_SPI_SUPPORTS_CUSTOM #if ETH_SPI_SUPPORTS_CUSTOM

View file

@ -12,7 +12,7 @@
#include <HTTPClient.h> #include <HTTPClient.h>
#include <WiFiClientSecure.h> #include <NetworkClientSecure.h>
// This is GandiStandardSSLCA2.pem, the root Certificate Authority that signed // This is GandiStandardSSLCA2.pem, the root Certificate Authority that signed
// the server certifcate for the demo server https://jigsaw.w3.org in this // the server certifcate for the demo server https://jigsaw.w3.org in this
@ -53,7 +53,7 @@ const char* rootCACertificate = \
"BT02Vf6Dsuimrdfp5gJ0iHRc2jTbkNJtUQoj1iM=\n" \ "BT02Vf6Dsuimrdfp5gJ0iHRc2jTbkNJtUQoj1iM=\n" \
"-----END CERTIFICATE-----\n"; "-----END CERTIFICATE-----\n";
// Not sure if WiFiClientSecure checks the validity date of the certificate. // Not sure if NetworkClientSecure checks the validity date of the certificate.
// Setting clock just to be sure... // Setting clock just to be sure...
void setClock() { void setClock() {
configTime(0, 0, "pool.ntp.org"); configTime(0, 0, "pool.ntp.org");
@ -100,12 +100,12 @@ void setup() {
} }
void loop() { void loop() {
WiFiClientSecure *client = new WiFiClientSecure; NetworkClientSecure *client = new NetworkClientSecure;
if(client) { if(client) {
client -> setCACert(rootCACertificate); client -> setCACert(rootCACertificate);
{ {
// Add a scoping block for HTTPClient https to make sure it is destroyed before WiFiClientSecure *client is // Add a scoping block for HTTPClient https to make sure it is destroyed before NetworkClientSecure *client is
HTTPClient https; HTTPClient https;
Serial.print("[HTTPS] begin...\n"); Serial.print("[HTTPS] begin...\n");

View file

@ -63,7 +63,7 @@ void loop() {
uint8_t buff[128] = { 0 }; uint8_t buff[128] = { 0 };
// get tcp stream // get tcp stream
WiFiClient * stream = http.getStreamPtr(); NetworkClient * stream = http.getStreamPtr();
// read all data from server // read all data from server
while(http.connected() && (len > 0 || len == -1)) { while(http.connected() && (len > 0 || len == -1)) {

View file

@ -30,8 +30,8 @@
#include <esp32-hal-log.h> #include <esp32-hal-log.h>
#ifdef HTTPCLIENT_1_1_COMPATIBLE #ifdef HTTPCLIENT_1_1_COMPATIBLE
#include <WiFi.h> #include <NetworkClient.h>
#include <WiFiClientSecure.h> #include <NetworkClientSecure.h>
#endif #endif
#include <StreamString.h> #include <StreamString.h>
@ -50,12 +50,12 @@ public:
{ {
} }
virtual std::unique_ptr<WiFiClient> create() virtual std::unique_ptr<NetworkClient> create()
{ {
return std::unique_ptr<WiFiClient>(new WiFiClient()); return std::unique_ptr<NetworkClient>(new NetworkClient());
} }
virtual bool verify(WiFiClient& client, const char* host) virtual bool verify(NetworkClient& client, const char* host)
{ {
return true; return true;
} }
@ -69,14 +69,14 @@ public:
{ {
} }
std::unique_ptr<WiFiClient> create() override std::unique_ptr<NetworkClient> create() override
{ {
return std::unique_ptr<WiFiClient>(new WiFiClientSecure()); return std::unique_ptr<NetworkClient>(new NetworkClientSecure());
} }
bool verify(WiFiClient& client, const char* host) override bool verify(NetworkClient& client, const char* host) override
{ {
WiFiClientSecure& wcs = static_cast<WiFiClientSecure&>(client); NetworkClientSecure& wcs = static_cast<NetworkClientSecure&>(client);
if (_cacert == nullptr) { if (_cacert == nullptr) {
wcs.setInsecure(); wcs.setInsecure();
} else { } else {
@ -135,7 +135,7 @@ void HTTPClient::clear()
* @param https bool * @param https bool
* @return success bool * @return success bool
*/ */
bool HTTPClient::begin(WiFiClient &client, String url) { bool HTTPClient::begin(NetworkClient &client, String url) {
#ifdef HTTPCLIENT_1_1_COMPATIBLE #ifdef HTTPCLIENT_1_1_COMPATIBLE
if(_tcpDeprecated) { if(_tcpDeprecated) {
log_d("mix up of new and deprecated api"); log_d("mix up of new and deprecated api");
@ -174,7 +174,7 @@ bool HTTPClient::begin(WiFiClient &client, String url) {
* @param https bool * @param https bool
* @return success bool * @return success bool
*/ */
bool HTTPClient::begin(WiFiClient &client, String host, uint16_t port, String uri, bool https) bool HTTPClient::begin(NetworkClient &client, String host, uint16_t port, String uri, bool https)
{ {
#ifdef HTTPCLIENT_1_1_COMPATIBLE #ifdef HTTPCLIENT_1_1_COMPATIBLE
if(_tcpDeprecated) { if(_tcpDeprecated) {
@ -862,24 +862,24 @@ int HTTPClient::getSize(void)
/** /**
* returns the stream of the tcp connection * returns the stream of the tcp connection
* @return WiFiClient * @return NetworkClient
*/ */
WiFiClient& HTTPClient::getStream(void) NetworkClient& HTTPClient::getStream(void)
{ {
if (connected()) { if (connected()) {
return *_client; return *_client;
} }
log_w("getStream: not connected"); log_w("getStream: not connected");
static WiFiClient empty; static NetworkClient empty;
return empty; return empty;
} }
/** /**
* returns a pointer to the stream of the tcp connection * returns a pointer to the stream of the tcp connection
* @return WiFiClient* * @return NetworkClient*
*/ */
WiFiClient* HTTPClient::getStreamPtr(void) NetworkClient* HTTPClient::getStreamPtr(void)
{ {
if(connected()) { if(connected()) {
return _client; return _client;
@ -1164,7 +1164,7 @@ bool HTTPClient::connect(void)
return false; return false;
} }
// set Timeout for WiFiClient and for Stream::readBytesUntil() and Stream::readStringUntil() // set Timeout for NetworkClient and for Stream::readBytesUntil() and Stream::readStringUntil()
_client->setTimeout(_tcpTimeout); _client->setTimeout(_tcpTimeout);
log_d(" connected to %s:%u", _host.c_str(), _port); log_d(" connected to %s:%u", _host.c_str(), _port);

View file

@ -33,8 +33,8 @@
#include <memory> #include <memory>
#include <Arduino.h> #include <Arduino.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WiFiClientSecure.h> #include <NetworkClientSecure.h>
/// Cookie jar support /// Cookie jar support
#include <vector> #include <vector>
@ -180,8 +180,8 @@ public:
* Since both begin() functions take a reference to client as a parameter, you need to * Since both begin() functions take a reference to client as a parameter, you need to
* ensure the client object lives the entire time of the HTTPClient * ensure the client object lives the entire time of the HTTPClient
*/ */
bool begin(WiFiClient &client, String url); bool begin(NetworkClient &client, String url);
bool begin(WiFiClient &client, String host, uint16_t port, String uri = "/", bool https = false); bool begin(NetworkClient &client, String host, uint16_t port, String uri = "/", bool https = false);
#ifdef HTTPCLIENT_1_1_COMPATIBLE #ifdef HTTPCLIENT_1_1_COMPATIBLE
bool begin(String url); bool begin(String url);
@ -236,8 +236,8 @@ public:
int getSize(void); int getSize(void);
const String &getLocation(void); const String &getLocation(void);
WiFiClient& getStream(void); NetworkClient& getStream(void);
WiFiClient* getStreamPtr(void); NetworkClient* getStreamPtr(void);
int writeToStream(Stream* stream); int writeToStream(Stream* stream);
String getString(void); String getString(void);
@ -269,10 +269,10 @@ protected:
#ifdef HTTPCLIENT_1_1_COMPATIBLE #ifdef HTTPCLIENT_1_1_COMPATIBLE
TransportTraitsPtr _transportTraits; TransportTraitsPtr _transportTraits;
std::unique_ptr<WiFiClient> _tcpDeprecated; std::unique_ptr<NetworkClient> _tcpDeprecated;
#endif #endif
WiFiClient* _client = nullptr; NetworkClient* _client = nullptr;
/// request handling /// request handling
String _host; String _host;

View file

@ -56,7 +56,7 @@ void loop() {
// wait for WiFi connection // wait for WiFi connection
if ((WiFiMulti.run() == WL_CONNECTED)) { if ((WiFiMulti.run() == WL_CONNECTED)) {
WiFiClient client; NetworkClient client;
// The line below is optional. It can be used to blink the LED on the board during flashing // The line below is optional. It can be used to blink the LED on the board during flashing
// The LED will be on during download of one buffer of data from the network. The LED will // The LED will be on during download of one buffer of data from the network. The LED will

View file

@ -41,7 +41,7 @@ void loop() {
Serial.println("Update SPIFFS..."); Serial.println("Update SPIFFS...");
WiFiClient client; NetworkClient client;
// The line below is optional. It can be used to blink the LED on the board during flashing // The line below is optional. It can be used to blink the LED on the board during flashing
// The LED will be on during download of one buffer of data from the network. The LED will // The LED will be on during download of one buffer of data from the network. The LED will

View file

@ -92,7 +92,7 @@ void loop() {
setClock(); setClock();
WiFiClientSecure client; NetworkClientSecure client;
client.setCACert(rootCACertificate); client.setCACert(rootCACertificate);
// Reading data over SSL may be slow, use an adequate timeout // Reading data over SSL may be slow, use an adequate timeout

View file

@ -25,6 +25,9 @@
#include "HTTPUpdate.h" #include "HTTPUpdate.h"
#include <StreamString.h> #include <StreamString.h>
#if SOC_WIFI_SUPPORTED
#include "WiFi.h"
#endif
#include <esp_partition.h> #include <esp_partition.h>
#include <esp_ota_ops.h> // get running partition #include <esp_ota_ops.h> // get running partition
@ -51,7 +54,7 @@ HTTPUpdate::~HTTPUpdate(void)
{ {
} }
HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& url, const String& currentVersion, HTTPUpdateRequestCB requestCB) HTTPUpdateResult HTTPUpdate::update(NetworkClient& client, const String& url, const String& currentVersion, HTTPUpdateRequestCB requestCB)
{ {
HTTPClient http; HTTPClient http;
if(!http.begin(client, url)) if(!http.begin(client, url))
@ -66,7 +69,7 @@ HTTPUpdateResult HTTPUpdate::updateSpiffs(HTTPClient& httpClient, const String&
return handleUpdate(httpClient, currentVersion, true, requestCB); return handleUpdate(httpClient, currentVersion, true, requestCB);
} }
HTTPUpdateResult HTTPUpdate::updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion, HTTPUpdateRequestCB requestCB) HTTPUpdateResult HTTPUpdate::updateSpiffs(NetworkClient& client, const String& url, const String& currentVersion, HTTPUpdateRequestCB requestCB)
{ {
HTTPClient http; HTTPClient http;
if(!http.begin(client, url)) if(!http.begin(client, url))
@ -82,7 +85,7 @@ HTTPUpdateResult HTTPUpdate::update(HTTPClient& httpClient,
return handleUpdate(httpClient, currentVersion, false, requestCB); return handleUpdate(httpClient, currentVersion, false, requestCB);
} }
HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& host, uint16_t port, const String& uri, HTTPUpdateResult HTTPUpdate::update(NetworkClient& client, const String& host, uint16_t port, const String& uri,
const String& currentVersion, HTTPUpdateRequestCB requestCB) const String& currentVersion, HTTPUpdateRequestCB requestCB)
{ {
HTTPClient http; HTTPClient http;
@ -194,8 +197,11 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient& http, const String& curren
http.setFollowRedirects(_followRedirects); http.setFollowRedirects(_followRedirects);
http.setUserAgent("ESP32-http-Update"); http.setUserAgent("ESP32-http-Update");
http.addHeader("Cache-Control", "no-cache"); http.addHeader("Cache-Control", "no-cache");
http.addHeader("x-ESP32-BASE-MAC", Network.macAddress());
#if SOC_WIFI_SUPPORTED
http.addHeader("x-ESP32-STA-MAC", WiFi.macAddress()); http.addHeader("x-ESP32-STA-MAC", WiFi.macAddress());
http.addHeader("x-ESP32-AP-MAC", WiFi.softAPmacAddress()); http.addHeader("x-ESP32-AP-MAC", WiFi.softAPmacAddress());
#endif
http.addHeader("x-ESP32-free-space", String(ESP.getFreeSketchSpace())); http.addHeader("x-ESP32-free-space", String(ESP.getFreeSketchSpace()));
http.addHeader("x-ESP32-sketch-size", String(ESP.getSketchSize())); http.addHeader("x-ESP32-sketch-size", String(ESP.getSketchSize()));
String sketchMD5 = ESP.getSketchMD5(); String sketchMD5 = ESP.getSketchMD5();
@ -309,10 +315,10 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient& http, const String& curren
_cbStart(); _cbStart();
} }
WiFiClient * tcp = http.getStreamPtr(); NetworkClient * tcp = http.getStreamPtr();
// To do? WiFiUDP::stopAll(); // To do? NetworkUDP::stopAll();
// To do? WiFiClient::stopAllExcept(tcp); // To do? NetworkClient::stopAllExcept(tcp);
delay(100); delay(100);

View file

@ -27,9 +27,7 @@
#define ___HTTP_UPDATE_H___ #define ___HTTP_UPDATE_H___
#include <Arduino.h> #include <Arduino.h>
#include <WiFi.h> #include <Network.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <HTTPClient.h> #include <HTTPClient.h>
#include <Update.h> #include <Update.h>
@ -101,12 +99,12 @@ public:
_auth = auth; _auth = auth;
} }
t_httpUpdate_return update(WiFiClient& client, const String& url, const String& currentVersion = "", HTTPUpdateRequestCB requestCB = NULL); t_httpUpdate_return update(NetworkClient& client, const String& url, const String& currentVersion = "", HTTPUpdateRequestCB requestCB = NULL);
t_httpUpdate_return update(WiFiClient& client, const String& host, uint16_t port, const String& uri = "/", t_httpUpdate_return update(NetworkClient& client, const String& host, uint16_t port, const String& uri = "/",
const String& currentVersion = "", HTTPUpdateRequestCB requestCB = NULL); const String& currentVersion = "", HTTPUpdateRequestCB requestCB = NULL);
t_httpUpdate_return updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion = "", HTTPUpdateRequestCB requestCB = NULL); t_httpUpdate_return updateSpiffs(NetworkClient& client, const String& url, const String& currentVersion = "", HTTPUpdateRequestCB requestCB = NULL);
t_httpUpdate_return update(HTTPClient& httpClient, t_httpUpdate_return update(HTTPClient& httpClient,
const String& currentVersion = "", const String& currentVersion = "",

View file

@ -3,7 +3,7 @@
*/ */
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WebServer.h> #include <WebServer.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>
#include <HTTPUpdateServer.h> #include <HTTPUpdateServer.h>

View file

@ -1,5 +1,4 @@
#include "NetBIOS.h" #include "NetBIOS.h"
#include <functional> #include <functional>
#define NBNS_PORT 137 #define NBNS_PORT 137
@ -92,7 +91,7 @@ void NetBIOS::_onPacket(AsyncUDPPacket& packet){
append_32((void *)&nbnsa.ttl, 300000); append_32((void *)&nbnsa.ttl, 300000);
append_16((void *)&nbnsa.data_len, 6); append_16((void *)&nbnsa.data_len, 6);
append_16((void *)&nbnsa.flags, 0); append_16((void *)&nbnsa.flags, 0);
nbnsa.addr = WiFi.localIP(); nbnsa.addr = packet.localIP();
_udp.writeTo((uint8_t *)&nbnsa, sizeof(nbnsa), packet.remoteIP(), NBNS_PORT); _udp.writeTo((uint8_t *)&nbnsa, sizeof(nbnsa), packet.remoteIP(), NBNS_PORT);
} }
} }
@ -102,6 +101,7 @@ void NetBIOS::_onPacket(AsyncUDPPacket& packet){
NetBIOS::NetBIOS(){ NetBIOS::NetBIOS(){
} }
NetBIOS::~NetBIOS(){ NetBIOS::~NetBIOS(){
end(); end();
} }

View file

@ -2,7 +2,7 @@
#ifndef __ESPNBNS_h__ #ifndef __ESPNBNS_h__
#define __ESPNBNS_h__ #define __ESPNBNS_h__
#include <WiFi.h> #include "Arduino.h"
#include "AsyncUDP.h" #include "AsyncUDP.h"
class NetBIOS class NetBIOS

View file

@ -0,0 +1,9 @@
name=Networking
version=1.0.0
author=Hristo Gochkov
maintainer=Hristo Gochkov <hristo@espressif.com>
sentence=General network management library.
paragraph=This library holds all common functionality of the different network interfaces.
category=Communication
url=
architectures=esp32

View file

@ -0,0 +1,14 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "NetworkInterface.h"
#include "NetworkEvents.h"
#include "NetworkManager.h"
#include "NetworkClient.h"
#include "NetworkServer.h"
#include "NetworkUdp.h"

View file

@ -17,8 +17,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "WiFiClient.h" #include "NetworkClient.h"
#include "WiFi.h" #include "NetworkManager.h"
#include <lwip/sockets.h> #include <lwip/sockets.h>
#include <lwip/netdb.h> #include <lwip/netdb.h>
#include <errno.h> #include <errno.h>
@ -37,7 +37,7 @@
#undef write #undef write
#undef read #undef read
class WiFiClientRxBuffer { class NetworkClientRxBuffer {
private: private:
size_t _size; size_t _size;
uint8_t *_buffer; uint8_t *_buffer;
@ -93,7 +93,7 @@ private:
} }
public: public:
WiFiClientRxBuffer(int fd, size_t size=1436) NetworkClientRxBuffer(int fd, size_t size=1436)
:_size(size) :_size(size)
,_buffer(NULL) ,_buffer(NULL)
,_pos(0) ,_pos(0)
@ -104,7 +104,7 @@ public:
//_buffer = (uint8_t *)malloc(_size); //_buffer = (uint8_t *)malloc(_size);
} }
~WiFiClientRxBuffer() ~NetworkClientRxBuffer()
{ {
free(_buffer); free(_buffer);
} }
@ -167,16 +167,16 @@ public:
} }
}; };
class WiFiClientSocketHandle { class NetworkClientSocketHandle {
private: private:
int sockfd; int sockfd;
public: public:
WiFiClientSocketHandle(int fd):sockfd(fd) NetworkClientSocketHandle(int fd):sockfd(fd)
{ {
} }
~WiFiClientSocketHandle() ~NetworkClientSocketHandle()
{ {
close(sockfd); close(sockfd);
} }
@ -187,22 +187,22 @@ public:
} }
}; };
WiFiClient::WiFiClient():_rxBuffer(nullptr),_connected(false),_sse(false),_timeout(WIFI_CLIENT_DEF_CONN_TIMEOUT_MS),next(NULL) NetworkClient::NetworkClient():_rxBuffer(nullptr),_connected(false),_sse(false),_timeout(WIFI_CLIENT_DEF_CONN_TIMEOUT_MS),next(NULL)
{ {
} }
WiFiClient::WiFiClient(int fd):_connected(true),_timeout(WIFI_CLIENT_DEF_CONN_TIMEOUT_MS),next(NULL) NetworkClient::NetworkClient(int fd):_connected(true),_timeout(WIFI_CLIENT_DEF_CONN_TIMEOUT_MS),next(NULL)
{ {
clientSocketHandle.reset(new WiFiClientSocketHandle(fd)); clientSocketHandle.reset(new NetworkClientSocketHandle(fd));
_rxBuffer.reset(new WiFiClientRxBuffer(fd)); _rxBuffer.reset(new NetworkClientRxBuffer(fd));
} }
WiFiClient::~WiFiClient() NetworkClient::~NetworkClient()
{ {
stop(); stop();
} }
void WiFiClient::stop() void NetworkClient::stop()
{ {
clientSocketHandle = NULL; clientSocketHandle = NULL;
_rxBuffer = NULL; _rxBuffer = NULL;
@ -211,12 +211,12 @@ void WiFiClient::stop()
_lastWriteTimeout = 0; _lastWriteTimeout = 0;
} }
int WiFiClient::connect(IPAddress ip, uint16_t port) int NetworkClient::connect(IPAddress ip, uint16_t port)
{ {
return connect(ip,port,_timeout); return connect(ip,port,_timeout);
} }
int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout_ms) int NetworkClient::connect(IPAddress ip, uint16_t port, int32_t timeout_ms)
{ {
struct sockaddr_storage serveraddr = {}; struct sockaddr_storage serveraddr = {};
_timeout = timeout_ms; _timeout = timeout_ms;
@ -291,38 +291,38 @@ int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout_ms)
ROE_WIFICLIENT(setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)),"SO_SNDTIMEO"); ROE_WIFICLIENT(setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)),"SO_SNDTIMEO");
ROE_WIFICLIENT(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)),"SO_RCVTIMEO"); ROE_WIFICLIENT(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)),"SO_RCVTIMEO");
// These are also set in WiFiClientSecure, should be set here too? // These are also set in NetworkClientSecure, should be set here too?
//ROE_WIFICLIENT(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)),"TCP_NODELAY"); //ROE_WIFICLIENT(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)),"TCP_NODELAY");
//ROE_WIFICLIENT (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)),"SO_KEEPALIVE"); //ROE_WIFICLIENT (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)),"SO_KEEPALIVE");
fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFL, 0 ) & (~O_NONBLOCK) ); fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFL, 0 ) & (~O_NONBLOCK) );
clientSocketHandle.reset(new WiFiClientSocketHandle(sockfd)); clientSocketHandle.reset(new NetworkClientSocketHandle(sockfd));
_rxBuffer.reset(new WiFiClientRxBuffer(sockfd)); _rxBuffer.reset(new NetworkClientRxBuffer(sockfd));
_connected = true; _connected = true;
return 1; return 1;
} }
int WiFiClient::connect(const char *host, uint16_t port) int NetworkClient::connect(const char *host, uint16_t port)
{ {
return connect(host,port,_timeout); return connect(host,port,_timeout);
} }
int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout_ms) int NetworkClient::connect(const char *host, uint16_t port, int32_t timeout_ms)
{ {
IPAddress srv((uint32_t)0); IPAddress srv((uint32_t)0);
if(!WiFiGenericClass::hostByName(host, srv)){ if(!Network.hostByName(host, srv)){
return 0; return 0;
} }
return connect(srv, port, timeout_ms); return connect(srv, port, timeout_ms);
} }
int WiFiClient::setSocketOption(int option, char* value, size_t len) int NetworkClient::setSocketOption(int option, char* value, size_t len)
{ {
return setSocketOption(SOL_SOCKET, option, (const void*)value, len); return setSocketOption(SOL_SOCKET, option, (const void*)value, len);
} }
int WiFiClient::setSocketOption(int level, int option, const void* value, size_t len) int NetworkClient::setSocketOption(int level, int option, const void* value, size_t len)
{ {
int res = setsockopt(fd(), level, option, value, len); int res = setsockopt(fd(), level, option, value, len);
if(res < 0) { if(res < 0) {
@ -331,7 +331,7 @@ int WiFiClient::setSocketOption(int level, int option, const void* value, size_t
return res; return res;
} }
int WiFiClient::getSocketOption(int level, int option, const void* value, size_t size) int NetworkClient::getSocketOption(int level, int option, const void* value, size_t size)
{ {
int res = getsockopt(fd(), level, option, (char *)value, (socklen_t*)&size); int res = getsockopt(fd(), level, option, (char *)value, (socklen_t*)&size);
if(res < 0) { if(res < 0) {
@ -340,12 +340,12 @@ int WiFiClient::getSocketOption(int level, int option, const void* value, size_t
return res; return res;
} }
int WiFiClient::setOption(int option, int *value) int NetworkClient::setOption(int option, int *value)
{ {
return setSocketOption(IPPROTO_TCP, option, (const void*)value, sizeof(int)); return setSocketOption(IPPROTO_TCP, option, (const void*)value, sizeof(int));
} }
int WiFiClient::getOption(int option, int *value) int NetworkClient::getOption(int option, int *value)
{ {
socklen_t size = sizeof(int); socklen_t size = sizeof(int);
int res = getsockopt(fd(), IPPROTO_TCP, option, (char *)value, &size); int res = getsockopt(fd(), IPPROTO_TCP, option, (char *)value, &size);
@ -355,30 +355,30 @@ int WiFiClient::getOption(int option, int *value)
return res; return res;
} }
void WiFiClient::setConnectionTimeout(uint32_t milliseconds) void NetworkClient::setConnectionTimeout(uint32_t milliseconds)
{ {
_timeout = milliseconds; _timeout = milliseconds;
} }
int WiFiClient::setNoDelay(bool nodelay) int NetworkClient::setNoDelay(bool nodelay)
{ {
int flag = nodelay; int flag = nodelay;
return setOption(TCP_NODELAY, &flag); return setOption(TCP_NODELAY, &flag);
} }
bool WiFiClient::getNoDelay() bool NetworkClient::getNoDelay()
{ {
int flag = 0; int flag = 0;
getOption(TCP_NODELAY, &flag); getOption(TCP_NODELAY, &flag);
return flag; return flag;
} }
size_t WiFiClient::write(uint8_t data) size_t NetworkClient::write(uint8_t data)
{ {
return write(&data, 1); return write(&data, 1);
} }
int WiFiClient::read() int NetworkClient::read()
{ {
uint8_t data = 0; uint8_t data = 0;
int res = read(&data, 1); int res = read(&data, 1);
@ -391,7 +391,7 @@ int WiFiClient::read()
return data; return data;
} }
size_t WiFiClient::write(const uint8_t *buf, size_t size) size_t NetworkClient::write(const uint8_t *buf, size_t size)
{ {
int res =0; int res =0;
int retry = WIFI_CLIENT_MAX_WRITE_RETRY; int retry = WIFI_CLIENT_MAX_WRITE_RETRY;
@ -459,12 +459,12 @@ size_t WiFiClient::write(const uint8_t *buf, size_t size)
return totalBytesSent; return totalBytesSent;
} }
size_t WiFiClient::write_P(PGM_P buf, size_t size) size_t NetworkClient::write_P(PGM_P buf, size_t size)
{ {
return write(buf, size); return write(buf, size);
} }
size_t WiFiClient::write(Stream &stream) size_t NetworkClient::write(Stream &stream)
{ {
uint8_t * buf = (uint8_t *)malloc(1360); uint8_t * buf = (uint8_t *)malloc(1360);
if(!buf){ if(!buf){
@ -482,7 +482,7 @@ size_t WiFiClient::write(Stream &stream)
return written; return written;
} }
int WiFiClient::read(uint8_t *buf, size_t size) int NetworkClient::read(uint8_t *buf, size_t size)
{ {
if(_lastReadTimeout != _timeout){ if(_lastReadTimeout != _timeout){
if(fd() >= 0){ if(fd() >= 0){
@ -507,7 +507,7 @@ int WiFiClient::read(uint8_t *buf, size_t size)
return res; return res;
} }
int WiFiClient::peek() int NetworkClient::peek()
{ {
int res = -1; int res = -1;
if (_rxBuffer) { if (_rxBuffer) {
@ -520,7 +520,7 @@ int WiFiClient::peek()
return res; return res;
} }
int WiFiClient::available() int NetworkClient::available()
{ {
if(!_rxBuffer) if(!_rxBuffer)
{ {
@ -536,13 +536,13 @@ int WiFiClient::available()
// Though flushing means to send all pending data, // Though flushing means to send all pending data,
// seems that in Arduino it also means to clear RX // seems that in Arduino it also means to clear RX
void WiFiClient::flush() { void NetworkClient::flush() {
if (_rxBuffer != nullptr) { if (_rxBuffer != nullptr) {
_rxBuffer->flush(); _rxBuffer->flush();
} }
} }
uint8_t WiFiClient::connected() uint8_t NetworkClient::connected()
{ {
if (_connected) { if (_connected) {
uint8_t dummy; uint8_t dummy;
@ -576,7 +576,7 @@ uint8_t WiFiClient::connected()
return _connected; return _connected;
} }
IPAddress WiFiClient::remoteIP(int fd) const IPAddress NetworkClient::remoteIP(int fd) const
{ {
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t len = sizeof addr; socklen_t len = sizeof addr;
@ -597,11 +597,11 @@ IPAddress WiFiClient::remoteIP(int fd) const
return IPAddress(IPv6, (uint8_t*)(saddr6->sin6_addr.s6_addr), saddr6->sin6_scope_id); return IPAddress(IPv6, (uint8_t*)(saddr6->sin6_addr.s6_addr), saddr6->sin6_scope_id);
} }
} }
log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?"); log_e("NetworkClient::remoteIP Not AF_INET or AF_INET6?");
return (IPAddress(0,0,0,0)); return (IPAddress(0,0,0,0));
} }
uint16_t WiFiClient::remotePort(int fd) const uint16_t NetworkClient::remotePort(int fd) const
{ {
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t len = sizeof addr; socklen_t len = sizeof addr;
@ -610,17 +610,17 @@ uint16_t WiFiClient::remotePort(int fd) const
return ntohs(s->sin_port); return ntohs(s->sin_port);
} }
IPAddress WiFiClient::remoteIP() const IPAddress NetworkClient::remoteIP() const
{ {
return remoteIP(fd()); return remoteIP(fd());
} }
uint16_t WiFiClient::remotePort() const uint16_t NetworkClient::remotePort() const
{ {
return remotePort(fd()); return remotePort(fd());
} }
IPAddress WiFiClient::localIP(int fd) const IPAddress NetworkClient::localIP(int fd) const
{ {
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t len = sizeof addr; socklen_t len = sizeof addr;
@ -629,7 +629,7 @@ IPAddress WiFiClient::localIP(int fd) const
return IPAddress((uint32_t)(s->sin_addr.s_addr)); return IPAddress((uint32_t)(s->sin_addr.s_addr));
} }
uint16_t WiFiClient::localPort(int fd) const uint16_t NetworkClient::localPort(int fd) const
{ {
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t len = sizeof addr; socklen_t len = sizeof addr;
@ -638,22 +638,22 @@ uint16_t WiFiClient::localPort(int fd) const
return ntohs(s->sin_port); return ntohs(s->sin_port);
} }
IPAddress WiFiClient::localIP() const IPAddress NetworkClient::localIP() const
{ {
return localIP(fd()); return localIP(fd());
} }
uint16_t WiFiClient::localPort() const uint16_t NetworkClient::localPort() const
{ {
return localPort(fd()); return localPort(fd());
} }
bool WiFiClient::operator==(const WiFiClient& rhs) bool NetworkClient::operator==(const NetworkClient& rhs)
{ {
return clientSocketHandle == rhs.clientSocketHandle && remotePort() == rhs.remotePort() && remoteIP() == rhs.remoteIP(); return clientSocketHandle == rhs.clientSocketHandle && remotePort() == rhs.remotePort() && remoteIP() == rhs.remoteIP();
} }
int WiFiClient::fd() const int NetworkClient::fd() const
{ {
if (clientSocketHandle == NULL) { if (clientSocketHandle == NULL) {
return -1; return -1;
@ -662,12 +662,12 @@ int WiFiClient::fd() const
} }
} }
void WiFiClient::setSSE(bool sse) void NetworkClient::setSSE(bool sse)
{ {
_sse = sse; _sse = sse;
} }
bool WiFiClient::isSSE() bool NetworkClient::isSSE()
{ {
return _sse; return _sse;
} }

View file

@ -0,0 +1,113 @@
/*
Client.h - Base class that provides Client
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "Arduino.h"
#include "Client.h"
#include <memory>
class NetworkClientSocketHandle;
class NetworkClientRxBuffer;
class ESPLwIPClient : public Client
{
public:
virtual int connect(IPAddress ip, uint16_t port, int32_t timeout) = 0;
virtual int connect(const char *host, uint16_t port, int32_t timeout) = 0;
virtual void setConnectionTimeout(uint32_t milliseconds) = 0;
};
class NetworkClient : public ESPLwIPClient
{
protected:
std::shared_ptr<NetworkClientSocketHandle> clientSocketHandle;
std::shared_ptr<NetworkClientRxBuffer> _rxBuffer;
bool _connected;
bool _sse;
int _timeout;
int _lastWriteTimeout;
int _lastReadTimeout;
public:
NetworkClient *next;
NetworkClient();
NetworkClient(int fd);
~NetworkClient();
int connect(IPAddress ip, uint16_t port);
int connect(IPAddress ip, uint16_t port, int32_t timeout_ms);
int connect(const char *host, uint16_t port);
int connect(const char *host, uint16_t port, int32_t timeout_ms);
size_t write(uint8_t data);
size_t write(const uint8_t *buf, size_t size);
size_t write_P(PGM_P buf, size_t size);
size_t write(Stream &stream);
int available();
int read();
int read(uint8_t *buf, size_t size);
int peek();
void flush();
void stop();
uint8_t connected();
void setSSE(bool sse);
bool isSSE();
operator bool()
{
return connected();
}
bool operator==(const bool value)
{
return bool() == value;
}
bool operator!=(const bool value)
{
return bool() != value;
}
bool operator==(const NetworkClient&);
bool operator!=(const NetworkClient& rhs)
{
return !this->operator==(rhs);
};
virtual int fd() const;
int setSocketOption(int option, char* value, size_t len);
int setSocketOption(int level, int option, const void* value, size_t len);
int getSocketOption(int level, int option, const void* value, size_t size);
int setOption(int option, int *value);
int getOption(int option, int *value);
void setConnectionTimeout(uint32_t milliseconds);
int setNoDelay(bool nodelay);
bool getNoDelay();
IPAddress remoteIP() const;
IPAddress remoteIP(int fd) const;
uint16_t remotePort() const;
uint16_t remotePort(int fd) const;
IPAddress localIP() const;
IPAddress localIP(int fd) const;
uint16_t localPort() const;
uint16_t localPort(int fd) const;
//friend class NetworkServer;
using Print::write;
};

View file

@ -0,0 +1,383 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "NetworkEvents.h"
#include "NetworkManager.h"
#include "esp_task.h"
#include "esp32-hal.h"
typedef struct NetworkEventCbList {
static network_event_handle_t current_id;
network_event_handle_t id;
NetworkEventCb cb;
NetworkEventFuncCb fcb;
NetworkEventSysCb scb;
arduino_event_id_t event;
NetworkEventCbList() : id(current_id++), cb(NULL), fcb(NULL), scb(NULL), event(ARDUINO_EVENT_NONE) {}
} NetworkEventCbList_t;
network_event_handle_t NetworkEventCbList::current_id = 1;
// arduino dont like std::vectors move static here
static std::vector<NetworkEventCbList_t> cbEventList;
static void _network_event_task(void * arg){
for (;;) {
((NetworkEvents*)arg)->checkForEvent();
}
vTaskDelete(NULL);
}
NetworkEvents::NetworkEvents()
: _arduino_event_group(NULL)
, _arduino_event_queue(NULL)
, _arduino_event_task_handle(NULL)
{}
NetworkEvents::~NetworkEvents(){
if(_arduino_event_task_handle != NULL){
vTaskDelete(_arduino_event_task_handle);
_arduino_event_task_handle = NULL;
}
if(_arduino_event_group != NULL){
vEventGroupDelete(_arduino_event_group);
_arduino_event_group = NULL;
}
if(_arduino_event_queue != NULL){
arduino_event_t *event = NULL;
while(xQueueReceive(_arduino_event_queue, &event, 0) == pdTRUE){
free(event);
}
vQueueDelete(_arduino_event_queue);
_arduino_event_queue = NULL;
}
}
static uint32_t _initial_bits = NET_DNS_IDLE_BIT;
bool NetworkEvents::initNetworkEvents(){
if(!_arduino_event_group){
_arduino_event_group = xEventGroupCreate();
if(!_arduino_event_group){
log_e("Network Event Group Create Failed!");
return false;
}
xEventGroupSetBits(_arduino_event_group, _initial_bits);
}
if(!_arduino_event_queue){
_arduino_event_queue = xQueueCreate(32, sizeof(arduino_event_t*));
if(!_arduino_event_queue){
log_e("Network Event Queue Create Failed!");
return false;
}
}
esp_err_t err = esp_event_loop_create_default();
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
log_e("esp_event_loop_create_default failed!");
return err;
}
if(!_arduino_event_task_handle){
xTaskCreateUniversal(_network_event_task, "arduino_events", 4096, this, ESP_TASKD_EVENT_PRIO - 1, &_arduino_event_task_handle, ARDUINO_EVENT_RUNNING_CORE);
if(!_arduino_event_task_handle){
log_e("Network Event Task Start Failed!");
return false;
}
}
return true;
}
bool NetworkEvents::postEvent(arduino_event_t *data)
{
if(data == NULL || _arduino_event_queue == NULL){
return false;
}
arduino_event_t * event = (arduino_event_t*)malloc(sizeof(arduino_event_t));
if(event == NULL){
log_e("Arduino Event Malloc Failed!");
return false;
}
memcpy(event, data, sizeof(arduino_event_t));
if (xQueueSend(_arduino_event_queue, &event, portMAX_DELAY) != pdPASS) {
log_e("Arduino Event Send Failed!");
return false;
}
return true;
}
void NetworkEvents::checkForEvent()
{
arduino_event_t *event = NULL;
if(_arduino_event_queue == NULL){
return;
}
if(xQueueReceive(_arduino_event_queue, &event, portMAX_DELAY) != pdTRUE){
return;
}
if(event == NULL){
return;
}
log_v("Network Event: %d - %s", event->event_id, eventName(event->event_id));
for(uint32_t i = 0; i < cbEventList.size(); i++) {
NetworkEventCbList_t entry = cbEventList[i];
if(entry.cb || entry.fcb || entry.scb) {
if(entry.event == (arduino_event_id_t) event->event_id || entry.event == ARDUINO_EVENT_MAX) {
if(entry.cb) {
entry.cb((arduino_event_id_t) event->event_id);
} else if(entry.fcb) {
entry.fcb((arduino_event_id_t) event->event_id, (arduino_event_info_t) event->event_info);
} else {
entry.scb(event);
}
}
}
}
free(event);
}
network_event_handle_t NetworkEvents::onEvent(NetworkEventCb cbEvent, arduino_event_id_t event)
{
if(!cbEvent) {
return 0;
}
NetworkEventCbList_t newEventHandler;
newEventHandler.cb = cbEvent;
newEventHandler.fcb = NULL;
newEventHandler.scb = NULL;
newEventHandler.event = event;
cbEventList.push_back(newEventHandler);
return newEventHandler.id;
}
network_event_handle_t NetworkEvents::onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event)
{
if(!cbEvent) {
return 0;
}
NetworkEventCbList_t newEventHandler;
newEventHandler.cb = NULL;
newEventHandler.fcb = cbEvent;
newEventHandler.scb = NULL;
newEventHandler.event = event;
cbEventList.push_back(newEventHandler);
return newEventHandler.id;
}
network_event_handle_t NetworkEvents::onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event)
{
if(!cbEvent) {
return 0;
}
NetworkEventCbList_t newEventHandler;
newEventHandler.cb = NULL;
newEventHandler.fcb = NULL;
newEventHandler.scb = cbEvent;
newEventHandler.event = event;
cbEventList.push_back(newEventHandler);
return newEventHandler.id;
}
network_event_handle_t NetworkEvents::onSysEvent(NetworkEventCb cbEvent, arduino_event_id_t event)
{
if(!cbEvent) {
return 0;
}
NetworkEventCbList_t newEventHandler;
newEventHandler.cb = cbEvent;
newEventHandler.fcb = NULL;
newEventHandler.scb = NULL;
newEventHandler.event = event;
cbEventList.insert(cbEventList.begin(), newEventHandler);
return newEventHandler.id;
}
network_event_handle_t NetworkEvents::onSysEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event)
{
if(!cbEvent) {
return 0;
}
NetworkEventCbList_t newEventHandler;
newEventHandler.cb = NULL;
newEventHandler.fcb = cbEvent;
newEventHandler.scb = NULL;
newEventHandler.event = event;
cbEventList.insert(cbEventList.begin(), newEventHandler);
return newEventHandler.id;
}
network_event_handle_t NetworkEvents::onSysEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event)
{
if(!cbEvent) {
return 0;
}
NetworkEventCbList_t newEventHandler;
newEventHandler.cb = NULL;
newEventHandler.fcb = NULL;
newEventHandler.scb = cbEvent;
newEventHandler.event = event;
cbEventList.insert(cbEventList.begin(), newEventHandler);
return newEventHandler.id;
}
void NetworkEvents::removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event)
{
if(!cbEvent) {
return;
}
for(uint32_t i = 0; i < cbEventList.size(); i++) {
NetworkEventCbList_t entry = cbEventList[i];
if(entry.cb == cbEvent && entry.event == event) {
cbEventList.erase(cbEventList.begin() + i);
}
}
}
template<typename T, typename... U>
static size_t getStdFunctionAddress(std::function<T(U...)> f) {
typedef T(fnType)(U...);
fnType ** fnPointer = f.template target<fnType*>();
return (size_t) *fnPointer;
}
void NetworkEvents::removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event)
{
if(!cbEvent) {
return;
}
for(uint32_t i = 0; i < cbEventList.size(); i++) {
NetworkEventCbList_t entry = cbEventList[i];
if(getStdFunctionAddress(entry.fcb) == getStdFunctionAddress(cbEvent) && entry.event == event) {
cbEventList.erase(cbEventList.begin() + i);
}
}
}
void NetworkEvents::removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event)
{
if(!cbEvent) {
return;
}
for(uint32_t i = 0; i < cbEventList.size(); i++) {
NetworkEventCbList_t entry = cbEventList[i];
if(entry.scb == cbEvent && entry.event == event) {
cbEventList.erase(cbEventList.begin() + i);
}
}
}
void NetworkEvents::removeEvent(network_event_handle_t id)
{
for(uint32_t i = 0; i < cbEventList.size(); i++) {
NetworkEventCbList_t entry = cbEventList[i];
if(entry.id == id) {
cbEventList.erase(cbEventList.begin() + i);
}
}
}
int NetworkEvents::setStatusBits(int bits){
if(!_arduino_event_group){
_initial_bits |= bits;
return _initial_bits;
}
return xEventGroupSetBits(_arduino_event_group, bits);
}
int NetworkEvents::clearStatusBits(int bits){
if(!_arduino_event_group){
_initial_bits &= ~bits;
return _initial_bits;
}
return xEventGroupClearBits(_arduino_event_group, bits);
}
int NetworkEvents::getStatusBits(){
if(!_arduino_event_group){
return _initial_bits;
}
return xEventGroupGetBits(_arduino_event_group);
}
int NetworkEvents::waitStatusBits(int bits, uint32_t timeout_ms){
if(!_arduino_event_group){
return 0;
}
return xEventGroupWaitBits(
_arduino_event_group, // The event group being tested.
bits, // The bits within the event group to wait for.
pdFALSE, // bits should be cleared before returning.
pdTRUE, // Don't wait for all bits, any bit will do.
timeout_ms / portTICK_PERIOD_MS ) & bits; // Wait a maximum of timeout_ms for any bit to be set.
}
/**
* @brief Convert arduino_event_id_t to a C string.
* @param [in] id The event id to be converted.
* @return A string representation of the event id.
* @note: arduino_event_id_t values as of Mar 2023 (arduino-esp32 r2.0.7) are: 0-39 (ARDUINO_EVENT_MAX=40) and are defined in WiFiGeneric.h.
*/
const char * NetworkEvents::eventName(arduino_event_id_t id) {
switch(id) {
case ARDUINO_EVENT_ETH_START: return "ETH_START";
case ARDUINO_EVENT_ETH_STOP: return "ETH_STOP";
case ARDUINO_EVENT_ETH_CONNECTED: return "ETH_CONNECTED";
case ARDUINO_EVENT_ETH_DISCONNECTED: return "ETH_DISCONNECTED";
case ARDUINO_EVENT_ETH_GOT_IP: return "ETH_GOT_IP";
case ARDUINO_EVENT_ETH_LOST_IP: return "ETH_LOST_IP";
case ARDUINO_EVENT_ETH_GOT_IP6: return "ETH_GOT_IP6";
// case ARDUINO_EVENT_PPP_START: return "PPP_START";
// case ARDUINO_EVENT_PPP_STOP: return "PPP_STOP";
// case ARDUINO_EVENT_PPP_CONNECTED: return "PPP_CONNECTED";
// case ARDUINO_EVENT_PPP_DISCONNECTED: return "PPP_DISCONNECTED";
// case ARDUINO_EVENT_PPP_GOT_IP: return "PPP_GOT_IP";
// case ARDUINO_EVENT_PPP_LOST_IP: return "PPP_LOST_IP";
// case ARDUINO_EVENT_PPP_GOT_IP6: return "PPP_GOT_IP6";
#if SOC_WIFI_SUPPORTED
case ARDUINO_EVENT_WIFI_OFF: return "WIFI_OFF";
case ARDUINO_EVENT_WIFI_READY: return "WIFI_READY";
case ARDUINO_EVENT_WIFI_SCAN_DONE: return "SCAN_DONE";
case ARDUINO_EVENT_WIFI_STA_START: return "STA_START";
case ARDUINO_EVENT_WIFI_STA_STOP: return "STA_STOP";
case ARDUINO_EVENT_WIFI_STA_CONNECTED: return "STA_CONNECTED";
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: return "STA_DISCONNECTED";
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: return "STA_AUTHMODE_CHANGE";
case ARDUINO_EVENT_WIFI_STA_GOT_IP: return "STA_GOT_IP";
case ARDUINO_EVENT_WIFI_STA_GOT_IP6: return "STA_GOT_IP6";
case ARDUINO_EVENT_WIFI_STA_LOST_IP: return "STA_LOST_IP";
case ARDUINO_EVENT_WIFI_AP_START: return "AP_START";
case ARDUINO_EVENT_WIFI_AP_STOP: return "AP_STOP";
case ARDUINO_EVENT_WIFI_AP_STACONNECTED: return "AP_STACONNECTED";
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: return "AP_STADISCONNECTED";
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: return "AP_STAIPASSIGNED";
case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: return "AP_PROBEREQRECVED";
case ARDUINO_EVENT_WIFI_AP_GOT_IP6: return "AP_GOT_IP6";
case ARDUINO_EVENT_WIFI_FTM_REPORT: return "FTM_REPORT";
case ARDUINO_EVENT_WPS_ER_SUCCESS: return "WPS_ER_SUCCESS";
case ARDUINO_EVENT_WPS_ER_FAILED: return "WPS_ER_FAILED";
case ARDUINO_EVENT_WPS_ER_TIMEOUT: return "WPS_ER_TIMEOUT";
case ARDUINO_EVENT_WPS_ER_PIN: return "WPS_ER_PIN";
case ARDUINO_EVENT_WPS_ER_PBC_OVERLAP: return "WPS_ER_PBC_OVERLAP";
case ARDUINO_EVENT_SC_SCAN_DONE: return "SC_SCAN_DONE";
case ARDUINO_EVENT_SC_FOUND_CHANNEL: return "SC_FOUND_CHANNEL";
case ARDUINO_EVENT_SC_GOT_SSID_PSWD: return "SC_GOT_SSID_PSWD";
case ARDUINO_EVENT_SC_SEND_ACK_DONE: return "SC_SEND_ACK_DONE";
case ARDUINO_EVENT_PROV_INIT: return "PROV_INIT";
case ARDUINO_EVENT_PROV_DEINIT: return "PROV_DEINIT";
case ARDUINO_EVENT_PROV_START: return "PROV_START";
case ARDUINO_EVENT_PROV_END: return "PROV_END";
case ARDUINO_EVENT_PROV_CRED_RECV: return "PROV_CRED_RECV";
case ARDUINO_EVENT_PROV_CRED_FAIL: return "PROV_CRED_FAIL";
case ARDUINO_EVENT_PROV_CRED_SUCCESS: return "PROV_CRED_SUCCESS";
#endif
default: return "";
}
}

View file

@ -0,0 +1,169 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_netif_types.h"
#include "esp_eth_driver.h"
#include <functional>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#if SOC_WIFI_SUPPORTED
#include "esp_wifi_types.h"
#include "esp_smartconfig.h"
#include "wifi_provisioning/wifi_config.h"
#endif
#if SOC_WIFI_SUPPORTED
static const int WIFI_SCANNING_BIT = BIT0;
static const int WIFI_SCAN_DONE_BIT= BIT1;
#endif
static const int NET_DNS_IDLE_BIT = BIT2;
static const int NET_DNS_DONE_BIT = BIT3;
#define NET_HAS_IP6_GLOBAL_BIT 0
ESP_EVENT_DECLARE_BASE(ARDUINO_EVENTS);
typedef enum {
ARDUINO_EVENT_NONE,
ARDUINO_EVENT_ETH_START,
ARDUINO_EVENT_ETH_STOP,
ARDUINO_EVENT_ETH_CONNECTED,
ARDUINO_EVENT_ETH_DISCONNECTED,
ARDUINO_EVENT_ETH_GOT_IP,
ARDUINO_EVENT_ETH_LOST_IP,
ARDUINO_EVENT_ETH_GOT_IP6,
#if SOC_WIFI_SUPPORTED
ARDUINO_EVENT_WIFI_OFF,
ARDUINO_EVENT_WIFI_READY,
ARDUINO_EVENT_WIFI_SCAN_DONE,
ARDUINO_EVENT_WIFI_STA_START,
ARDUINO_EVENT_WIFI_STA_STOP,
ARDUINO_EVENT_WIFI_STA_CONNECTED,
ARDUINO_EVENT_WIFI_STA_DISCONNECTED,
ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE,
ARDUINO_EVENT_WIFI_STA_GOT_IP,
ARDUINO_EVENT_WIFI_STA_GOT_IP6,
ARDUINO_EVENT_WIFI_STA_LOST_IP,
ARDUINO_EVENT_WIFI_AP_START,
ARDUINO_EVENT_WIFI_AP_STOP,
ARDUINO_EVENT_WIFI_AP_STACONNECTED,
ARDUINO_EVENT_WIFI_AP_STADISCONNECTED,
ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED,
ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED,
ARDUINO_EVENT_WIFI_AP_GOT_IP6,
ARDUINO_EVENT_WIFI_FTM_REPORT,
ARDUINO_EVENT_WPS_ER_SUCCESS,
ARDUINO_EVENT_WPS_ER_FAILED,
ARDUINO_EVENT_WPS_ER_TIMEOUT,
ARDUINO_EVENT_WPS_ER_PIN,
ARDUINO_EVENT_WPS_ER_PBC_OVERLAP,
ARDUINO_EVENT_SC_SCAN_DONE,
ARDUINO_EVENT_SC_FOUND_CHANNEL,
ARDUINO_EVENT_SC_GOT_SSID_PSWD,
ARDUINO_EVENT_SC_SEND_ACK_DONE,
ARDUINO_EVENT_PROV_INIT,
ARDUINO_EVENT_PROV_DEINIT,
ARDUINO_EVENT_PROV_START,
ARDUINO_EVENT_PROV_END,
ARDUINO_EVENT_PROV_CRED_RECV,
ARDUINO_EVENT_PROV_CRED_FAIL,
ARDUINO_EVENT_PROV_CRED_SUCCESS,
#endif
// ARDUINO_EVENT_PPP_START,
// ARDUINO_EVENT_PPP_STOP,
// ARDUINO_EVENT_PPP_CONNECTED,
// ARDUINO_EVENT_PPP_DISCONNECTED,
// ARDUINO_EVENT_PPP_GOT_IP,
// ARDUINO_EVENT_PPP_LOST_IP,
// ARDUINO_EVENT_PPP_GOT_IP6,
ARDUINO_EVENT_MAX
} arduino_event_id_t;
typedef union {
ip_event_ap_staipassigned_t wifi_ap_staipassigned;
ip_event_got_ip_t got_ip;
ip_event_got_ip6_t got_ip6;
esp_eth_handle_t eth_connected;
#if SOC_WIFI_SUPPORTED
wifi_event_sta_scan_done_t wifi_scan_done;
wifi_event_sta_authmode_change_t wifi_sta_authmode_change;
wifi_event_sta_connected_t wifi_sta_connected;
wifi_event_sta_disconnected_t wifi_sta_disconnected;
wifi_event_sta_wps_er_pin_t wps_er_pin;
wifi_event_sta_wps_fail_reason_t wps_fail_reason;
wifi_event_ap_probe_req_rx_t wifi_ap_probereqrecved;
wifi_event_ap_staconnected_t wifi_ap_staconnected;
wifi_event_ap_stadisconnected_t wifi_ap_stadisconnected;
wifi_event_ftm_report_t wifi_ftm_report;
wifi_sta_config_t prov_cred_recv;
wifi_prov_sta_fail_reason_t prov_fail_reason;
smartconfig_event_got_ssid_pswd_t sc_got_ssid_pswd;
#endif
} arduino_event_info_t;
typedef struct{
arduino_event_id_t event_id;
arduino_event_info_t event_info;
} arduino_event_t;
typedef void (*NetworkEventCb)(arduino_event_id_t event);
typedef std::function<void(arduino_event_id_t event, arduino_event_info_t info)> NetworkEventFuncCb;
typedef void (*NetworkEventSysCb)(arduino_event_t *event);
typedef size_t network_event_handle_t;
class NetworkEvents {
public:
NetworkEvents();
~NetworkEvents();
network_event_handle_t onEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
network_event_handle_t onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
network_event_handle_t onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
void removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
void removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
void removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
void removeEvent(network_event_handle_t event_handle);
const char * eventName(arduino_event_id_t id);
void checkForEvent();
bool postEvent(arduino_event_t *event);
int getStatusBits();
int waitStatusBits(int bits, uint32_t timeout_ms);
int setStatusBits(int bits);
int clearStatusBits(int bits);
friend class ESP_NetworkInterface;
friend class ETHClass;
#if SOC_WIFI_SUPPORTED
friend class STAClass;
friend class APClass;
friend class WiFiGenericClass;
#endif
protected:
bool initNetworkEvents();
network_event_handle_t onSysEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
network_event_handle_t onSysEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
network_event_handle_t onSysEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
private:
EventGroupHandle_t _arduino_event_group;
QueueHandle_t _arduino_event_queue;
TaskHandle_t _arduino_event_task_handle;
};

View file

@ -0,0 +1,718 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "NetworkInterface.h"
#include "esp_netif.h"
#include "esp_netif_defaults.h"
#include "esp_system.h"
#include "lwip/ip_addr.h"
#include "lwip/err.h"
#include "lwip/netif.h"
#include "dhcpserver/dhcpserver.h"
#include "dhcpserver/dhcpserver_options.h"
#include "esp32-hal-log.h"
static NetworkInterface * _interfaces[ESP_NETIF_ID_MAX] = { NULL, NULL, NULL, NULL, NULL, NULL};
static esp_event_handler_instance_t _ip_ev_instance = NULL;
static NetworkInterface * getNetifByEspNetif(esp_netif_t *esp_netif){
for (int i = 0; i < ESP_NETIF_ID_MAX; ++i){
if(_interfaces[i] != NULL && _interfaces[i]->netif() == esp_netif){
return _interfaces[i];
}
}
return NULL;
}
NetworkInterface * getNetifByID(Network_Interface_ID id){
if(id < ESP_NETIF_ID_MAX){
return _interfaces[id];
}
return NULL;
}
static void _ip_event_cb(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
if (event_base == IP_EVENT){
NetworkInterface * netif = NULL;
if(event_id == IP_EVENT_STA_GOT_IP || event_id == IP_EVENT_ETH_GOT_IP || event_id == IP_EVENT_PPP_GOT_IP){
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
netif = getNetifByEspNetif(event->esp_netif);
} else if(event_id == IP_EVENT_STA_LOST_IP || event_id == IP_EVENT_PPP_LOST_IP || event_id == IP_EVENT_ETH_LOST_IP){
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
netif = getNetifByEspNetif(event->esp_netif);
} else if(event_id == IP_EVENT_GOT_IP6){
ip_event_got_ip6_t* event = (ip_event_got_ip6_t*) event_data;
netif = getNetifByEspNetif(event->esp_netif);
} else if(event_id == IP_EVENT_AP_STAIPASSIGNED){
ip_event_ap_staipassigned_t* event = (ip_event_ap_staipassigned_t*) event_data;
netif = getNetifByEspNetif(event->esp_netif);
}
if(netif != NULL){
netif->_onIpEvent(event_id, event_data);
}
}
}
void NetworkInterface::_onIpEvent(int32_t event_id, void* event_data){
arduino_event_t arduino_event;
arduino_event.event_id = ARDUINO_EVENT_MAX;
if(event_id == _got_ip_event_id){
setStatusBits(ESP_NETIF_HAS_IP_BIT);
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
log_v("%s Got %sIP: " IPSTR " MASK: " IPSTR " GW: " IPSTR, desc(), event->ip_changed?"New ":"Same ", IP2STR(&event->ip_info.ip), IP2STR(&event->ip_info.netmask), IP2STR(&event->ip_info.gw));
#endif
memcpy(&arduino_event.event_info.got_ip, event_data, sizeof(ip_event_got_ip_t));
#if SOC_WIFI_SUPPORTED
if(_interface_id == ESP_NETIF_ID_STA){
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_GOT_IP;
} else
#endif
// if(_interface_id == ESP_NETIF_ID_PPP){
// arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP;
// } else
if(_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX){
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP;
}
} else if(event_id == _lost_ip_event_id){
clearStatusBits(ESP_NETIF_HAS_IP_BIT);
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
log_v("%s Lost IP", desc());
#endif
#if SOC_WIFI_SUPPORTED
if(_interface_id == ESP_NETIF_ID_STA){
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_LOST_IP;
} else
#endif
// if(_interface_id == ESP_NETIF_ID_PPP){
// arduino_event.event_id = ARDUINO_EVENT_PPP_LOST_IP;
// } else
if(_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX){
arduino_event.event_id = ARDUINO_EVENT_ETH_LOST_IP;
}
} else if(event_id == IP_EVENT_GOT_IP6){
ip_event_got_ip6_t* event = (ip_event_got_ip6_t*) event_data;
esp_ip6_addr_type_t addr_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
if(addr_type == ESP_IP6_ADDR_IS_GLOBAL){
setStatusBits(ESP_NETIF_HAS_GLOBAL_IP6_BIT);
} else if(addr_type == ESP_IP6_ADDR_IS_LINK_LOCAL){
setStatusBits(ESP_NETIF_HAS_LOCAL_IP6_BIT);
}
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
char if_name[NETIF_NAMESIZE] = {0,};
netif_index_to_name(event->ip6_info.ip.zone, if_name);
static const char * addr_types[] = { "UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6" };
log_v("IF %s Got IPv6: Interface: %d, IP Index: %d, Type: %s, Zone: %d (%s), Address: " IPV6STR, desc(), _interface_id, event->ip_index, addr_types[addr_type], event->ip6_info.ip.zone, if_name, IPV62STR(event->ip6_info.ip));
#endif
memcpy(&arduino_event.event_info.got_ip6, event_data, sizeof(ip_event_got_ip6_t));
#if SOC_WIFI_SUPPORTED
if(_interface_id == ESP_NETIF_ID_STA){
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_GOT_IP6;
} else if(_interface_id == ESP_NETIF_ID_AP){
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_GOT_IP6;
} else
#endif
// if(_interface_id == ESP_NETIF_ID_PPP){
// arduino_event.event_id = ARDUINO_EVENT_PPP_GOT_IP6;
// } else
if(_interface_id >= ESP_NETIF_ID_ETH && _interface_id < ESP_NETIF_ID_MAX){
arduino_event.event_id = ARDUINO_EVENT_ETH_GOT_IP6;
}
#if SOC_WIFI_SUPPORTED
} else if(event_id == IP_EVENT_AP_STAIPASSIGNED && _interface_id == ESP_NETIF_ID_AP){
setStatusBits(ESP_NETIF_HAS_IP_BIT);
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
ip_event_ap_staipassigned_t* event = (ip_event_ap_staipassigned_t*) event_data;
log_v("%s Assigned IP: " IPSTR " to MAC: %02X:%02X:%02X:%02X:%02X:%02X", desc(), IP2STR(&event->ip), event->mac[0], event->mac[1], event->mac[2], event->mac[3], event->mac[4], event->mac[5]);
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED;
memcpy(&arduino_event.event_info.wifi_ap_staipassigned, event_data, sizeof(ip_event_ap_staipassigned_t));
#endif
}
if(arduino_event.event_id < ARDUINO_EVENT_MAX){
Network.postEvent(&arduino_event);
}
}
NetworkInterface::NetworkInterface()
: _esp_netif(NULL)
, _interface_event_group(NULL)
, _initial_bits(0)
, _got_ip_event_id(-1)
, _lost_ip_event_id(-1)
, _interface_id(ESP_NETIF_ID_MAX)
, _is_server_if(false)
{}
NetworkInterface::~NetworkInterface(){
destroyNetif();
}
IPAddress NetworkInterface::calculateNetworkID(IPAddress ip, IPAddress subnet) const {
IPAddress networkID;
for (size_t i = 0; i < 4; i++)
networkID[i] = subnet[i] & ip[i];
return networkID;
}
IPAddress NetworkInterface::calculateBroadcast(IPAddress ip, IPAddress subnet) const {
IPAddress broadcastIp;
for (int i = 0; i < 4; i++)
broadcastIp[i] = ~subnet[i] | ip[i];
return broadcastIp;
}
uint8_t NetworkInterface::calculateSubnetCIDR(IPAddress subnetMask) const {
uint8_t CIDR = 0;
for (uint8_t i = 0; i < 4; i++) {
if (subnetMask[i] == 0x80) // 128
CIDR += 1;
else if (subnetMask[i] == 0xC0) // 192
CIDR += 2;
else if (subnetMask[i] == 0xE0) // 224
CIDR += 3;
else if (subnetMask[i] == 0xF0) // 242
CIDR += 4;
else if (subnetMask[i] == 0xF8) // 248
CIDR += 5;
else if (subnetMask[i] == 0xFC) // 252
CIDR += 6;
else if (subnetMask[i] == 0xFE) // 254
CIDR += 7;
else if (subnetMask[i] == 0xFF) // 255
CIDR += 8;
}
return CIDR;
}
int NetworkInterface::setStatusBits(int bits) {
if(!_interface_event_group){
_initial_bits |= bits;
return _initial_bits;
}
return xEventGroupSetBits(_interface_event_group, bits);
}
int NetworkInterface::clearStatusBits(int bits) {
if(!_interface_event_group){
_initial_bits &= ~bits;
return _initial_bits;
}
return xEventGroupClearBits(_interface_event_group, bits) ;
}
int NetworkInterface::getStatusBits() const {
if(!_interface_event_group){
return _initial_bits;
}
return xEventGroupGetBits(_interface_event_group);
}
int NetworkInterface::waitStatusBits(int bits, uint32_t timeout_ms) const {
if(!_interface_event_group){
return 0;
}
bits = xEventGroupWaitBits(
_interface_event_group, // The event group being tested.
bits, // The bits within the event group to wait for.
pdFALSE, // bits should be cleared before returning.
pdTRUE, // Don't wait for all bits, any bit will do.
timeout_ms / portTICK_PERIOD_MS ) & bits; // Wait a maximum of timeout_ms for any bit to be set.
return bits;
}
void NetworkInterface::destroyNetif() {
if(_ip_ev_instance != NULL){
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &_ip_event_cb);
_ip_ev_instance = NULL;
}
if(_esp_netif != NULL){
esp_netif_destroy(_esp_netif);
_esp_netif = NULL;
}
if(_interface_event_group != NULL){
vEventGroupDelete(_interface_event_group);
_interface_event_group = NULL;
_initial_bits = 0;
}
}
bool NetworkInterface::initNetif(Network_Interface_ID interface_id, bool server_interface) {
if(_esp_netif == NULL || interface_id >= ESP_NETIF_ID_MAX){
return false;
}
_is_server_if = server_interface;
_interface_id = interface_id;
_got_ip_event_id = esp_netif_get_event_id(_esp_netif, ESP_NETIF_IP_EVENT_GOT_IP);
_lost_ip_event_id = esp_netif_get_event_id(_esp_netif, ESP_NETIF_IP_EVENT_LOST_IP);
_interfaces[_interface_id] = this;
if(_interface_event_group == NULL){
_interface_event_group = xEventGroupCreate();
if(!_interface_event_group){
log_e("Interface Event Group Create Failed!");
return false;
}
setStatusBits(_initial_bits);
}
if(_ip_ev_instance == NULL && esp_event_handler_instance_register(IP_EVENT, ESP_EVENT_ANY_ID, &_ip_event_cb, NULL, &_ip_ev_instance)){
log_e("event_handler_instance_register for IP_EVENT Failed!");
return false;
}
return true;
}
bool NetworkInterface::started() const {
return (getStatusBits() & ESP_NETIF_STARTED_BIT) != 0;
}
bool NetworkInterface::connected() const {
return (getStatusBits() & ESP_NETIF_CONNECTED_BIT) != 0;
}
bool NetworkInterface::hasIP() const {
return (getStatusBits() & ESP_NETIF_HAS_IP_BIT) != 0;
}
bool NetworkInterface::hasLinkLocalIPv6() const {
return (getStatusBits() & ESP_NETIF_HAS_LOCAL_IP6_BIT) != 0;
}
bool NetworkInterface::hasGlobalIPv6() const {
return (getStatusBits() & ESP_NETIF_HAS_GLOBAL_IP6_BIT) != 0;
}
bool NetworkInterface::enableIPv6(bool en)
{
if (en) {
setStatusBits(ESP_NETIF_WANT_IP6_BIT);
} else {
clearStatusBits(ESP_NETIF_WANT_IP6_BIT);
}
return true;
}
bool NetworkInterface::dnsIP(uint8_t dns_no, IPAddress ip)
{
if(_esp_netif == NULL || dns_no > 2){
return false;
}
if(_is_server_if && dns_no > 0){
log_e("Server interfaces can have only one DNS server.");
return false;
}
esp_netif_dns_info_t d;
// ToDo: can this work with IPv6 addresses?
d.ip.type = IPADDR_TYPE_V4;
if(static_cast<uint32_t>(ip) != 0){
d.ip.u_addr.ip4.addr = static_cast<uint32_t>(ip);
} else {
d.ip.u_addr.ip4.addr = 0;
}
if(esp_netif_set_dns_info(_esp_netif, (esp_netif_dns_type_t)dns_no, &d) != ESP_OK){
return false;
}
return true;
}
bool NetworkInterface::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2, IPAddress dns3)
{
if(_esp_netif == NULL){
return false;
}
esp_err_t err = ESP_OK;
esp_netif_ip_info_t info;
esp_netif_dns_info_t d1;
esp_netif_dns_info_t d2;
esp_netif_dns_info_t d3;
d1.ip.type = IPADDR_TYPE_V4;
d2.ip.type = IPADDR_TYPE_V4;
d3.ip.type = IPADDR_TYPE_V4;
if(static_cast<uint32_t>(local_ip) != 0){
info.ip.addr = static_cast<uint32_t>(local_ip);
info.gw.addr = static_cast<uint32_t>(gateway);
info.netmask.addr = static_cast<uint32_t>(subnet);
d1.ip.u_addr.ip4.addr = static_cast<uint32_t>(dns1);
d2.ip.u_addr.ip4.addr = static_cast<uint32_t>(dns2);
d3.ip.u_addr.ip4.addr = static_cast<uint32_t>(dns3);
} else {
info.ip.addr = 0;
info.gw.addr = 0;
info.netmask.addr = 0;
d1.ip.u_addr.ip4.addr = 0;
d2.ip.u_addr.ip4.addr = 0;
d3.ip.u_addr.ip4.addr = 0;
}
if(_is_server_if){
// Stop DHCPS
err = esp_netif_dhcps_stop(_esp_netif);
if(err && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED){
log_e("DHCPS Stop Failed! 0x%04x: %s", err, esp_err_to_name(err));
return false;
}
// Set IPv4, Netmask, Gateway
err = esp_netif_set_ip_info(_esp_netif, &info);
if(err){
log_e("Netif Set IP Failed! 0x%04x: %s", err, esp_err_to_name(err));
return false;
}
// Set DNS Server
if(d2.ip.u_addr.ip4.addr != 0){
esp_netif_set_dns_info(_esp_netif, ESP_NETIF_DNS_MAIN, &d2);
}
dhcps_lease_t lease;
lease.enable = true;
uint8_t CIDR = calculateSubnetCIDR(subnet);
log_v("SoftAP: %s | Gateway: %s | DHCP Start: %s | Netmask: %s", local_ip.toString().c_str(), gateway.toString().c_str(), dns1.toString().c_str(), subnet.toString().c_str());
// netmask must have room for at least 12 IP addresses (AP + GW + 10 DHCP Leasing addresses)
// netmask also must be limited to the last 8 bits of IPv4, otherwise this function won't work
// IDF NETIF checks netmask for the 3rd byte: https://github.com/espressif/esp-idf/blob/master/components/esp_netif/lwip/esp_netif_lwip.c#L1857-L1862
if (CIDR > 28 || CIDR < 24) {
log_e("Bad netmask. It must be from /24 to /28 (255.255.255. 0<->240)");
return false; // ESP_FAIL if initializing failed
}
#define _byte_swap32(num) (((num>>24)&0xff) | ((num<<8)&0xff0000) | ((num>>8)&0xff00) | ((num<<24)&0xff000000))
// The code below is ready for any netmask, not limited to 255.255.255.0
uint32_t netmask = _byte_swap32(info.netmask.addr);
uint32_t ap_ipaddr = _byte_swap32(info.ip.addr);
uint32_t dhcp_ipaddr = _byte_swap32(static_cast<uint32_t>(dns1));
dhcp_ipaddr = dhcp_ipaddr == 0 ? ap_ipaddr + 1 : dhcp_ipaddr;
uint32_t leaseStartMax = ~netmask - 10;
// there will be 10 addresses for DHCP to lease
lease.start_ip.addr = dhcp_ipaddr;
lease.end_ip.addr = lease.start_ip.addr + 10;
// Check if local_ip is in the same subnet as the dhcp leasing range initial address
if ((ap_ipaddr & netmask) != (dhcp_ipaddr & netmask)) {
log_e("The AP IP address (%s) and the DHCP start address (%s) must be in the same subnet",
local_ip.toString().c_str(), IPAddress(_byte_swap32(dhcp_ipaddr)).toString().c_str());
return false; // ESP_FAIL if initializing failed
}
// prevents DHCP lease range to overflow subnet range
if ((dhcp_ipaddr & ~netmask) >= leaseStartMax) {
// make first DHCP lease addr stay in the begining of the netmask range
lease.start_ip.addr = (dhcp_ipaddr & netmask) + 1;
lease.end_ip.addr = lease.start_ip.addr + 10;
log_w("DHCP Lease out of range - Changing DHCP leasing start to %s", IPAddress(_byte_swap32(lease.start_ip.addr)).toString().c_str());
}
// Check if local_ip is within DHCP range
if (ap_ipaddr >= lease.start_ip.addr && ap_ipaddr <= lease.end_ip.addr) {
log_e("The AP IP address (%s) can't be within the DHCP range (%s -- %s)",
local_ip.toString().c_str(), IPAddress(_byte_swap32(lease.start_ip.addr)).toString().c_str(), IPAddress(_byte_swap32(lease.end_ip.addr)).toString().c_str());
return false; // ESP_FAIL if initializing failed
}
// Check if gateway is within DHCP range
uint32_t gw_ipaddr = _byte_swap32(info.gw.addr);
bool gw_in_same_subnet = (gw_ipaddr & netmask) == (ap_ipaddr & netmask);
if (gw_in_same_subnet && gw_ipaddr >= lease.start_ip.addr && gw_ipaddr <= lease.end_ip.addr) {
log_e("The GatewayP address (%s) can't be within the DHCP range (%s -- %s)",
gateway.toString().c_str(), IPAddress(_byte_swap32(lease.start_ip.addr)).toString().c_str(), IPAddress(_byte_swap32(lease.end_ip.addr)).toString().c_str());
return false; // ESP_FAIL if initializing failed
}
// all done, just revert back byte order of DHCP lease range
lease.start_ip.addr = _byte_swap32(lease.start_ip.addr);
lease.end_ip.addr = _byte_swap32(lease.end_ip.addr);
log_v("DHCP Server Range: %s to %s", IPAddress(lease.start_ip.addr).toString().c_str(), IPAddress(lease.end_ip.addr).toString().c_str());
err = esp_netif_dhcps_option(
_esp_netif,
ESP_NETIF_OP_SET,
ESP_NETIF_REQUESTED_IP_ADDRESS,
(void*)&lease, sizeof(dhcps_lease_t)
);
if(err){
log_e("DHCPS Set Lease Failed! 0x%04x: %s", err, esp_err_to_name(err));
return false;
}
// Start DHCPS
err = esp_netif_dhcps_start(_esp_netif);
if(err){
log_e("DHCPS Start Failed! 0x%04x: %s", err, esp_err_to_name(err));
return false;
}
} else {
// Stop DHCPC
err = esp_netif_dhcpc_stop(_esp_netif);
if(err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED){
log_e("DHCP could not be stopped! Error: 0x%04x: %s", err, esp_err_to_name(err));
return false;
}
clearStatusBits(ESP_NETIF_HAS_IP_BIT);
// Set IPv4, Netmask, Gateway
err = esp_netif_set_ip_info(_esp_netif, &info);
if(err != ERR_OK){
log_e("ETH IP could not be configured! Error: 0x%04x: %s", err, esp_err_to_name(err));
return false;
}
// Set DNS Servers
esp_netif_set_dns_info(_esp_netif, ESP_NETIF_DNS_MAIN, &d1);
esp_netif_set_dns_info(_esp_netif, ESP_NETIF_DNS_BACKUP, &d2);
esp_netif_set_dns_info(_esp_netif, ESP_NETIF_DNS_FALLBACK, &d3);
// Start DHCPC if static IP was set
if(info.ip.addr == 0){
err = esp_netif_dhcpc_start(_esp_netif);
if(err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED){
log_w("DHCP could not be started! Error: 0x%04x: %s", err, esp_err_to_name(err));
return false;
}
} else {
setStatusBits(ESP_NETIF_HAS_IP_BIT);
}
}
return true;
}
const char * NetworkInterface::getHostname() const
{
if(_esp_netif == NULL){
return "";
}
const char * hostname;
if(esp_netif_get_hostname(_esp_netif, &hostname)){
return NULL;
}
return hostname;
}
bool NetworkInterface::setHostname(const char * hostname) const
{
if(_esp_netif == NULL){
return false;
}
return esp_netif_set_hostname(_esp_netif, hostname) == 0;
}
bool NetworkInterface::linkUp() const
{
if(_esp_netif == NULL){
return false;
}
return esp_netif_is_netif_up(_esp_netif);
}
const char * NetworkInterface::ifkey(void) const
{
if(_esp_netif == NULL){
return "";
}
return esp_netif_get_ifkey(_esp_netif);
}
const char * NetworkInterface::desc(void) const
{
if(_esp_netif == NULL){
return "";
}
return esp_netif_get_desc(_esp_netif);
}
String NetworkInterface::impl_name(void) const
{
if(_esp_netif == NULL){
return String("");
}
char netif_name[8];
esp_err_t err = esp_netif_get_netif_impl_name(_esp_netif, netif_name);
if(err != ESP_OK){
log_e("Failed to get netif impl_name: %d", err);
return String("");
}
return String(netif_name);
}
uint8_t * NetworkInterface::macAddress(uint8_t* mac) const
{
if(!mac || _esp_netif == NULL){
return NULL;
}
esp_err_t err = esp_netif_get_mac(_esp_netif, mac);
if(err != ESP_OK){
log_e("Failed to get netif mac: %d", err);
return NULL;
}
// getMac(mac);
return mac;
}
String NetworkInterface::macAddress(void) const
{
uint8_t mac[6] = {0,0,0,0,0,0};
char macStr[18] = { 0 };
macAddress(mac);
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(macStr);
}
IPAddress NetworkInterface::localIP() const
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return IPAddress();
}
return IPAddress(ip.ip.addr);
}
IPAddress NetworkInterface::subnetMask() const
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return IPAddress();
}
return IPAddress(ip.netmask.addr);
}
IPAddress NetworkInterface::gatewayIP() const
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return IPAddress();
}
return IPAddress(ip.gw.addr);
}
IPAddress NetworkInterface::dnsIP(uint8_t dns_no) const
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_dns_info_t d;
if(esp_netif_get_dns_info(_esp_netif, dns_no?ESP_NETIF_DNS_BACKUP:ESP_NETIF_DNS_MAIN, &d) != ESP_OK){
return IPAddress();
}
return IPAddress(d.ip.u_addr.ip4.addr);
}
IPAddress NetworkInterface::broadcastIP() const
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return IPAddress();
}
return calculateBroadcast(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr));
}
IPAddress NetworkInterface::networkID() const
{
if(_esp_netif == NULL){
return IPAddress();
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return IPAddress();
}
return calculateNetworkID(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr));
}
uint8_t NetworkInterface::subnetCIDR() const
{
if(_esp_netif == NULL){
return (uint8_t)0;
}
esp_netif_ip_info_t ip;
if(esp_netif_get_ip_info(_esp_netif, &ip)){
return (uint8_t)0;
}
return calculateSubnetCIDR(IPAddress(ip.netmask.addr));
}
IPAddress NetworkInterface::linkLocalIPv6() const
{
if(_esp_netif == NULL){
return IPAddress(IPv6);
}
static esp_ip6_addr_t addr;
if(esp_netif_get_ip6_linklocal(_esp_netif, &addr)){
return IPAddress(IPv6);
}
return IPAddress(IPv6, (const uint8_t *)addr.addr, addr.zone);
}
IPAddress NetworkInterface::globalIPv6() const
{
if(_esp_netif == NULL){
return IPAddress(IPv6);
}
static esp_ip6_addr_t addr;
if(esp_netif_get_ip6_global(_esp_netif, &addr)){
return IPAddress(IPv6);
}
return IPAddress(IPv6, (const uint8_t *)addr.addr, addr.zone);
}
size_t NetworkInterface::printTo(Print & out) const {
size_t bytes = 0;
bytes += out.print(esp_netif_get_desc(_esp_netif));
bytes += out.print(":");
if(esp_netif_is_netif_up(_esp_netif)){
bytes += out.print(" <UP");
} else {
bytes += out.print(" <DOWN");
}
bytes += printDriverInfo(out);
bytes += out.println(">");
bytes += out.print(" ");
bytes += out.print("ether ");
bytes += out.print(macAddress());
bytes += out.println();
bytes += out.print(" ");
bytes += out.print("inet ");
bytes += out.print(localIP());
bytes += out.print(" netmask ");
bytes += out.print(subnetMask());
bytes += out.print(" broadcast ");
bytes += out.print(broadcastIP());
bytes += out.println();
bytes += out.print(" ");
bytes += out.print("gateway ");
bytes += out.print(gatewayIP());
bytes += out.print(" dns ");
bytes += out.print(dnsIP());
bytes += out.println();
static const char * types[] = { "UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6" };
esp_ip6_addr_t if_ip6[CONFIG_LWIP_IPV6_NUM_ADDRESSES];
int v6addrs = esp_netif_get_all_ip6(_esp_netif, if_ip6);
for (int i = 0; i < v6addrs; ++i){
bytes += out.print(" ");
bytes += out.print("inet6 ");
bytes += IPAddress(IPv6, (const uint8_t *)if_ip6[i].addr, if_ip6[i].zone).printTo(out, true);
bytes += out.print(" type ");
bytes += out.print(types[esp_netif_ip6_get_addr_type(&if_ip6[i])]);
bytes += out.println();
}
return bytes;
}

View file

@ -0,0 +1,99 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_netif_types.h"
#include "esp_event.h"
#include "Arduino.h"
#include "NetworkManager.h"
#include "Printable.h"
typedef enum {
ESP_NETIF_ID_STA,
ESP_NETIF_ID_AP,
ESP_NETIF_ID_PPP,
ESP_NETIF_ID_ETH0,
ESP_NETIF_ID_ETH1,
ESP_NETIF_ID_ETH2,
ESP_NETIF_ID_MAX
} Network_Interface_ID;
static const int ESP_NETIF_STARTED_BIT = BIT0;
static const int ESP_NETIF_CONNECTED_BIT = BIT1;
static const int ESP_NETIF_HAS_IP_BIT = BIT2;
static const int ESP_NETIF_HAS_LOCAL_IP6_BIT = BIT3;
static const int ESP_NETIF_HAS_GLOBAL_IP6_BIT = BIT4;
static const int ESP_NETIF_WANT_IP6_BIT = BIT5;
#define ESP_NETIF_ID_ETH ESP_NETIF_ID_ETH0
class NetworkInterface: public Printable {
public:
NetworkInterface();
virtual ~NetworkInterface();
// For server interfaces (WiFi AP), dns1 is the DHCP lease range start and dns2 is the DNS. dns3 is not used
bool config(IPAddress local_ip = (uint32_t)0x00000000, IPAddress gateway = (uint32_t)0x00000000, IPAddress subnet = (uint32_t)0x00000000, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000, IPAddress dns3 = (uint32_t)0x00000000);
bool dnsIP(uint8_t dns_no, IPAddress ip);
const char * getHostname() const;
bool setHostname(const char * hostname) const;
bool started() const;
bool connected() const;
bool hasIP() const;
bool hasLinkLocalIPv6() const;
bool hasGlobalIPv6() const;
bool enableIPv6(bool en=true);
bool linkUp() const;
const char * ifkey() const;
const char * desc() const;
String impl_name() const;
uint8_t * macAddress(uint8_t* mac) const;
String macAddress() const;
IPAddress localIP() const;
IPAddress subnetMask() const;
IPAddress gatewayIP() const;
IPAddress dnsIP(uint8_t dns_no = 0) const;
IPAddress broadcastIP() const;
IPAddress networkID() const;
uint8_t subnetCIDR() const;
IPAddress linkLocalIPv6() const;
IPAddress globalIPv6() const;
size_t printTo(Print & out) const;
esp_netif_t * netif(){ return _esp_netif; }
int getStatusBits() const;
int waitStatusBits(int bits, uint32_t timeout_ms) const;
protected:
esp_netif_t *_esp_netif;
EventGroupHandle_t _interface_event_group;
int _initial_bits;
int32_t _got_ip_event_id;
int32_t _lost_ip_event_id;
Network_Interface_ID _interface_id;
bool _is_server_if;
bool initNetif(Network_Interface_ID interface_id, bool server_interface=false);
void destroyNetif();
int setStatusBits(int bits);
int clearStatusBits(int bits);
// virtual void getMac(uint8_t* mac) = 0;
virtual size_t printDriverInfo(Print & out) const = 0;
public:
void _onIpEvent(int32_t event_id, void* event_data);
private:
IPAddress calculateNetworkID(IPAddress ip, IPAddress subnet) const;
IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet) const;
uint8_t calculateSubnetCIDR(IPAddress subnetMask) const;
};

View file

@ -0,0 +1,177 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "NetworkManager.h"
#include "NetworkInterface.h"
#include "esp_netif.h"
#include "lwip/ip_addr.h"
#include "lwip/dns.h"
#include "esp32-hal-log.h"
#include "esp_mac.h"
NetworkManager::NetworkManager(){
}
bool NetworkManager::begin(){
static bool initialized = false;
if(!initialized){
initialized = true;
#if CONFIG_IDF_TARGET_ESP32
uint8_t mac[8];
if(esp_efuse_mac_get_default(mac) == ESP_OK){
esp_base_mac_addr_set(mac);
}
#endif
initialized = esp_netif_init() == ESP_OK;
if(!initialized){
log_e("esp_netif_init failed!");
}
}
if(initialized){
initNetworkEvents();
}
return initialized;
}
typedef struct gethostbynameParameters {
const char *hostname;
ip_addr_t addr;
uint8_t addr_type;
int result;
} gethostbynameParameters_t;
/**
* DNS callback
* @param name
* @param ipaddr
* @param callback_arg
*/
static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
{
gethostbynameParameters_t *parameters = static_cast<gethostbynameParameters_t *>(callback_arg);
if(ipaddr) {
if(parameters->result == 0){
memcpy(&(parameters->addr), ipaddr, sizeof(ip_addr_t));
parameters->result = 1;
}
} else {
parameters->result = -1;
}
Network.setStatusBits(NET_DNS_DONE_BIT);
}
/**
* Callback to execute dns_gethostbyname in lwIP's TCP/IP context
* @param param Parameters for dns_gethostbyname call
*/
static esp_err_t wifi_gethostbyname_tcpip_ctx(void *param)
{
gethostbynameParameters_t *parameters = static_cast<gethostbynameParameters_t *>(param);
return dns_gethostbyname_addrtype(parameters->hostname, &parameters->addr, &wifi_dns_found_callback, parameters, parameters->addr_type);
}
/**
* Resolve the given hostname to an IP address.
* @param aHostname Name to be resolved
* @param aResult IPAddress structure to store the returned IP address
* @return 1 if aIPAddrString was successfully converted to an IP address,
* else error code
*/
int NetworkManager::hostByName(const char* aHostname, IPAddress& aResult, bool preferV6)
{
err_t err = ERR_OK;
gethostbynameParameters_t params;
// This should generally check if we have a global address assigned to one of the interfaces.
// If such address is not assigned, there is no point in trying to get V6 from DNS as we will not be able to reach it.
// That is of course, if 'preferV6' is not set to true
static bool hasGlobalV6 = false;
bool hasGlobalV6Now = false;//ToDo: implement this!
if(hasGlobalV6 != hasGlobalV6Now){
hasGlobalV6 = hasGlobalV6Now;
dns_clear_cache();
log_d("Clearing DNS cache");
}
aResult = static_cast<uint32_t>(0);
params.hostname = aHostname;
params.addr_type = (preferV6 || hasGlobalV6)?LWIP_DNS_ADDRTYPE_IPV6_IPV4:LWIP_DNS_ADDRTYPE_IPV4;
params.result = 0;
aResult.to_ip_addr_t(&(params.addr));
if (!aResult.fromString(aHostname)) {
Network.waitStatusBits(NET_DNS_IDLE_BIT, 16000);
Network.clearStatusBits(NET_DNS_IDLE_BIT | NET_DNS_DONE_BIT);
err = esp_netif_tcpip_exec(wifi_gethostbyname_tcpip_ctx, &params);
if (err == ERR_OK) {
aResult.from_ip_addr_t(&(params.addr));
} else if (err == ERR_INPROGRESS) {
Network.waitStatusBits(NET_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s]
Network.clearStatusBits(NET_DNS_DONE_BIT);
if (params.result == 1) {
aResult.from_ip_addr_t(&(params.addr));
err = ERR_OK;
}
}
Network.setStatusBits(NET_DNS_IDLE_BIT);
}
if (err == ERR_OK) {
return 1;
}
log_e("DNS Failed for '%s' with error '%d' and result '%d'", aHostname, err, params.result);
return err;
}
uint8_t * NetworkManager::macAddress(uint8_t * mac){
esp_base_mac_addr_get(mac);
return mac;
}
String NetworkManager::macAddress(void){
uint8_t mac[6];
char macStr[18] = { 0 };
macAddress(mac);
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(macStr);
}
static char default_hostname[32] = {0,};
const char * NetworkManager::getHostname()
{
if(default_hostname[0] == 0){
uint8_t eth_mac[6];
esp_base_mac_addr_get(eth_mac);
snprintf(default_hostname, 32, "%s%02X%02X%02X", CONFIG_IDF_TARGET "-", eth_mac[3], eth_mac[4], eth_mac[5]);
}
return (const char *)default_hostname;
}
bool NetworkManager::setHostname(const char * name)
{
if(name){
snprintf(default_hostname, 32, "%s", name);
}
return true;
}
NetworkInterface * getNetifByID(Network_Interface_ID id);
size_t NetworkManager::printTo(Print & out) const {
size_t bytes = 0;
for (int i = 0; i < ESP_NETIF_ID_MAX; ++i){
NetworkInterface * iface = getNetifByID((Network_Interface_ID)i);
if(iface != NULL && iface->netif() != NULL){
bytes += out.println(*iface);
}
}
return bytes;
}
NetworkManager Network;

View file

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "NetworkEvents.h"
#include "IPAddress.h"
#include "WString.h"
class NetworkManager : public NetworkEvents, public Printable {
public:
NetworkManager();
bool begin();
int hostByName(const char *aHostname, IPAddress &aResult, bool preferV6=false);
uint8_t * macAddress(uint8_t * mac);
String macAddress();
size_t printTo(Print & out) const;
static const char * getHostname();
static bool setHostname(const char * hostname);
static bool hostname(const String& aHostname) { return setHostname(aHostname.c_str()); }
};
extern NetworkManager Network;

View file

@ -16,14 +16,14 @@
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "WiFiServer.h" #include "NetworkServer.h"
#include <lwip/sockets.h> #include <lwip/sockets.h>
#include <lwip/netdb.h> #include <lwip/netdb.h>
#undef write #undef write
#undef close #undef close
int WiFiServer::setTimeout(uint32_t seconds){ int NetworkServer::setTimeout(uint32_t seconds){
struct timeval tv; struct timeval tv;
tv.tv_sec = seconds; tv.tv_sec = seconds;
tv.tv_usec = 0; tv.tv_usec = 0;
@ -32,13 +32,13 @@ int WiFiServer::setTimeout(uint32_t seconds){
return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval)); return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));
} }
WiFiClient WiFiServer::available(){ NetworkClient NetworkServer::available(){
return accept(); return accept();
} }
WiFiClient WiFiServer::accept(){ NetworkClient NetworkServer::accept(){
if(!_listening) if(!_listening)
return WiFiClient(); return NetworkClient();
int client_sock; int client_sock;
if (_accepted_sockfd >= 0) { if (_accepted_sockfd >= 0) {
client_sock = _accepted_sockfd; client_sock = _accepted_sockfd;
@ -58,17 +58,17 @@ WiFiClient WiFiServer::accept(){
if(setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(int)) == ESP_OK) { if(setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(int)) == ESP_OK) {
val = _noDelay; val = _noDelay;
if(setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(int)) == ESP_OK) if(setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(int)) == ESP_OK)
return WiFiClient(client_sock); return NetworkClient(client_sock);
} }
} }
return WiFiClient(); return NetworkClient();
} }
void WiFiServer::begin(uint16_t port){ void NetworkServer::begin(uint16_t port){
begin(port, 1); begin(port, 1);
} }
void WiFiServer::begin(uint16_t port, int enable){ void NetworkServer::begin(uint16_t port, int enable){
if(_listening) if(_listening)
return; return;
if(port){ if(port){
@ -99,15 +99,15 @@ void WiFiServer::begin(uint16_t port, int enable){
_accepted_sockfd = -1; _accepted_sockfd = -1;
} }
void WiFiServer::setNoDelay(bool nodelay) { void NetworkServer::setNoDelay(bool nodelay) {
_noDelay = nodelay; _noDelay = nodelay;
} }
bool WiFiServer::getNoDelay() { bool NetworkServer::getNoDelay() {
return _noDelay; return _noDelay;
} }
bool WiFiServer::hasClient() { bool NetworkServer::hasClient() {
if (_accepted_sockfd >= 0) { if (_accepted_sockfd >= 0) {
return true; return true;
} }
@ -124,7 +124,7 @@ bool WiFiServer::hasClient() {
return false; return false;
} }
void WiFiServer::end(){ void NetworkServer::end(){
#ifdef ESP_IDF_VERSION_MAJOR #ifdef ESP_IDF_VERSION_MAJOR
lwip_close(sockfd); lwip_close(sockfd);
#else #else
@ -134,10 +134,10 @@ void WiFiServer::end(){
_listening = false; _listening = false;
} }
void WiFiServer::close(){ void NetworkServer::close(){
end(); end();
} }
void WiFiServer::stop(){ void NetworkServer::stop(){
end(); end();
} }

View file

@ -0,0 +1,60 @@
/*
Server.h - Server class for Raspberry Pi
Copyright (c) 2016 Hristo Gochkov All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "Arduino.h"
#include "Server.h"
#include "NetworkClient.h"
#include "IPAddress.h"
class NetworkServer {
private:
int sockfd;
int _accepted_sockfd = -1;
IPAddress _addr;
uint16_t _port;
uint8_t _max_clients;
bool _listening;
bool _noDelay = false;
public:
void listenOnLocalhost(){}
NetworkServer(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("NetworkServer::NetworkServer(port=%d, ...)", port);
}
NetworkServer(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("NetworkServer::NetworkServer(addr=%s, port=%d, ...)", addr.toString().c_str(), port);
}
~NetworkServer(){ end();}
NetworkClient available() __attribute__((deprecated("Renamed to accept().")));
NetworkClient accept();
void begin(uint16_t port=0);
void begin(uint16_t port, int reuse_enable);
void setNoDelay(bool nodelay);
bool getNoDelay();
bool hasClient();
void end();
void close();
void stop();
operator bool(){return _listening;}
int setTimeout(uint32_t seconds);
};

View file

@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "WiFiUdp.h" #include "NetworkUdp.h"
#include <new> //std::nothrow #include <new> //std::nothrow
#include <lwip/sockets.h> #include <lwip/sockets.h>
#include <lwip/netdb.h> #include <lwip/netdb.h>
@ -26,7 +26,7 @@
#undef write #undef write
#undef read #undef read
WiFiUDP::WiFiUDP() NetworkUDP::NetworkUDP()
: udp_server(-1) : udp_server(-1)
, server_port(0) , server_port(0)
, remote_port(0) , remote_port(0)
@ -35,11 +35,11 @@ WiFiUDP::WiFiUDP()
, rx_buffer(0) , rx_buffer(0)
{} {}
WiFiUDP::~WiFiUDP(){ NetworkUDP::~NetworkUDP(){
stop(); stop();
} }
uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){ uint8_t NetworkUDP::begin(IPAddress address, uint16_t port){
stop(); stop();
server_port = port; server_port = port;
@ -100,11 +100,11 @@ uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){
return 1; return 1;
} }
uint8_t WiFiUDP::begin(uint16_t p){ uint8_t NetworkUDP::begin(uint16_t p){
return begin(IPAddress(), p); return begin(IPAddress(), p);
} }
uint8_t WiFiUDP::beginMulticast(IPAddress address, uint16_t p){ uint8_t NetworkUDP::beginMulticast(IPAddress address, uint16_t p){
if(begin(IPAddress(), p)){ if(begin(IPAddress(), p)){
ip_addr_t addr; ip_addr_t addr;
address.to_ip_addr_t(&addr); address.to_ip_addr_t(&addr);
@ -147,7 +147,7 @@ uint8_t WiFiUDP::beginMulticast(IPAddress address, uint16_t p){
return 0; return 0;
} }
void WiFiUDP::stop(){ void NetworkUDP::stop(){
if(tx_buffer){ if(tx_buffer){
free(tx_buffer); free(tx_buffer);
tx_buffer = NULL; tx_buffer = NULL;
@ -190,7 +190,7 @@ void WiFiUDP::stop(){
udp_server = -1; udp_server = -1;
} }
int WiFiUDP::beginMulticastPacket(){ int NetworkUDP::beginMulticastPacket(){
if(!server_port || multicast_ip == IPAddress()) if(!server_port || multicast_ip == IPAddress())
return 0; return 0;
remote_ip = multicast_ip; remote_ip = multicast_ip;
@ -198,7 +198,7 @@ int WiFiUDP::beginMulticastPacket(){
return beginPacket(); return beginPacket();
} }
int WiFiUDP::beginPacket(){ int NetworkUDP::beginPacket(){
if(!remote_port) if(!remote_port)
return 0; return 0;
@ -226,13 +226,13 @@ int WiFiUDP::beginPacket(){
return 1; return 1;
} }
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port){ int NetworkUDP::beginPacket(IPAddress ip, uint16_t port){
remote_ip = ip; remote_ip = ip;
remote_port = port; remote_port = port;
return beginPacket(); return beginPacket();
} }
int WiFiUDP::beginPacket(const char *host, uint16_t port){ int NetworkUDP::beginPacket(const char *host, uint16_t port){
struct hostent *server; struct hostent *server;
server = gethostbyname(host); server = gethostbyname(host);
if (server == NULL){ if (server == NULL){
@ -242,7 +242,7 @@ int WiFiUDP::beginPacket(const char *host, uint16_t port){
return beginPacket(IPAddress((const uint8_t *)(server->h_addr_list[0])), port); return beginPacket(IPAddress((const uint8_t *)(server->h_addr_list[0])), port);
} }
int WiFiUDP::endPacket(){ int NetworkUDP::endPacket(){
ip_addr_t addr; ip_addr_t addr;
remote_ip.to_ip_addr_t(&addr); remote_ip.to_ip_addr_t(&addr);
@ -272,7 +272,7 @@ int WiFiUDP::endPacket(){
return 1; return 1;
} }
size_t WiFiUDP::write(uint8_t data){ size_t NetworkUDP::write(uint8_t data){
if(tx_buffer_len == 1460){ if(tx_buffer_len == 1460){
endPacket(); endPacket();
tx_buffer_len = 0; tx_buffer_len = 0;
@ -281,14 +281,14 @@ size_t WiFiUDP::write(uint8_t data){
return 1; return 1;
} }
size_t WiFiUDP::write(const uint8_t *buffer, size_t size){ size_t NetworkUDP::write(const uint8_t *buffer, size_t size){
size_t i; size_t i;
for(i=0;i<size;i++) for(i=0;i<size;i++)
write(buffer[i]); write(buffer[i]);
return i; return i;
} }
int WiFiUDP::parsePacket(){ int NetworkUDP::parsePacket(){
if(rx_buffer) if(rx_buffer)
return 0; return 0;
struct sockaddr_storage si_other_storage; // enough storage for v4 and v6 struct sockaddr_storage si_other_storage; // enough storage for v4 and v6
@ -338,12 +338,12 @@ int WiFiUDP::parsePacket(){
return len; return len;
} }
int WiFiUDP::available(){ int NetworkUDP::available(){
if(!rx_buffer) return 0; if(!rx_buffer) return 0;
return rx_buffer->available(); return rx_buffer->available();
} }
int WiFiUDP::read(){ int NetworkUDP::read(){
if(!rx_buffer) return -1; if(!rx_buffer) return -1;
int out = rx_buffer->read(); int out = rx_buffer->read();
if(!rx_buffer->available()){ if(!rx_buffer->available()){
@ -354,11 +354,11 @@ int WiFiUDP::read(){
return out; return out;
} }
int WiFiUDP::read(unsigned char* buffer, size_t len){ int NetworkUDP::read(unsigned char* buffer, size_t len){
return read((char *)buffer, len); return read((char *)buffer, len);
} }
int WiFiUDP::read(char* buffer, size_t len){ int NetworkUDP::read(char* buffer, size_t len){
if(!rx_buffer) return 0; if(!rx_buffer) return 0;
int out = rx_buffer->read(buffer, len); int out = rx_buffer->read(buffer, len);
if(!rx_buffer->available()){ if(!rx_buffer->available()){
@ -369,22 +369,22 @@ int WiFiUDP::read(char* buffer, size_t len){
return out; return out;
} }
int WiFiUDP::peek(){ int NetworkUDP::peek(){
if(!rx_buffer) return -1; if(!rx_buffer) return -1;
return rx_buffer->peek(); return rx_buffer->peek();
} }
void WiFiUDP::flush(){ void NetworkUDP::flush(){
if(!rx_buffer) return; if(!rx_buffer) return;
cbuf *b = rx_buffer; cbuf *b = rx_buffer;
rx_buffer = 0; rx_buffer = 0;
delete b; delete b;
} }
IPAddress WiFiUDP::remoteIP(){ IPAddress NetworkUDP::remoteIP(){
return remote_ip; return remote_ip;
} }
uint16_t WiFiUDP::remotePort(){ uint16_t NetworkUDP::remotePort(){
return remote_port; return remote_port;
} }

View file

@ -0,0 +1,77 @@
/*
* Udp.cpp: Library to send/receive UDP packets.
*
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
* might not happen often in practice, but in larger network topologies, a UDP
* packet can be received out of sequence.
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
* aware of it. Again, this may not be a concern in practice on small local networks.
* For more information, see http://www.cafeaulait.org/course/week12/35.html
*
* MIT License:
* Copyright (c) 2008 Bjoern Hartmann
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* bjoern@cs.stanford.edu 12/30/2008
*/
#ifndef _NETWORKUDP_H_
#define _NETWORKUDP_H_
#include <Arduino.h>
#include <Udp.h>
#include <cbuf.h>
class NetworkUDP : public UDP {
private:
int udp_server;
IPAddress multicast_ip;
IPAddress remote_ip;
uint16_t server_port;
uint16_t remote_port;
char * tx_buffer;
size_t tx_buffer_len;
cbuf * rx_buffer;
public:
NetworkUDP();
~NetworkUDP();
uint8_t begin(IPAddress a, uint16_t p);
uint8_t begin(uint16_t p);
uint8_t beginMulticast(IPAddress a, uint16_t p);
void stop();
int beginMulticastPacket();
int beginPacket();
int beginPacket(IPAddress ip, uint16_t port);
int beginPacket(const char *host, uint16_t port);
int endPacket();
size_t write(uint8_t);
size_t write(const uint8_t *buffer, size_t size);
int parsePacket();
int available();
int read();
int read(unsigned char* buffer, size_t len);
int read(char* buffer, size_t len);
int peek();
void flush();
IPAddress remoteIP();
uint16_t remotePort();
};
#endif /* _NETWORKUDP_H_ */

View file

@ -1,9 +1,9 @@
WiFiClientSecure NetworkClientSecure
================ ================
The WiFiClientSecure class implements support for secure connections using TLS (SSL). The NetworkClientSecure class implements support for secure connections using TLS (SSL).
It inherits from WiFiClient and thus implements a superset of that class' interface. It inherits from NetworkClient and thus implements a superset of that class' interface.
There are three ways to establish a secure connection using the WiFiClientSecure class: There are three ways to establish a secure connection using the NetworkClientSecure class:
using a root certificate authority (CA) cert, using a root CA cert plus a client cert and key, using a root certificate authority (CA) cert, using a root CA cert plus a client cert and key,
and using a pre-shared key (PSK). and using a pre-shared key (PSK).
@ -19,12 +19,12 @@ If you are accessing your own server:
If you are accessing a public server: If you are accessing a public server:
- Obtain the cert of the public CA that signed that server's cert - Obtain the cert of the public CA that signed that server's cert
Then: Then:
- In WiFiClientSecure use setCACert (or the appropriate connect method) to set the root cert of your - In NetworkClientSecure use setCACert (or the appropriate connect method) to set the root cert of your
CA or of the public CA CA or of the public CA
- When WiFiClientSecure connects to the target server it uses the CA cert to verify the certificate - When NetworkClientSecure connects to the target server it uses the CA cert to verify the certificate
presented by the server, and then negotiates encryption for the connection presented by the server, and then negotiates encryption for the connection
Please see the WiFiClientSecure example. Please see the NetworkClientSecure example.
Using a bundle of root certificate authority certificates Using a bundle of root certificate authority certificates
--------------------------------------------------------- ---------------------------------------------------------
@ -60,11 +60,11 @@ the client to the server, then negotiates an encrypted connection.
- Follow steps above - Follow steps above
- Using your root CA generate cert/key for your client - Using your root CA generate cert/key for your client
- Register the keys with the server you will be accessing so the server can authenticate your client - Register the keys with the server you will be accessing so the server can authenticate your client
- In WiFiClientSecure use setCACert (or the appropriate connect method) to set the root cert of your - In NetworkClientSecure use setCACert (or the appropriate connect method) to set the root cert of your
CA or of the public CA, this is used to authenticate the server CA or of the public CA, this is used to authenticate the server
- In WiFiClientSecure use setCertificate, and setPrivateKey (or the appropriate connect method) to - In NetworkClientSecure use setCertificate, and setPrivateKey (or the appropriate connect method) to
set your client's cert & key, this will be used to authenticate your client to the server set your client's cert & key, this will be used to authenticate your client to the server
- When WiFiClientSecure connects to the target server it uses the CA cert to verify the certificate - When NetworkClientSecure connects to the target server it uses the CA cert to verify the certificate
presented by the server, it will use the cert/key to authenticate your client to the server, and presented by the server, it will use the cert/key to authenticate your client to the server, and
it will then negotiate encryption for the connection it will then negotiate encryption for the connection
@ -85,13 +85,13 @@ malicious server does not divulge the password. Plus the server is also authenti
To use PSK: To use PSK:
- Generate a random hex string (generating an MD5 or SHA for some file is one way to do this) - Generate a random hex string (generating an MD5 or SHA for some file is one way to do this)
- Come up with a string id for your client and configure your server to accept the id/key pair - Come up with a string id for your client and configure your server to accept the id/key pair
- In WiFiClientSecure use setPreSharedKey (or the appropriate connect method) to - In NetworkClientSecure use setPreSharedKey (or the appropriate connect method) to
set the id/key combo set the id/key combo
- When WiFiClientSecure connects to the target server it uses the id/key combo to authenticate the - When NetworkClientSecure connects to the target server it uses the id/key combo to authenticate the
server (it must prove that it has the key too), authenticate the client and then negotiate server (it must prove that it has the key too), authenticate the client and then negotiate
encryption for the connection encryption for the connection
Please see the WiFiClientPSK example. Please see the NetworkClientPSK example.
Specifying the ALPN Protocol Specifying the ALPN Protocol
---------------------------- ----------------------------
@ -110,23 +110,23 @@ wiFiClient.setAlpnProtocols(aws_protos);
Examples Examples
-------- --------
#### WiFiClientInsecure #### NetworkClientInsecure
Demonstrates usage of insecure connection using `WiFiClientSecure::setInsecure()` Demonstrates usage of insecure connection using `NetworkClientSecure::setInsecure()`
#### WiFiClientPSK #### NetworkClientPSK
Wifi secure connection example for ESP32 using a pre-shared key (PSK) Wifi secure connection example for ESP32 using a pre-shared key (PSK)
This is useful with MQTT servers instead of using a self-signed cert, tested with mosquitto. This is useful with MQTT servers instead of using a self-signed cert, tested with mosquitto.
Running on TLS 1.2 using mbedTLS Running on TLS 1.2 using mbedTLS
#### WiFiClientSecure #### NetworkClientSecure
Wifi secure connection example for ESP32 Wifi secure connection example for ESP32
Running on TLS 1.2 using mbedTLS Running on TLS 1.2 using mbedTLS
#### WiFiClientSecureEnterprise #### NetworkClientSecureEnterprise
This example demonstrates a secure connection to a WiFi network using WPA/WPA2 Enterprise (for example eduroam), This example demonstrates a secure connection to a WiFi network using WPA/WPA2 Enterprise (for example eduroam),
and establishing a secure HTTPS connection with an external server (for example arduino.php5.sk) using the defined anonymous identity, user identity, and password. and establishing a secure HTTPS connection with an external server (for example arduino.php5.sk) using the defined anonymous identity, user identity, and password.
.. note:: .. note::
This example is outdated and might not work. For more examples see [https://github.com/martinius96/ESP32-eduroam](https://github.com/martinius96/ESP32-eduroam) This example is outdated and might not work. For more examples see [https://github.com/martinius96/ESP32-eduroam](https://github.com/martinius96/ESP32-eduroam)
#### WiFiClientShowPeerCredentials #### NetworkClientShowPeerCredentials
Example of a establishing a secure connection and then showing the fingerprint of the certificate. Example of a establishing a secure connection and then showing the fingerprint of the certificate.
This can be useful in an IoT setting to know for sure that you are connecting to the right server. This can be useful in an IoT setting to know for sure that you are connecting to the right server.
Especially in situations where you cannot hardcode a trusted root certificate for long Especially in situations where you cannot hardcode a trusted root certificate for long

View file

@ -1,10 +1,11 @@
#include <WiFiClientSecure.h> #include <NetworkClientSecure.h>
#include <WiFi.h>
/* This is a very INSECURE approach. /* This is a very INSECURE approach.
* If for some reason the secure, proper example WiFiClientSecure * If for some reason the secure, proper example NetworkClientSecure
* does not work for you; then you may want to check the * does not work for you; then you may want to check the
* WiFiClientTrustOnFirstUse example first. It is less secure than * NetworkClientTrustOnFirstUse example first. It is less secure than
* WiFiClientSecure, but a lot better than this totally insecure * NetworkClientSecure, but a lot better than this totally insecure
* approach shown below. * approach shown below.
*/ */
@ -13,7 +14,7 @@ const char* password = "your-password"; // your network password
const char* server = "www.howsmyssl.com"; // Server URL const char* server = "www.howsmyssl.com"; // Server URL
WiFiClientSecure client; NetworkClientSecure client;
void setup() { void setup() {
//Initialize serial and wait for port to open: //Initialize serial and wait for port to open:

View file

@ -10,7 +10,8 @@
2018 - Adapted for PSK by Thorsten von Eicken 2018 - Adapted for PSK by Thorsten von Eicken
*/ */
#include <WiFiClientSecure.h> #include <NetworkClientSecure.h>
#include <WiFi.h>
#if 0 #if 0
const char* ssid = "your-ssid"; // your network SSID (name of wifi network) const char* ssid = "your-ssid"; // your network SSID (name of wifi network)
@ -27,7 +28,7 @@ const int port = 8443; // server's port (8883 for MQTT)
const char* pskIdent = "Client_identity"; // PSK identity (sometimes called key hint) const char* pskIdent = "Client_identity"; // PSK identity (sometimes called key hint)
const char* psKey = "1a2b3c4d"; // PSK Key (must be hex string without 0x) const char* psKey = "1a2b3c4d"; // PSK Key (must be hex string without 0x)
WiFiClientSecure client; NetworkClientSecure client;
void setup() { void setup() {
//Initialize serial and wait for port to open: //Initialize serial and wait for port to open:

View file

@ -6,7 +6,8 @@
2017 - Evandro Copercini - Apache 2.0 License. 2017 - Evandro Copercini - Apache 2.0 License.
*/ */
#include <WiFiClientSecure.h> #include <NetworkClientSecure.h>
#include <WiFi.h>
const char* ssid = "your-ssid"; // your network SSID (name of wifi network) const char* ssid = "your-ssid"; // your network SSID (name of wifi network)
const char* password = "your-password"; // your network password const char* password = "your-password"; // your network password
@ -44,7 +45,7 @@ const char* test_root_ca= \
//const char* test_client_cert = ""; //to verify the client //const char* test_client_cert = ""; //to verify the client
WiFiClientSecure client; NetworkClientSecure client;
void setup() { void setup() {
//Initialize serial and wait for port to open: //Initialize serial and wait for port to open:

View file

@ -14,7 +14,7 @@
// For more examples see https://github.com/martinius96/ESP32-eduroam // For more examples see https://github.com/martinius96/ESP32-eduroam
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClientSecure.h> #include <NetworkClientSecure.h>
#if __has_include ("esp_eap_client.h") #if __has_include ("esp_eap_client.h")
#include "esp_eap_client.h" #include "esp_eap_client.h"
#else #else
@ -59,7 +59,7 @@ const char* test_root_ca = \
// You can use x.509 client certificates if you want // You can use x.509 client certificates if you want
//const char* test_client_key = ""; //to verify the client //const char* test_client_key = ""; //to verify the client
//const char* test_client_cert = ""; //to verify the client //const char* test_client_cert = ""; //to verify the client
WiFiClientSecure client; NetworkClientSecure client;
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
delay(10); delay(10);

View file

@ -18,11 +18,11 @@
8. server now tells the client what (else) is supported; such as additional authentication options. 8. server now tells the client what (else) is supported; such as additional authentication options.
... conversation continues encrypted. ... conversation continues encrypted.
This can be enabled in WiFiClientSecure by telling it to start in plaintext: This can be enabled in NetworkClientSecure by telling it to start in plaintext:
client.setPlainStart(); client.setPlainStart();
and client is than a plain, TCP, connection (just as WiFiClient would be); until the client calls and client is than a plain, TCP, connection (just as NetworkClient would be); until the client calls
the method: the method:
client.startTLS(); // returns zero on error; non zero on success. client.startTLS(); // returns zero on error; non zero on success.
@ -30,7 +30,8 @@
After which things switch to TLS/SSL. After which things switch to TLS/SSL.
*/ */
#include <WiFiClientSecure.h> #include <WiFi.h>
#include <NetworkClientSecure.h>
#ifndef WIFI_NETWORK #ifndef WIFI_NETWORK
#define WIFI_NETWORK "YOUR Wifi SSID" #define WIFI_NETWORK "YOUR Wifi SSID"
@ -53,7 +54,7 @@ const char* password = WIFI_PASSWD; // your network password
const char* server = SMTP_HOST; // Server URL const char* server = SMTP_HOST; // Server URL
const int submission_port = SMTP_PORT; // submission port. const int submission_port = SMTP_PORT; // submission port.
WiFiClientSecure client; NetworkClientSecure client;
static bool readAllSMTPLines(); static bool readAllSMTPLines();
@ -138,7 +139,7 @@ static bool readAllSMTPLines() {
int i; int i;
// blocking read; we cannot rely on a timeout // blocking read; we cannot rely on a timeout
// of a WiFiClientSecure read; as it is non // of a NetworkClientSecure read; as it is non
// blocking. // blocking.
const unsigned long timeout = 15 * 1000; const unsigned long timeout = 15 * 1000;
unsigned long start = millis(); // the timeout is for the entire CMD block response; not per character/line. unsigned long start = millis(); // the timeout is for the entire CMD block response; not per character/line.

View file

@ -1,4 +1,4 @@
// WiFiClientShowPeerCredentials // NetworkClientShowPeerCredentials
// //
// Example of a establishing a secure connection and then // Example of a establishing a secure connection and then
// showing the fingerprint of the certificate. This can // showing the fingerprint of the certificate. This can
@ -12,7 +12,7 @@
#include <WiFi.h> #include <WiFi.h>
#include <HTTPClient.h> #include <HTTPClient.h>
#include <WiFiClientSecure.h> #include <NetworkClientSecure.h>
#ifndef WIFI_NETWORK #ifndef WIFI_NETWORK
#define WIFI_NETWORK "MyWifiNetwork" #define WIFI_NETWORK "MyWifiNetwork"
@ -25,7 +25,7 @@
#define URL "https://arduino.cc" #define URL "https://arduino.cc"
void demo() { void demo() {
WiFiClientSecure *client = new WiFiClientSecure; NetworkClientSecure *client = new NetworkClientSecure;
client->setInsecure(); // client->setInsecure(); //
HTTPClient https; HTTPClient https;

View file

@ -54,7 +54,8 @@ const char* server = "www.howsmyssl.com"; // Server to test with.
const int TOFU_RESET_BUTTON = 35; /* Trust reset button wired between GPIO 35 and GND (pulldown) */ const int TOFU_RESET_BUTTON = 35; /* Trust reset button wired between GPIO 35 and GND (pulldown) */
#include <WiFiClientSecure.h> #include <WiFi.h>
#include <NetworkClientSecure.h>
#include <EEPROM.h> #include <EEPROM.h>
/* Set aside some persistant memory (i.e. memory that is preserved on reboots and /* Set aside some persistant memory (i.e. memory that is preserved on reboots and
@ -76,7 +77,7 @@ static void printSHA256(unsigned char * ptr) {
Serial.println(""); Serial.println("");
}; };
WiFiClientSecure client; NetworkClientSecure client;
bool get_tofu(); bool get_tofu();
bool doTOFU_Protected_Connection(uint8_t * fingerprint_tofu); bool doTOFU_Protected_Connection(uint8_t * fingerprint_tofu);

View file

@ -6,13 +6,13 @@
# Library (KEYWORD3) # Library (KEYWORD3)
####################################### #######################################
WiFiClientSecure KEYWORD3 NetworkClientSecure KEYWORD3
####################################### #######################################
# Datatypes (KEYWORD1) # Datatypes (KEYWORD1)
####################################### #######################################
WiFiClientSecure KEYWORD1 NetworkClientSecure KEYWORD1
####################################### #######################################
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)

View file

@ -1,4 +1,4 @@
name=WiFiClientSecure name=NetworkClientSecure
version=2.0.0 version=2.0.0
author=Evandro Luis Copercini author=Evandro Luis Copercini
maintainer=Github Community maintainer=Github Community

View file

@ -1,5 +1,5 @@
/* /*
WiFiClientSecure.cpp - Client Secure class for ESP32 NetworkClientSecure.cpp - Client Secure class for ESP32
Copyright (c) 2016 Hristo Gochkov All right reserved. Copyright (c) 2016 Hristo Gochkov All right reserved.
Additions Copyright (C) 2017 Evandro Luis Copercini. Additions Copyright (C) 2017 Evandro Luis Copercini.
@ -18,7 +18,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "WiFiClientSecure.h" #include "NetworkClientSecure.h"
#include "esp_crt_bundle.h" #include "esp_crt_bundle.h"
#include <lwip/sockets.h> #include <lwip/sockets.h>
#include <lwip/netdb.h> #include <lwip/netdb.h>
@ -29,7 +29,7 @@
#undef read #undef read
WiFiClientSecure::WiFiClientSecure() NetworkClientSecure::NetworkClientSecure()
{ {
_connected = false; _connected = false;
_timeout = 30000; // Same default as ssl_client _timeout = 30000; // Same default as ssl_client
@ -50,7 +50,7 @@ WiFiClientSecure::WiFiClientSecure()
} }
WiFiClientSecure::WiFiClientSecure(int sock) NetworkClientSecure::NetworkClientSecure(int sock)
{ {
_connected = false; _connected = false;
_timeout = 30000; // Same default as ssl_client _timeout = 30000; // Same default as ssl_client
@ -75,13 +75,13 @@ WiFiClientSecure::WiFiClientSecure(int sock)
_alpn_protos = NULL; _alpn_protos = NULL;
} }
WiFiClientSecure::~WiFiClientSecure() NetworkClientSecure::~NetworkClientSecure()
{ {
stop(); stop();
delete sslclient; delete sslclient;
} }
WiFiClientSecure &WiFiClientSecure::operator=(const WiFiClientSecure &other) NetworkClientSecure &NetworkClientSecure::operator=(const NetworkClientSecure &other)
{ {
stop(); stop();
sslclient->socket = other.sslclient->socket; sslclient->socket = other.sslclient->socket;
@ -89,7 +89,7 @@ WiFiClientSecure &WiFiClientSecure::operator=(const WiFiClientSecure &other)
return *this; return *this;
} }
void WiFiClientSecure::stop() void NetworkClientSecure::stop()
{ {
stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key); stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key);
@ -99,45 +99,45 @@ void WiFiClientSecure::stop()
_lastWriteTimeout = 0; _lastWriteTimeout = 0;
} }
int WiFiClientSecure::connect(IPAddress ip, uint16_t port) int NetworkClientSecure::connect(IPAddress ip, uint16_t port)
{ {
if (_pskIdent && _psKey) if (_pskIdent && _psKey)
return connect(ip, port, _pskIdent, _psKey); return connect(ip, port, _pskIdent, _psKey);
return connect(ip, port, _CA_cert, _cert, _private_key); return connect(ip, port, _CA_cert, _cert, _private_key);
} }
int WiFiClientSecure::connect(IPAddress ip, uint16_t port, int32_t timeout){ int NetworkClientSecure::connect(IPAddress ip, uint16_t port, int32_t timeout){
_timeout = timeout; _timeout = timeout;
return connect(ip, port); return connect(ip, port);
} }
int WiFiClientSecure::connect(const char *host, uint16_t port) int NetworkClientSecure::connect(const char *host, uint16_t port)
{ {
if (_pskIdent && _psKey) if (_pskIdent && _psKey)
return connect(host, port, _pskIdent, _psKey); return connect(host, port, _pskIdent, _psKey);
return connect(host, port, _CA_cert, _cert, _private_key); return connect(host, port, _CA_cert, _cert, _private_key);
} }
int WiFiClientSecure::connect(const char *host, uint16_t port, int32_t timeout){ int NetworkClientSecure::connect(const char *host, uint16_t port, int32_t timeout){
_timeout = timeout; _timeout = timeout;
return connect(host, port); return connect(host, port);
} }
int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *CA_cert, const char *cert, const char *private_key) int NetworkClientSecure::connect(IPAddress ip, uint16_t port, const char *CA_cert, const char *cert, const char *private_key)
{ {
return connect(ip, port, NULL, CA_cert, cert, private_key); return connect(ip, port, NULL, CA_cert, cert, private_key);
} }
int WiFiClientSecure::connect(const char *host, uint16_t port, const char *CA_cert, const char *cert, const char *private_key) int NetworkClientSecure::connect(const char *host, uint16_t port, const char *CA_cert, const char *cert, const char *private_key)
{ {
IPAddress address; IPAddress address;
if (!WiFi.hostByName(host, address)) if (!Network.hostByName(host, address))
return 0; return 0;
return connect(address, port, host, CA_cert, cert, private_key); return connect(address, port, host, CA_cert, cert, private_key);
} }
int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *host, const char *CA_cert, const char *cert, const char *private_key) int NetworkClientSecure::connect(IPAddress ip, uint16_t port, const char *host, const char *CA_cert, const char *cert, const char *private_key)
{ {
int ret = start_ssl_client(sslclient, ip, port, host, _timeout, CA_cert, _use_ca_bundle, cert, private_key, NULL, NULL, _use_insecure, _alpn_protos); int ret = start_ssl_client(sslclient, ip, port, host, _timeout, CA_cert, _use_ca_bundle, cert, private_key, NULL, NULL, _use_insecure, _alpn_protos);
@ -157,7 +157,7 @@ int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *host, con
return 1; return 1;
} }
int WiFiClientSecure::startTLS() int NetworkClientSecure::startTLS()
{ {
int ret = 1; int ret = 1;
if (_stillinPlainStart) { if (_stillinPlainStart) {
@ -174,15 +174,15 @@ int WiFiClientSecure::startTLS()
return 1; return 1;
} }
int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey) { int NetworkClientSecure::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey) {
return connect(ip.toString().c_str(), port, pskIdent, psKey); return connect(ip.toString().c_str(), port, pskIdent, psKey);
} }
int WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) { int NetworkClientSecure::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) {
log_v("start_ssl_client with PSK"); log_v("start_ssl_client with PSK");
IPAddress address; IPAddress address;
if (!WiFi.hostByName(host, address)) if (!Network.hostByName(host, address))
return 0; return 0;
int ret = start_ssl_client(sslclient, address, port, host, _timeout, NULL, false, NULL, NULL, pskIdent, psKey, _use_insecure, _alpn_protos); int ret = start_ssl_client(sslclient, address, port, host, _timeout, NULL, false, NULL, NULL, pskIdent, psKey, _use_insecure, _alpn_protos);
@ -196,7 +196,7 @@ int WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskId
return 1; return 1;
} }
int WiFiClientSecure::peek(){ int NetworkClientSecure::peek(){
if(_peek >= 0){ if(_peek >= 0){
return _peek; return _peek;
} }
@ -204,19 +204,19 @@ int WiFiClientSecure::peek(){
return _peek; return _peek;
} }
size_t WiFiClientSecure::write(uint8_t data) size_t NetworkClientSecure::write(uint8_t data)
{ {
return write(&data, 1); return write(&data, 1);
} }
int WiFiClientSecure::read() int NetworkClientSecure::read()
{ {
uint8_t data = -1; uint8_t data = -1;
int res = read(&data, 1); int res = read(&data, 1);
return res < 0 ? res: data; return res < 0 ? res: data;
} }
size_t WiFiClientSecure::write(const uint8_t *buf, size_t size) size_t NetworkClientSecure::write(const uint8_t *buf, size_t size)
{ {
if (!_connected) { if (!_connected) {
return 0; return 0;
@ -243,7 +243,7 @@ size_t WiFiClientSecure::write(const uint8_t *buf, size_t size)
return res; return res;
} }
int WiFiClientSecure::read(uint8_t *buf, size_t size) int NetworkClientSecure::read(uint8_t *buf, size_t size)
{ {
if(_stillinPlainStart) if(_stillinPlainStart)
return get_net_receive(sslclient, buf, size); return get_net_receive(sslclient, buf, size);
@ -289,7 +289,7 @@ int WiFiClientSecure::read(uint8_t *buf, size_t size)
return res + peeked; return res + peeked;
} }
int WiFiClientSecure::available() int NetworkClientSecure::available()
{ {
if (_stillinPlainStart) if (_stillinPlainStart)
return peek_net_receive(sslclient,0); return peek_net_receive(sslclient,0);
@ -308,7 +308,7 @@ int WiFiClientSecure::available()
return res+peeked; return res+peeked;
} }
uint8_t WiFiClientSecure::connected() uint8_t NetworkClientSecure::connected()
{ {
uint8_t dummy = 0; uint8_t dummy = 0;
read(&dummy, 0); read(&dummy, 0);
@ -316,7 +316,7 @@ uint8_t WiFiClientSecure::connected()
return _connected; return _connected;
} }
void WiFiClientSecure::setInsecure() void NetworkClientSecure::setInsecure()
{ {
_CA_cert = NULL; _CA_cert = NULL;
_cert = NULL; _cert = NULL;
@ -326,13 +326,13 @@ void WiFiClientSecure::setInsecure()
_use_insecure = true; _use_insecure = true;
} }
void WiFiClientSecure::setCACert (const char *rootCA) void NetworkClientSecure::setCACert (const char *rootCA)
{ {
_CA_cert = rootCA; _CA_cert = rootCA;
_use_insecure = false; _use_insecure = false;
} }
void WiFiClientSecure::setCACertBundle(const uint8_t * bundle) void NetworkClientSecure::setCACertBundle(const uint8_t * bundle)
{ {
if (bundle != NULL) if (bundle != NULL)
{ {
@ -344,22 +344,22 @@ void WiFiClientSecure::setCACert (const char *rootCA)
} }
} }
void WiFiClientSecure::setCertificate (const char *client_ca) void NetworkClientSecure::setCertificate (const char *client_ca)
{ {
_cert = client_ca; _cert = client_ca;
} }
void WiFiClientSecure::setPrivateKey (const char *private_key) void NetworkClientSecure::setPrivateKey (const char *private_key)
{ {
_private_key = private_key; _private_key = private_key;
} }
void WiFiClientSecure::setPreSharedKey(const char *pskIdent, const char *psKey) { void NetworkClientSecure::setPreSharedKey(const char *pskIdent, const char *psKey) {
_pskIdent = pskIdent; _pskIdent = pskIdent;
_psKey = psKey; _psKey = psKey;
} }
bool WiFiClientSecure::verify(const char* fp, const char* domain_name) bool NetworkClientSecure::verify(const char* fp, const char* domain_name)
{ {
if (!sslclient) if (!sslclient)
return false; return false;
@ -367,7 +367,7 @@ bool WiFiClientSecure::verify(const char* fp, const char* domain_name)
return verify_ssl_fingerprint(sslclient, fp, domain_name); return verify_ssl_fingerprint(sslclient, fp, domain_name);
} }
char *WiFiClientSecure::_streamLoad(Stream& stream, size_t size) { char *NetworkClientSecure::_streamLoad(Stream& stream, size_t size) {
char *dest = (char*)malloc(size+1); char *dest = (char*)malloc(size+1);
if (!dest) { if (!dest) {
return nullptr; return nullptr;
@ -381,7 +381,7 @@ char *WiFiClientSecure::_streamLoad(Stream& stream, size_t size) {
return dest; return dest;
} }
bool WiFiClientSecure::loadCACert(Stream& stream, size_t size) { bool NetworkClientSecure::loadCACert(Stream& stream, size_t size) {
if (_CA_cert != NULL) free(const_cast<char*>(_CA_cert)); if (_CA_cert != NULL) free(const_cast<char*>(_CA_cert));
char *dest = _streamLoad(stream, size); char *dest = _streamLoad(stream, size);
bool ret = false; bool ret = false;
@ -392,7 +392,7 @@ bool WiFiClientSecure::loadCACert(Stream& stream, size_t size) {
return ret; return ret;
} }
bool WiFiClientSecure::loadCertificate(Stream& stream, size_t size) { bool NetworkClientSecure::loadCertificate(Stream& stream, size_t size) {
if (_cert != NULL) free(const_cast<char*>(_cert)); if (_cert != NULL) free(const_cast<char*>(_cert));
char *dest = _streamLoad(stream, size); char *dest = _streamLoad(stream, size);
bool ret = false; bool ret = false;
@ -403,7 +403,7 @@ bool WiFiClientSecure::loadCertificate(Stream& stream, size_t size) {
return ret; return ret;
} }
bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size) { bool NetworkClientSecure::loadPrivateKey(Stream& stream, size_t size) {
if (_private_key != NULL) free(const_cast<char*>(_private_key)); if (_private_key != NULL) free(const_cast<char*>(_private_key));
char *dest = _streamLoad(stream, size); char *dest = _streamLoad(stream, size);
bool ret = false; bool ret = false;
@ -414,7 +414,7 @@ bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size) {
return ret; return ret;
} }
int WiFiClientSecure::lastError(char *buf, const size_t size) int NetworkClientSecure::lastError(char *buf, const size_t size)
{ {
if (!_lastError) { if (!_lastError) {
return 0; return 0;
@ -423,17 +423,17 @@ int WiFiClientSecure::lastError(char *buf, const size_t size)
return _lastError; return _lastError;
} }
void WiFiClientSecure::setHandshakeTimeout(unsigned long handshake_timeout) void NetworkClientSecure::setHandshakeTimeout(unsigned long handshake_timeout)
{ {
sslclient->handshake_timeout = handshake_timeout * 1000; sslclient->handshake_timeout = handshake_timeout * 1000;
} }
void WiFiClientSecure::setAlpnProtocols(const char **alpn_protos) void NetworkClientSecure::setAlpnProtocols(const char **alpn_protos)
{ {
_alpn_protos = alpn_protos; _alpn_protos = alpn_protos;
} }
int WiFiClientSecure::fd() const int NetworkClientSecure::fd() const
{ {
return sslclient->socket; return sslclient->socket;
} }

View file

@ -1,5 +1,5 @@
/* /*
WiFiClientSecure.h - Base class that provides Client SSL to ESP32 NetworkClientSecure.h - Base class that provides Client SSL to ESP32
Copyright (c) 2011 Adrian McEwen. All right reserved. Copyright (c) 2011 Adrian McEwen. All right reserved.
Additions Copyright (C) 2017 Evandro Luis Copercini. Additions Copyright (C) 2017 Evandro Luis Copercini.
@ -18,14 +18,14 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef WiFiClientSecure_h #ifndef NetworkClientSecure_h
#define WiFiClientSecure_h #define NetworkClientSecure_h
#include "Arduino.h" #include "Arduino.h"
#include "IPAddress.h" #include "IPAddress.h"
#include <WiFi.h> #include "Network.h"
#include "ssl_client.h" #include "ssl_client.h"
class WiFiClientSecure : public WiFiClient class NetworkClientSecure : public NetworkClient
{ {
protected: protected:
sslclient_context *sslclient; sslclient_context *sslclient;
@ -44,10 +44,10 @@ protected:
bool _use_ca_bundle; bool _use_ca_bundle;
public: public:
WiFiClientSecure *next; NetworkClientSecure *next;
WiFiClientSecure(); NetworkClientSecure();
WiFiClientSecure(int socket); NetworkClientSecure(int socket);
~WiFiClientSecure(); ~NetworkClientSecure();
int connect(IPAddress ip, uint16_t port); int connect(IPAddress ip, uint16_t port);
int connect(IPAddress ip, uint16_t port, int32_t timeout); int connect(IPAddress ip, uint16_t port, int32_t timeout);
int connect(const char *host, uint16_t port); int connect(const char *host, uint16_t port);
@ -98,7 +98,7 @@ public:
{ {
return connected(); return connected();
} }
WiFiClientSecure &operator=(const WiFiClientSecure &other); NetworkClientSecure &operator=(const NetworkClientSecure &other);
bool operator==(const bool value) bool operator==(const bool value)
{ {
return bool() == value; return bool() == value;
@ -107,8 +107,8 @@ public:
{ {
return bool() != value; return bool() != value;
} }
bool operator==(const WiFiClientSecure &); bool operator==(const NetworkClientSecure &);
bool operator!=(const WiFiClientSecure &rhs) bool operator!=(const NetworkClientSecure &rhs)
{ {
return !this->operator==(rhs); return !this->operator==(rhs);
}; };
@ -121,7 +121,7 @@ public:
private: private:
char *_streamLoad(Stream& stream, size_t size); char *_streamLoad(Stream& stream, size_t size);
//friend class WiFiServer; //friend class NetworkServer;
using Print::write; using Print::write;
}; };

View file

@ -0,0 +1,3 @@
#pragma once
#include "NetworkClientSecure.h"
#define WiFiClientSecure NetworkClientSecure

View file

@ -18,7 +18,6 @@
#include <string> #include <string>
#include "ssl_client.h" #include "ssl_client.h"
#include "esp_crt_bundle.h" #include "esp_crt_bundle.h"
#include "WiFi.h"
#if !defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && !defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) #if !defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && !defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
# warning "Please call `idf.py menuconfig` then go to Component config -> mbedTLS -> TLS Key Exchange Methods -> Enable pre-shared-key ciphersuites and then check `Enable PSK based cyphersuite modes`. Save and Quit." # warning "Please call `idf.py menuconfig` then go to Component config -> mbedTLS -> TLS Key Exchange Methods -> Enable pre-shared-key ciphersuites and then check `Enable PSK based cyphersuite modes`. Save and Quit."

View file

@ -53,7 +53,7 @@ arduino-esp32 includes libraries for Arduino compatibility along with some objec
Filesystem virtualization framework Filesystem virtualization framework
### HTTPClient ### HTTPClient
A simple HTTP client, compatible with WiFiClientSecure A simple HTTP client, compatible with NetworkClientSecure
### HTTPUpdate ### HTTPUpdate
Download a firmware update from HTTPd and apply it using Update Download a firmware update from HTTPd and apply it using Update
@ -103,7 +103,7 @@ arduino-esp32 includes libraries for Arduino compatibility along with some objec
### WiFi ### WiFi
Arduino compatible WiFi driver (includes Ethernet driver) Arduino compatible WiFi driver (includes Ethernet driver)
### WiFiClientSecure ### NetworkClientSecure
Arduino compatible WiFi client object using embedded encryption Arduino compatible WiFi client object using embedded encryption
### Wire ### Wire

View file

@ -22,7 +22,7 @@
#include <WiFi.h> #include <WiFi.h>
#include <Update.h> #include <Update.h>
WiFiClient client; NetworkClient client;
// Variables to validate // Variables to validate
// response from S3 // response from S3

View file

@ -48,7 +48,7 @@ espsecure.py encrypt_flash_data = runs the idf encryption function to make a en
#include <Arduino.h> #include <Arduino.h>
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <HTTPClient.h> #include <HTTPClient.h>
#include <Update.h> #include <Update.h>
@ -150,7 +150,7 @@ bool http_downloadUpdate(HTTPClient& http, uint32_t size=0) {
if(size == 0){ if(size == 0){
return false; return false;
} }
WiFiClient *client = http.getStreamPtr(); NetworkClient *client = http.getStreamPtr();
if( !Update.begin(size, U_FLASH) ) { if( !Update.begin(size, U_FLASH) ) {
Serial.printf("Update.begin failed! (%s)\n", Update.errorString() ); Serial.printf("Update.begin failed! (%s)\n", Update.errorString() );
@ -207,7 +207,7 @@ bool http_updater(const String& host, const uint16_t& port, String uri, const bo
//setup HTTPclient to be ready to connect & send a request to HTTP server //setup HTTPclient to be ready to connect & send a request to HTTP server
HTTPClient http; HTTPClient http;
WiFiClient client; NetworkClient client;
uri.concat(query); //GET query added to end of uri path uri.concat(query); //GET query added to end of uri path
if( !http.begin(client, host, port, uri) ){ if( !http.begin(client, host, port, uri) ){
return false; //httpclient setup error return false; //httpclient setup error
@ -261,7 +261,7 @@ bool http_updater(const String& host, const uint16_t& port, String uri, const bo
bool http_direct(const String& host, const uint16_t& port, const String& uri, const char* user=NULL, const char* password=NULL) { bool http_direct(const String& host, const uint16_t& port, const String& uri, const char* user=NULL, const char* password=NULL) {
//setup HTTPclient to be ready to connect & send a request to HTTP server //setup HTTPclient to be ready to connect & send a request to HTTP server
HTTPClient http; HTTPClient http;
WiFiClient client; NetworkClient client;
if( !http.begin(client, host, port, uri) ){ if( !http.begin(client, host, port, uri) ){
return false; //httpclient setup error return false; //httpclient setup error
} }

View file

@ -35,7 +35,7 @@ espsecure.py encrypt_flash_data = runs the idf encryption function to make a en
*/ */
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <SPIFFS.h> #include <SPIFFS.h>
#include <Update.h> #include <Update.h>
#include <WebServer.h> #include <WebServer.h>

View file

@ -29,7 +29,7 @@
*/ */
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WebServer.h> #include <WebServer.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>

View file

@ -23,7 +23,7 @@
edit the page by going to http://esp32fs.local/edit edit the page by going to http://esp32fs.local/edit
*/ */
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WebServer.h> #include <WebServer.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>

View file

@ -1,5 +1,5 @@
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WebServer.h> #include <WebServer.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>

View file

@ -1,5 +1,5 @@
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WebServer.h> #include <WebServer.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>

View file

@ -3,10 +3,10 @@
This example tests support for multi-homed servers, i.e. a distinct web servers on distinct IP interface. This example tests support for multi-homed servers, i.e. a distinct web servers on distinct IP interface.
It only tests the case n=2 because on a basic ESP32 device, we only have two IP interfaces, namely the WiFi station interfaces and the WiFi soft AP interface. It only tests the case n=2 because on a basic ESP32 device, we only have two IP interfaces, namely the WiFi station interfaces and the WiFi soft AP interface.
For this to work, the WebServer and the WiFiServer classes must correctly handle the case where an IP address is passed to their relevant constructor. For this to work, the WebServer and the NetworkServer classes must correctly handle the case where an IP address is passed to their relevant constructor.
It also requires WebServer to work with multiple, simultaneous instances. It also requires WebServer to work with multiple, simultaneous instances.
Testing the WebServer and the WiFiServer constructors was the primary purpose of this script. Testing the WebServer and the NetworkServer constructors was the primary purpose of this script.
The part of WebServer used by this sketch does seem to work with multiple, simultaneous instances. The part of WebServer used by this sketch does seem to work with multiple, simultaneous instances.
However there is much functionality in WebServer that is not tested here. It may all be well, but that is not proven here. However there is much functionality in WebServer that is not tested here. It may all be well, but that is not proven here.

View file

@ -1,5 +1,5 @@
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WebServer.h> #include <WebServer.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>

View file

@ -30,7 +30,7 @@
*/ */
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WebServer.h> #include <WebServer.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>
#include <SPI.h> #include <SPI.h>

View file

@ -1,5 +1,5 @@
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WebServer.h> #include <WebServer.h>
const char* ssid = "........"; const char* ssid = "........";

View file

@ -48,7 +48,7 @@ How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espress
The WebServer library offers a simple path to implement a web server on a ESP32 based board. The WebServer library offers a simple path to implement a web server on a ESP32 based board.
The advantage on using the WebServer instead of the plain simple WiFiServer is that the WebServer The advantage on using the WebServer instead of the plain simple NetworkServer is that the WebServer
takes much care about the http protocol conventions and features and allows easily access to parameters. takes much care about the http protocol conventions and features and allows easily access to parameters.
It offers plug-in capabilities by registering specific functionalities that will be outlined below. It offers plug-in capabilities by registering specific functionalities that will be outlined below.

View file

@ -29,6 +29,7 @@
#include <Arduino.h> #include <Arduino.h>
#include <WebServer.h> #include <WebServer.h>
#include <WiFi.h>
#include "secrets.h" // add WLAN Credentials in here. #include "secrets.h" // add WLAN Credentials in here.

View file

@ -3,7 +3,7 @@
*/ */
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WebServer.h> #include <WebServer.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>
#include <Update.h> #include <Update.h>

View file

@ -21,8 +21,8 @@
#include <Arduino.h> #include <Arduino.h>
#include <esp32-hal-log.h> #include <esp32-hal-log.h>
#include "WiFiServer.h" #include "NetworkServer.h"
#include "WiFiClient.h" #include "NetworkClient.h"
#include "WebServer.h" #include "WebServer.h"
#include "detail/mimetable.h" #include "detail/mimetable.h"
@ -41,7 +41,7 @@ const char * _http_method_str[] = {
static const char Content_Type[] PROGMEM = "Content-Type"; static const char Content_Type[] PROGMEM = "Content-Type";
static const char filename[] PROGMEM = "filename"; static const char filename[] PROGMEM = "filename";
static char* readBytesWithTimeout(WiFiClient& client, size_t maxLength, size_t& dataLength, int timeout_ms) static char* readBytesWithTimeout(NetworkClient& client, size_t maxLength, size_t& dataLength, int timeout_ms)
{ {
char *buf = nullptr; char *buf = nullptr;
dataLength = 0; dataLength = 0;
@ -73,7 +73,7 @@ static char* readBytesWithTimeout(WiFiClient& client, size_t maxLength, size_t&
return buf; return buf;
} }
bool WebServer::_parseRequest(WiFiClient& client) { bool WebServer::_parseRequest(NetworkClient& client) {
// Read the first line of HTTP request // Read the first line of HTTP request
String req = client.readStringUntil('\r'); String req = client.readStringUntil('\r');
client.readStringUntil('\n'); client.readStringUntil('\n');
@ -309,7 +309,7 @@ void WebServer::_uploadWriteByte(uint8_t b){
_currentUpload->buf[_currentUpload->currentSize++] = b; _currentUpload->buf[_currentUpload->currentSize++] = b;
} }
int WebServer::_uploadReadByte(WiFiClient& client) { int WebServer::_uploadReadByte(NetworkClient& client) {
int res = client.read(); int res = client.read();
if (res < 0) { if (res < 0) {
@ -322,7 +322,7 @@ int WebServer::_uploadReadByte(WiFiClient& client) {
return res; return res;
} }
bool WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t len){ bool WebServer::_parseForm(NetworkClient& client, String boundary, uint32_t len){
(void) len; (void) len;
log_v("Parse Form: Boundary: %s Length: %d", boundary.c_str(), len); log_v("Parse Form: Boundary: %s Length: %d", boundary.c_str(), len);
String line; String line;

View file

@ -26,8 +26,8 @@
#include <libb64/cdecode.h> #include <libb64/cdecode.h>
#include <libb64/cencode.h> #include <libb64/cencode.h>
#include "esp_random.h" #include "esp_random.h"
#include "WiFiServer.h" #include "NetworkServer.h"
#include "WiFiClient.h" #include "NetworkClient.h"
#include "WebServer.h" #include "WebServer.h"
#include "FS.h" #include "FS.h"
#include "detail/RequestHandlersImpl.h" #include "detail/RequestHandlersImpl.h"
@ -435,7 +435,7 @@ void WebServer::handleClient() {
} }
if (!keepCurrentClient) { if (!keepCurrentClient) {
_currentClient = WiFiClient(); _currentClient = NetworkClient();
_currentStatus = HC_NONE; _currentStatus = HC_NONE;
_currentUpload.reset(); _currentUpload.reset();
} }

View file

@ -26,8 +26,8 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <WiFi.h> #include "FS.h"
#include <FS.h> #include "Network.h"
#include "HTTP_Method.h" #include "HTTP_Method.h"
#include "Uri.h" #include "Uri.h"
@ -126,7 +126,7 @@ public:
String uri() { return _currentUri; } String uri() { return _currentUri; }
HTTPMethod method() { return _currentMethod; } HTTPMethod method() { return _currentMethod; }
virtual WiFiClient & client() { return _currentClient; } virtual NetworkClient & client() { return _currentClient; }
HTTPUpload& upload() { return *_currentUpload; } HTTPUpload& upload() { return *_currentUpload; }
String pathArg(unsigned int i); // get request path argument by number String pathArg(unsigned int i); // get request path argument by number
@ -188,13 +188,13 @@ protected:
void _addRequestHandler(RequestHandler* handler); void _addRequestHandler(RequestHandler* handler);
void _handleRequest(); void _handleRequest();
void _finalizeResponse(); void _finalizeResponse();
bool _parseRequest(WiFiClient& client); bool _parseRequest(NetworkClient& client);
void _parseArguments(String data); void _parseArguments(String data);
static String _responseCodeToString(int code); static String _responseCodeToString(int code);
bool _parseForm(WiFiClient& client, String boundary, uint32_t len); bool _parseForm(NetworkClient& client, String boundary, uint32_t len);
bool _parseFormUploadAborted(); bool _parseFormUploadAborted();
void _uploadWriteByte(uint8_t b); void _uploadWriteByte(uint8_t b);
int _uploadReadByte(WiFiClient& client); int _uploadReadByte(NetworkClient& client);
void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength); void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength);
bool _collectHeader(const char* headerName, const char* headerValue); bool _collectHeader(const char* headerName, const char* headerValue);
@ -210,9 +210,9 @@ protected:
}; };
boolean _corsEnabled; boolean _corsEnabled;
WiFiServer _server; NetworkServer _server;
WiFiClient _currentClient; NetworkClient _currentClient;
HTTPMethod _currentMethod; HTTPMethod _currentMethod;
String _currentUri; String _currentUri;
uint8_t _currentVersion; uint8_t _currentVersion;

View file

@ -30,7 +30,7 @@ ported for sparkfun esp32
const char* ssid = "yourssid"; const char* ssid = "yourssid";
const char* password = "yourpasswd"; const char* password = "yourpasswd";
WiFiServer server(80); NetworkServer server(80);
void setup() void setup()
{ {
@ -63,7 +63,7 @@ void setup()
} }
void loop(){ void loop(){
WiFiClient client = server.accept(); // listen for incoming clients NetworkClient client = server.accept(); // listen for incoming clients
if (client) { // if you get a client, if (client) { // if you get a client,
Serial.println("New Client."); // print a message out the serial port Serial.println("New Client."); // print a message out the serial port

View file

@ -12,7 +12,7 @@
*/ */
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClient.h> #include <NetworkClient.h>
#include <WiFiAP.h> #include <WiFiAP.h>
#ifndef LED_BUILTIN #ifndef LED_BUILTIN
@ -23,7 +23,7 @@
const char *ssid = "yourAP"; const char *ssid = "yourAP";
const char *password = "yourPassword"; const char *password = "yourPassword";
WiFiServer server(80); NetworkServer server(80);
void setup() { void setup() {
@ -48,7 +48,7 @@ void setup() {
} }
void loop() { void loop() {
WiFiClient client = server.accept(); // listen for incoming clients NetworkClient client = server.accept(); // listen for incoming clients
if (client) { // if you get a client, if (client) { // if you get a client,
Serial.println("New Client."); // print a message out the serial port Serial.println("New Client."); // print a message out the serial port

View file

@ -92,7 +92,7 @@ void WiFiEvent(WiFiEvent_t event){
break; break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP6: case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
Serial.print("STA IPv6: "); Serial.print("STA IPv6: ");
Serial.println(WiFi.localIPv6()); Serial.println(WiFi.linkLocalIPv6());
break; break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP: case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.print("STA IPv4: "); Serial.print("STA IPv4: ");

View file

@ -1,4 +1,4 @@
# WiFiClient # NetworkClient
This example demonstrates reading and writing data from and to a web service which can be used for logging data, creating insights and taking actions based on those data. This example demonstrates reading and writing data from and to a web service which can be used for logging data, creating insights and taking actions based on those data.
@ -126,7 +126,7 @@ ETag: W/"8e9c308fe2c50309f991586be1aff28d"
X-Frame-Options: SAMEORIGIN X-Frame-Options: SAMEORIGIN
1e3 1e3
{"channel":{"id":2005329,"name":"WiFiCLient example","description":"Default setup for Arduino ESP32 WiFiClient example","latitude":"0.0","longitude":"0.0","field1":"data0","created_at":"2023-01-11T15:56:08Z","updated_at":"2023-01-13T08:13:58Z","last_entry_id":2871},"feeds":[{"created_at":"2023-01-13T13:11:30Z","entry_id":2869,"field1":"359"},{"created_at":"2023-01-13T13:11:57Z","entry_id":2870,"field1":"361"},{"created_at":"2023-01-13T13:12:23Z","entry_id":2871,"field1":"363"}]} {"channel":{"id":2005329,"name":"WiFiCLient example","description":"Default setup for Arduino ESP32 NetworkClient example","latitude":"0.0","longitude":"0.0","field1":"data0","created_at":"2023-01-11T15:56:08Z","updated_at":"2023-01-13T08:13:58Z","last_entry_id":2871},"feeds":[{"created_at":"2023-01-13T13:11:30Z","entry_id":2869,"field1":"359"},{"created_at":"2023-01-13T13:11:57Z","entry_id":2870,"field1":"361"},{"created_at":"2023-01-13T13:12:23Z","entry_id":2871,"field1":"363"}]}
0 0

View file

@ -57,7 +57,7 @@ void setup()
Serial.println(WiFi.localIP()); Serial.println(WiFi.localIP());
} }
void readResponse(WiFiClient *client){ void readResponse(NetworkClient *client){
unsigned long timeout = millis(); unsigned long timeout = millis();
while(client->available() == 0){ while(client->available() == 0){
if(millis() - timeout > 5000){ if(millis() - timeout > 5000){
@ -77,7 +77,7 @@ void readResponse(WiFiClient *client){
} }
void loop(){ void loop(){
WiFiClient client; NetworkClient client;
String footer = String(" HTTP/1.1\r\n") + "Host: " + String(host) + "\r\n" + "Connection: close\r\n\r\n"; String footer = String(" HTTP/1.1\r\n") + "Host: " + String(host) + "\r\n" + "Connection: close\r\n\r\n";
// WRITE -------------------------------------------------------------------------------------------- // WRITE --------------------------------------------------------------------------------------------

View file

@ -44,8 +44,8 @@ void loop()
Serial.print("Connecting to "); Serial.print("Connecting to ");
Serial.println(host); Serial.println(host);
// Use WiFiClient class to create TCP connections // Use NetworkClient class to create TCP connections
WiFiClient client; NetworkClient client;
if (!client.connect(host, port)) { if (!client.connect(host, port)) {
Serial.println("Connection failed."); Serial.println("Connection failed.");

View file

@ -1,4 +1,4 @@
# WiFiClientConnect Example # NetworkClientConnect Example
This example demonstrates how to connect to the WiFi and manage the status and disconnection from STA. This example demonstrates how to connect to the WiFi and manage the status and disconnection from STA.

View file

@ -66,7 +66,7 @@ void loop() {
} }
Serial.print("Connecting to website: "); Serial.print("Connecting to website: ");
Serial.println(host); Serial.println(host);
WiFiClient client; NetworkClient client;
if (client.connect(host, 80)) { if (client.connect(host, 80)) {
String url = "/rele/rele1.txt"; String url = "/rele/rele1.txt";
client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: ESP32\r\n" + "Connection: close\r\n\r\n"); client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: ESP32\r\n" + "Connection: close\r\n\r\n");

View file

@ -56,8 +56,8 @@ void loop()
Serial.print("connecting to "); Serial.print("connecting to ");
Serial.println(host); Serial.println(host);
// Use WiFiClient class to create TCP connections // Use NetworkClient class to create TCP connections
WiFiClient client; NetworkClient client;
const int httpPort = 80; const int httpPort = 80;
if (!client.connect(host, httpPort)) { if (!client.connect(host, httpPort)) {
Serial.println("connection failed"); Serial.println("connection failed");

View file

@ -6,7 +6,7 @@
static volatile bool wifi_connected = false; static volatile bool wifi_connected = false;
WiFiUDP ntpClient; NetworkUDP ntpClient;
void wifiOnConnect(){ void wifiOnConnect(){
Serial.println("STA Connected"); Serial.println("STA Connected");
@ -79,11 +79,11 @@ void WiFiEvent(WiFiEvent_t event){
break; break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP6: case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
Serial.print("STA IPv6: "); Serial.print("STA IPv6: ");
Serial.println(WiFi.localIPv6()); Serial.println(WiFi.linkLocalIPv6());
break; break;
case ARDUINO_EVENT_WIFI_AP_GOT_IP6: case ARDUINO_EVENT_WIFI_AP_GOT_IP6:
Serial.print("AP IPv6: "); Serial.print("AP IPv6: ");
Serial.println(WiFi.softAPIPv6()); Serial.println(WiFi.softAPlinkLocalIPv6());
break; break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP: case ARDUINO_EVENT_WIFI_STA_GOT_IP:
wifiOnConnect(); wifiOnConnect();

View file

@ -28,8 +28,8 @@ WiFiMulti wifiMulti;
const char* ssid = "**********"; const char* ssid = "**********";
const char* password = "**********"; const char* password = "**********";
WiFiServer server(23); NetworkServer server(23);
WiFiClient serverClients[MAX_SRV_CLIENTS]; NetworkClient serverClients[MAX_SRV_CLIENTS];
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);

View file

@ -3,7 +3,7 @@
* *
*/ */
#include <WiFi.h> #include <WiFi.h>
#include <WiFiUdp.h> #include <NetworkUdp.h>
// WiFi network name and password: // WiFi network name and password:
const char * networkName = "your-ssid"; const char * networkName = "your-ssid";
@ -19,7 +19,7 @@ const int udpPort = 3333;
boolean connected = false; boolean connected = false;
//The udp library class //The udp library class
WiFiUDP udp; NetworkUDP udp;
void setup(){ void setup(){
// Initilize hardware serial: // Initilize hardware serial:

View file

@ -13,10 +13,10 @@ WiFi KEYWORD3
####################################### #######################################
WiFi KEYWORD1 WiFi KEYWORD1
WiFiClient KEYWORD1 NetworkClient KEYWORD1
WiFiServer KEYWORD1 NetworkServer KEYWORD1
WiFiUDP KEYWORD1 NetworkUDP KEYWORD1
WiFiClientSecure KEYWORD1 NetworkClientSecure KEYWORD1
####################################### #######################################
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)

340
libraries/WiFi/src/AP.cpp Normal file
View file

@ -0,0 +1,340 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "WiFi.h"
#include "WiFiGeneric.h"
#include "WiFiAP.h"
#if SOC_WIFI_SUPPORTED
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <esp_err.h>
#include <esp_mac.h>
#include <esp_wifi.h>
#include <esp_event.h>
#include <lwip/ip_addr.h>
#include "dhcpserver/dhcpserver_options.h"
esp_netif_t* get_esp_interface_netif(esp_interface_t interface);
static size_t _wifi_strncpy(char * dst, const char * src, size_t dst_len){
if(!dst || !src || !dst_len){
return 0;
}
size_t src_len = strlen(src);
if(src_len >= dst_len){
src_len = dst_len;
} else {
src_len += 1;
}
memcpy(dst, src, src_len);
return src_len;
}
/**
* compare two AP configurations
* @param lhs softap_config
* @param rhs softap_config
* @return equal
*/
static bool softap_config_equal(const wifi_config_t& lhs, const wifi_config_t& rhs)
{
if(strncmp(reinterpret_cast<const char*>(lhs.ap.ssid), reinterpret_cast<const char*>(rhs.ap.ssid), 32) != 0) {
return false;
}
if(strncmp(reinterpret_cast<const char*>(lhs.ap.password), reinterpret_cast<const char*>(rhs.ap.password), 64) != 0) {
return false;
}
if(lhs.ap.channel != rhs.ap.channel) {
return false;
}
if(lhs.ap.authmode != rhs.ap.authmode) {
return false;
}
if(lhs.ap.ssid_hidden != rhs.ap.ssid_hidden) {
return false;
}
if(lhs.ap.max_connection != rhs.ap.max_connection) {
return false;
}
if(lhs.ap.pairwise_cipher != rhs.ap.pairwise_cipher) {
return false;
}
if(lhs.ap.ftm_responder != rhs.ap.ftm_responder) {
return false;
}
return true;
}
static APClass * _ap_network_if = NULL;
static esp_event_handler_instance_t _ap_ev_instance = NULL;
static void _ap_event_cb(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
if (event_base == WIFI_EVENT){
((APClass*)arg)->_onApEvent(event_id, event_data);
}
}
static void _onApArduinoEvent(arduino_event_id_t event, arduino_event_info_t info)
{
if(_ap_network_if == NULL || event < ARDUINO_EVENT_WIFI_AP_START || event > ARDUINO_EVENT_WIFI_AP_GOT_IP6){
return;
}
log_d("Arduino AP Event: %d - %s", event, Network.eventName(event));
if(event == ARDUINO_EVENT_WIFI_AP_START) {
if (_ap_network_if->getStatusBits() & ESP_NETIF_WANT_IP6_BIT){
esp_err_t err = esp_netif_create_ip6_linklocal(_ap_network_if->netif());
if(err != ESP_OK){
log_e("Failed to enable IPv6 Link Local on AP: 0x%x: %s", err, esp_err_to_name(err));
} else {
log_v("Enabled IPv6 Link Local on %s", _ap_network_if->desc());
}
}
}
}
void APClass::_onApEvent(int32_t event_id, void* event_data){
arduino_event_t arduino_event;
arduino_event.event_id = ARDUINO_EVENT_MAX;
if (event_id == WIFI_EVENT_AP_START) {
log_v("AP Started");
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_START;
setStatusBits(ESP_NETIF_STARTED_BIT);
} else if (event_id == WIFI_EVENT_AP_STOP) {
log_v("AP Stopped");
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_STOP;
clearStatusBits(ESP_NETIF_STARTED_BIT | ESP_NETIF_CONNECTED_BIT | ESP_NETIF_HAS_IP_BIT | ESP_NETIF_HAS_LOCAL_IP6_BIT | ESP_NETIF_HAS_GLOBAL_IP6_BIT);
} else if (event_id == WIFI_EVENT_AP_PROBEREQRECVED) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_ap_probe_req_rx_t * event = (wifi_event_ap_probe_req_rx_t*)event_data;
log_v("AP Probe Request: RSSI: %d, MAC: " MACSTR, event->rssi, MAC2STR(event->mac));
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED;
memcpy(&arduino_event.event_info.wifi_ap_probereqrecved, event_data, sizeof(wifi_event_ap_probe_req_rx_t));
} else if (event_id == WIFI_EVENT_AP_STACONNECTED) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
log_v("AP Station Connected: MAC: " MACSTR ", AID: %d", MAC2STR(event->mac), event->aid);
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_STACONNECTED;
memcpy(&arduino_event.event_info.wifi_ap_staconnected, event_data, sizeof(wifi_event_ap_staconnected_t));
setStatusBits(ESP_NETIF_CONNECTED_BIT);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
log_v("AP Station Disconnected: MAC: " MACSTR ", AID: %d", MAC2STR(event->mac), event->aid);
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_STADISCONNECTED;
memcpy(&arduino_event.event_info.wifi_ap_stadisconnected, event_data, sizeof(wifi_event_ap_stadisconnected_t));
// If no more clients are left
wifi_sta_list_t clients;
if(esp_wifi_ap_get_sta_list(&clients) != ESP_OK || clients.num == 0) {
clearStatusBits(ESP_NETIF_CONNECTED_BIT);
}
} else {
return;
}
if(arduino_event.event_id < ARDUINO_EVENT_MAX){
Network.postEvent(&arduino_event);
}
}
APClass::APClass(){
_ap_network_if = this;
}
APClass::~APClass(){
end();
_ap_network_if = NULL;
}
bool APClass::begin(){
Network.begin();
if(_ap_ev_instance == NULL && esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &_ap_event_cb, this, &_ap_ev_instance)){
log_e("event_handler_instance_register for WIFI_EVENT Failed!");
return false;
}
if(_esp_netif == NULL){
Network.onSysEvent(_onApArduinoEvent);
}
if(!WiFi.enableAP(true)) {
log_e("AP enable failed!");
return false;
}
// attach events and esp_netif here
if(_esp_netif == NULL){
_esp_netif = get_esp_interface_netif(ESP_IF_WIFI_AP);
/* attach to receive events */
initNetif(ESP_NETIF_ID_AP);
}
return true;
}
bool APClass::end(){
if(!WiFi.enableAP(false)) {
log_e("AP disable failed!");
return false;
}
Network.removeEvent(_onApArduinoEvent);
// we just set _esp_netif to NULL here, so destroyNetif() does not try to destroy it.
// That would be done by WiFi.enableAP(false) if STA is not enabled, or when it gets disabled
_esp_netif = NULL;
destroyNetif();
if(_ap_ev_instance != NULL){
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &_ap_event_cb);
_ap_ev_instance = NULL;
}
return true;
}
bool APClass::create(const char* ssid, const char* passphrase, int channel, int ssid_hidden, int max_connection, bool ftm_responder){
if(!ssid || *ssid == 0) {
// fail SSID missing
log_e("SSID missing!");
return false;
}
if(passphrase && (strlen(passphrase) > 0 && strlen(passphrase) < 8)) {
// fail passphrase too short
log_e("passphrase too short!");
return false;
}
if(!begin()) {
return false;
}
wifi_config_t conf;
memset(&conf, 0, sizeof(wifi_config_t));
conf.ap.channel = channel;
conf.ap.max_connection = max_connection;
conf.ap.beacon_interval = 100;
conf.ap.ssid_hidden = ssid_hidden;
conf.ap.ftm_responder = ftm_responder;
if(ssid != NULL && ssid[0] != 0){
_wifi_strncpy((char*)conf.ap.ssid, ssid, 32);
conf.ap.ssid_len = strlen(ssid);
if(passphrase != NULL && passphrase[0] != 0){
conf.ap.authmode = WIFI_AUTH_WPA2_PSK;
conf.ap.pairwise_cipher = WIFI_CIPHER_TYPE_CCMP; // Disable by default enabled insecure TKIP and use just CCMP.
_wifi_strncpy((char*)conf.ap.password, passphrase, 64);
}
}
wifi_config_t conf_current;
esp_err_t err = esp_wifi_get_config(WIFI_IF_AP, &conf_current);
if(err){
log_e("Get AP config failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
if(!softap_config_equal(conf, conf_current)) {
err = esp_wifi_set_config(WIFI_IF_AP, &conf);
if(err){
log_e("Set AP config failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
}
return true;
}
bool APClass::clear(){
if(!begin()) {
return false;
}
wifi_config_t conf;
memset(&conf, 0, sizeof(wifi_config_t));
conf.ap.channel = 1;
conf.ap.max_connection = 4;
conf.ap.beacon_interval = 100;
esp_err_t err = esp_wifi_set_config(WIFI_IF_AP, &conf);
if(err){
log_e("Set AP config failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
return true;
}
bool APClass::bandwidth(wifi_bandwidth_t bandwidth){
if(!begin()) {
return false;
}
esp_err_t err = esp_wifi_set_bandwidth(WIFI_IF_AP, bandwidth);
if(err){
log_e("Could not set AP bandwidth! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
return true;
}
String APClass::SSID(void) const{
if(!started()){
return String();
}
wifi_config_t info;
if(!esp_wifi_get_config(WIFI_IF_AP, &info)) {
return String(reinterpret_cast<char*>(info.ap.ssid));
}
return String();
}
uint8_t APClass::stationCount(){
wifi_sta_list_t clients;
if(!started()){
return 0;
}
if(esp_wifi_ap_get_sta_list(&clients) == ESP_OK) {
return clients.num;
}
return 0;
}
size_t APClass::printDriverInfo(Print & out) const{
size_t bytes = 0;
wifi_config_t info;
wifi_sta_list_t clients;
if(!started()){
return bytes;
}
if(esp_wifi_get_config(WIFI_IF_AP, &info) != ESP_OK){
return bytes;
}
bytes += out.print(",");
bytes += out.print((const char*)info.ap.ssid);
bytes += out.print(",CH:");
bytes += out.print(info.ap.channel);
if(info.ap.authmode == WIFI_AUTH_OPEN){ bytes += out.print(",OPEN"); }
else if(info.ap.authmode == WIFI_AUTH_WEP){ bytes += out.print(",WEP"); }
else if(info.ap.authmode == WIFI_AUTH_WPA_PSK){ bytes += out.print(",WWPA_PSK"); }
else if(info.ap.authmode == WIFI_AUTH_WPA2_PSK){ bytes += out.print(",WWPA2_PSK"); }
else if(info.ap.authmode == WIFI_AUTH_WPA_WPA2_PSK){ bytes += out.print(",WWPA_WPA2_PSK"); }
else if(info.ap.authmode == WIFI_AUTH_ENTERPRISE){ bytes += out.print(",WEAP"); }
else if(info.ap.authmode == WIFI_AUTH_WPA3_PSK){ bytes += out.print(",WWPA3_PSK"); }
else if(info.ap.authmode == WIFI_AUTH_WPA2_WPA3_PSK){ bytes += out.print(",WWPA2_WPA3_PSK"); }
else if(info.ap.authmode == WIFI_AUTH_WAPI_PSK){ bytes += out.print(",WWAPI_PSK"); }
else if(info.ap.authmode == WIFI_AUTH_OWE){ bytes += out.print(",WOWE"); }
else if(info.ap.authmode == WIFI_AUTH_WPA3_ENT_192){ bytes += out.print(",WWPA3_ENT_SUITE_B_192_BIT"); }
if(esp_wifi_ap_get_sta_list(&clients) == ESP_OK) {
bytes += out.print(",STA:");
bytes += out.print(clients.num);
}
return bytes;
}
#endif /* SOC_WIFI_SUPPORTED */

794
libraries/WiFi/src/STA.cpp Normal file
View file

@ -0,0 +1,794 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "WiFi.h"
#include "WiFiGeneric.h"
#include "WiFiSTA.h"
#if SOC_WIFI_SUPPORTED
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <esp_err.h>
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp32-hal.h>
#include <lwip/ip_addr.h>
#include "lwip/err.h"
#include "lwip/dns.h"
#include <esp_smartconfig.h>
#include <esp_netif.h>
#include "esp_mac.h"
#if __has_include ("esp_eap_client.h")
#include "esp_eap_client.h"
#else
#include "esp_wpa2.h"
#endif
esp_netif_t* get_esp_interface_netif(esp_interface_t interface);
static size_t _wifi_strncpy(char * dst, const char * src, size_t dst_len){
if(!dst || !src || !dst_len){
return 0;
}
size_t src_len = strlen(src);
if(src_len >= dst_len){
src_len = dst_len;
} else {
src_len += 1;
}
memcpy(dst, src, src_len);
return src_len;
}
static STAClass * _sta_network_if = NULL;
static esp_event_handler_instance_t _sta_ev_instance = NULL;
static void _sta_event_cb(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
if (event_base == WIFI_EVENT){
((STAClass*)arg)->_onStaEvent(event_id, event_data);
}
}
static bool _is_staReconnectableReason(uint8_t reason) {
switch(reason) {
case WIFI_REASON_UNSPECIFIED:
//Timeouts (retry)
case WIFI_REASON_AUTH_EXPIRE:
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT:
case WIFI_REASON_802_1X_AUTH_FAILED:
case WIFI_REASON_HANDSHAKE_TIMEOUT:
//Transient error (reconnect)
case WIFI_REASON_AUTH_LEAVE:
case WIFI_REASON_ASSOC_EXPIRE:
case WIFI_REASON_ASSOC_TOOMANY:
case WIFI_REASON_NOT_AUTHED:
case WIFI_REASON_NOT_ASSOCED:
case WIFI_REASON_ASSOC_NOT_AUTHED:
case WIFI_REASON_MIC_FAILURE:
case WIFI_REASON_IE_IN_4WAY_DIFFERS:
case WIFI_REASON_INVALID_PMKID:
case WIFI_REASON_BEACON_TIMEOUT:
case WIFI_REASON_NO_AP_FOUND:
case WIFI_REASON_ASSOC_FAIL:
case WIFI_REASON_CONNECTION_FAIL:
case WIFI_REASON_AP_TSF_RESET:
case WIFI_REASON_ROAMING:
return true;
default:
return false;
}
}
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
static const char * auth_mode_str(int authmode)
{
switch (authmode) {
case WIFI_AUTH_OPEN:
return ("OPEN");
break;
case WIFI_AUTH_WEP:
return ("WEP");
break;
case WIFI_AUTH_WPA_PSK:
return ("WPA_PSK");
break;
case WIFI_AUTH_WPA2_PSK:
return ("WPA2_PSK");
break;
case WIFI_AUTH_WPA_WPA2_PSK:
return ("WPA_WPA2_PSK");
break;
case WIFI_AUTH_WPA2_ENTERPRISE:
return ("WPA2_ENTERPRISE");
break;
case WIFI_AUTH_WPA3_PSK:
return ("WPA3_PSK");
break;
case WIFI_AUTH_WPA2_WPA3_PSK:
return ("WPA2_WPA3_PSK");
break;
case WIFI_AUTH_WAPI_PSK:
return ("WPAPI_PSK");
break;
default:
break;
}
return ("UNKNOWN");
}
#endif
static void _onStaArduinoEvent(arduino_event_id_t event, arduino_event_info_t info)
{
if(_sta_network_if == NULL || event < ARDUINO_EVENT_WIFI_STA_START || event > ARDUINO_EVENT_WIFI_STA_LOST_IP){
return;
}
static bool first_connect = true;
log_d("Arduino STA Event: %d - %s", event, Network.eventName(event));
if(event == ARDUINO_EVENT_WIFI_STA_START) {
_sta_network_if->_setStatus(WL_DISCONNECTED);
if(esp_wifi_set_ps(WiFi.getSleep()) != ESP_OK){
log_e("esp_wifi_set_ps failed");
}
} else if(event == ARDUINO_EVENT_WIFI_STA_STOP) {
_sta_network_if->_setStatus(WL_STOPPED);
} else if(event == ARDUINO_EVENT_WIFI_STA_CONNECTED) {
_sta_network_if->_setStatus(WL_IDLE_STATUS);
if (_sta_network_if->getStatusBits() & ESP_NETIF_WANT_IP6_BIT){
esp_err_t err = esp_netif_create_ip6_linklocal(_sta_network_if->netif());
if(err != ESP_OK){
log_e("Failed to enable IPv6 Link Local on STA: 0x%x: %s", err, esp_err_to_name(err));
} else {
log_v("Enabled IPv6 Link Local on %s", _sta_network_if->desc());
}
}
} else if(event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) {
uint8_t reason = info.wifi_sta_disconnected.reason;
// Reason 0 causes crash, use reason 1 (UNSPECIFIED) instead
if(!reason)
reason = WIFI_REASON_UNSPECIFIED;
log_w("Reason: %u - %s", reason, WiFi.STA.disconnectReasonName((wifi_err_reason_t)reason));
if(reason == WIFI_REASON_NO_AP_FOUND) {
_sta_network_if->_setStatus(WL_NO_SSID_AVAIL);
} else if((reason == WIFI_REASON_AUTH_FAIL) && !first_connect){
_sta_network_if->_setStatus(WL_CONNECT_FAILED);
} else if(reason == WIFI_REASON_BEACON_TIMEOUT || reason == WIFI_REASON_HANDSHAKE_TIMEOUT) {
_sta_network_if->_setStatus(WL_CONNECTION_LOST);
} else if(reason == WIFI_REASON_AUTH_EXPIRE) {
} else {
_sta_network_if->_setStatus(WL_DISCONNECTED);
}
bool DoReconnect = false;
if(reason == WIFI_REASON_ASSOC_LEAVE) { //Voluntarily disconnected. Don't reconnect!
}
else if(first_connect) { //Retry once for all failure reasons
first_connect = false;
DoReconnect = true;
log_d("WiFi Reconnect Running");
}
else if(_sta_network_if->getAutoReconnect() && _is_staReconnectableReason(reason)) {
DoReconnect = true;
log_d("WiFi AutoReconnect Running");
}
else if(reason == WIFI_REASON_ASSOC_FAIL) {
_sta_network_if->_setStatus(WL_CONNECT_FAILED);
}
if(DoReconnect) {
_sta_network_if->disconnect();
_sta_network_if->connect();
}
} else if(event == ARDUINO_EVENT_WIFI_STA_GOT_IP) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
uint8_t * ip = (uint8_t *)&(info.got_ip.ip_info.ip.addr);
uint8_t * mask = (uint8_t *)&(info.got_ip.ip_info.netmask.addr);
uint8_t * gw = (uint8_t *)&(info.got_ip.ip_info.gw.addr);
log_d("STA IP: %u.%u.%u.%u, MASK: %u.%u.%u.%u, GW: %u.%u.%u.%u",
ip[0], ip[1], ip[2], ip[3],
mask[0], mask[1], mask[2], mask[3],
gw[0], gw[1], gw[2], gw[3]);
#endif
_sta_network_if->_setStatus(WL_CONNECTED);
} else if(event == ARDUINO_EVENT_WIFI_STA_LOST_IP) {
_sta_network_if->_setStatus(WL_IDLE_STATUS);
}
}
void STAClass::_onStaEvent(int32_t event_id, void* event_data){
arduino_event_t arduino_event;
arduino_event.event_id = ARDUINO_EVENT_MAX;
if (event_id == WIFI_EVENT_STA_START) {
log_v("STA Started");
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_START;
setStatusBits(ESP_NETIF_STARTED_BIT);
} else if (event_id == WIFI_EVENT_STA_STOP) {
log_v("STA Stopped");
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_STOP;
clearStatusBits(ESP_NETIF_STARTED_BIT | ESP_NETIF_CONNECTED_BIT | ESP_NETIF_HAS_IP_BIT | ESP_NETIF_HAS_LOCAL_IP6_BIT | ESP_NETIF_HAS_GLOBAL_IP6_BIT);
} else if (event_id == WIFI_EVENT_STA_AUTHMODE_CHANGE) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_sta_authmode_change_t * event = (wifi_event_sta_authmode_change_t*)event_data;
log_v("STA Auth Mode Changed: From: %s, To: %s", auth_mode_str(event->old_mode), auth_mode_str(event->new_mode));
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE;
memcpy(&arduino_event.event_info.wifi_sta_authmode_change, event_data, sizeof(wifi_event_sta_authmode_change_t));
} else if (event_id == WIFI_EVENT_STA_CONNECTED) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_sta_connected_t * event = (wifi_event_sta_connected_t*)event_data;
log_v("STA Connected: SSID: %s, BSSID: " MACSTR ", Channel: %u, Auth: %s", event->ssid, MAC2STR(event->bssid), event->channel, auth_mode_str(event->authmode));
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_CONNECTED;
memcpy(&arduino_event.event_info.wifi_sta_connected, event_data, sizeof(wifi_event_sta_connected_t));
setStatusBits(ESP_NETIF_CONNECTED_BIT);
} else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_sta_disconnected_t * event = (wifi_event_sta_disconnected_t*)event_data;
log_v("STA Disconnected: SSID: %s, BSSID: " MACSTR ", Reason: %u", event->ssid, MAC2STR(event->bssid), event->reason);
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_DISCONNECTED;
memcpy(&arduino_event.event_info.wifi_sta_disconnected, event_data, sizeof(wifi_event_sta_disconnected_t));
clearStatusBits(ESP_NETIF_CONNECTED_BIT | ESP_NETIF_HAS_IP_BIT | ESP_NETIF_HAS_LOCAL_IP6_BIT | ESP_NETIF_HAS_GLOBAL_IP6_BIT);
} else {
return;
}
if(arduino_event.event_id < ARDUINO_EVENT_MAX){
Network.postEvent(&arduino_event);
}
}
STAClass::STAClass():
_minSecurity(WIFI_AUTH_WPA2_PSK)
, _scanMethod(WIFI_FAST_SCAN)
, _sortMethod(WIFI_CONNECT_AP_BY_SIGNAL)
, _autoReconnect(true)
, _status(WL_STOPPED)
{
_sta_network_if = this;
}
STAClass::~STAClass(){
end();
_sta_network_if = NULL;
}
wl_status_t STAClass::status(){
return _status;
}
void STAClass::_setStatus(wl_status_t status){
_status = status;
}
/**
* Sets the working bandwidth of the STA mode
* @param m wifi_bandwidth_t
*/
bool STAClass::bandwidth(wifi_bandwidth_t bandwidth) {
if(!begin()) {
return false;
}
esp_err_t err;
err = esp_wifi_set_bandwidth(WIFI_IF_STA, bandwidth);
if(err){
log_e("Could not set STA bandwidth! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
return true;
}
bool STAClass::begin(bool tryConnect){
Network.begin();
if(_sta_ev_instance == NULL && esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &_sta_event_cb, this, &_sta_ev_instance)){
log_e("event_handler_instance_register for WIFI_EVENT Failed!");
return false;
}
if(_esp_netif == NULL){
Network.onSysEvent(_onStaArduinoEvent);
}
if(!WiFi.enableSTA(true)) {
log_e("STA enable failed!");
return false;
}
// attach events and esp_netif here
if(_esp_netif == NULL){
_esp_netif = get_esp_interface_netif(ESP_IF_WIFI_STA);
/* attach to receive events */
initNetif(ESP_NETIF_ID_STA);
}
if(tryConnect){
return connect();
}
return true;
}
bool STAClass::end(){
if(!WiFi.enableSTA(false)) {
log_e("STA disable failed!");
return false;
}
Network.removeEvent(_onStaArduinoEvent);
// we just set _esp_netif to NULL here, so destroyNetif() does not try to destroy it.
// That would be done by WiFi.enableSTA(false) if AP is not enabled, or when it gets disabled
_esp_netif = NULL;
destroyNetif();
if(_sta_ev_instance != NULL){
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &_sta_event_cb);
_sta_ev_instance = NULL;
}
return true;
}
bool STAClass::connect(){
if(_esp_netif == NULL){
log_e("STA not started! You must call begin() first.");
return false;
}
if(connected()){
log_w("STA already connected.");
return true;
}
wifi_config_t current_conf;
if(esp_wifi_get_config(WIFI_IF_STA, &current_conf) != ESP_OK || esp_wifi_set_config(WIFI_IF_STA, &current_conf) != ESP_OK) {
log_e("STA config failed");
return false;
}
if((getStatusBits() & ESP_NETIF_HAS_IP_BIT) == 0 && !config()){
log_e("STA failed to configure dynamic IP!");
return false;
}
esp_err_t err = esp_wifi_connect();
if(err){
log_e("STA connect failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
return true;
}
/**
* Start Wifi connection
* if passphrase is set the most secure supported mode will be automatically selected
* @param ssid const char* Pointer to the SSID string.
* @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal).
* @param bssid uint8_t[6] Optional. BSSID / MAC of AP
* @param channel Optional. Channel of AP
* @param connect Optional. call connect
* @return
*/
bool STAClass::connect(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool tryConnect){
if(_esp_netif == NULL){
log_e("STA not started! You must call begin() first.");
return false;
}
if(connected()){
log_w("STA currently connected. Disconnecting...");
if(!disconnect(true, 1000)){
return false;
}
}
if(!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
log_e("SSID too long or missing!");
return false;
}
if(passphrase && strlen(passphrase) > 64) {
log_e("passphrase too long!");
return false;
}
wifi_config_t conf;
memset(&conf, 0, sizeof(wifi_config_t));
conf.sta.channel = channel;
conf.sta.scan_method = _scanMethod;
conf.sta.sort_method = _sortMethod;
conf.sta.threshold.rssi = -127;
conf.sta.pmf_cfg.capable = true;
if(ssid != NULL && ssid[0] != 0){
_wifi_strncpy((char*)conf.sta.ssid, ssid, 32);
if(passphrase != NULL && passphrase[0] != 0){
conf.sta.threshold.authmode = _minSecurity;
_wifi_strncpy((char*)conf.sta.password, passphrase, 64);
}
if(bssid != NULL){
conf.sta.bssid_set = 1;
memcpy(conf.sta.bssid, bssid, 6);
}
}
esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &conf);
if(err != ESP_OK){
log_e("STA clear config failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
if((getStatusBits() & ESP_NETIF_HAS_IP_BIT) == 0 && !config()){
log_e("STA failed to configure dynamic IP!");
return false;
}
if(tryConnect){
esp_err_t err = esp_wifi_connect();
if(err){
log_e("STA connect failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
}
return true;
}
/**
* Start Wifi connection with a WPA2 Enterprise AP
* if passphrase is set the most secure supported mode will be automatically selected
* @param ssid const char* Pointer to the SSID string.
* @param method wpa2_method_t The authentication method of WPA2 (WPA2_AUTH_TLS, WPA2_AUTH_PEAP, WPA2_AUTH_TTLS)
* @param wpa2_identity const char* Pointer to the entity
* @param wpa2_username const char* Pointer to the username
* @param password const char * Pointer to the password.
* @param ca_pem const char* Pointer to a string with the contents of a .pem file with CA cert
* @param client_crt const char* Pointer to a string with the contents of a .crt file with client cert
* @param client_key const char* Pointer to a string with the contants of a .key file with client key
* @param bssid uint8_t[6] Optional. BSSID / MAC of AP
* @param channel Optional. Channel of AP
* @param connect Optional. call connect
* @return
*/
bool STAClass::connect(const char* wpa2_ssid, wpa2_auth_method_t method, const char* wpa2_identity, const char* wpa2_username, const char *wpa2_password, const char* ca_pem, const char* client_crt, const char* client_key, int32_t channel, const uint8_t* bssid, bool tryConnect){
if(_esp_netif == NULL){
log_e("STA not started! You must call begin() first.");
return false;
}
if(connected()){
log_w("STA currently connected. Disconnecting...");
if(!disconnect(true, 1000)){
return false;
}
}
if(!wpa2_ssid || *wpa2_ssid == 0x00 || strlen(wpa2_ssid) > 32) {
log_e("SSID too long or missing!");
return false;
}
if(wpa2_identity && strlen(wpa2_identity) > 64) {
log_e("identity too long!");
return false;
}
if(wpa2_username && strlen(wpa2_username) > 64) {
log_e("username too long!");
return false;
}
if(wpa2_password && strlen(wpa2_password) > 64) {
log_e("password too long!");
return false;
}
if(ca_pem) {
#if __has_include ("esp_eap_client.h")
esp_eap_client_set_ca_cert((uint8_t *)ca_pem, strlen(ca_pem));
#else
esp_wifi_sta_wpa2_ent_set_ca_cert((uint8_t *)ca_pem, strlen(ca_pem));
#endif
}
if(client_crt) {
#if __has_include ("esp_eap_client.h")
esp_eap_client_set_certificate_and_key((uint8_t *)client_crt, strlen(client_crt), (uint8_t *)client_key, strlen(client_key), NULL, 0);
#else
esp_wifi_sta_wpa2_ent_set_cert_key((uint8_t *)client_crt, strlen(client_crt), (uint8_t *)client_key, strlen(client_key), NULL, 0);
#endif
}
#if __has_include ("esp_eap_client.h")
esp_eap_client_set_identity((uint8_t *)wpa2_identity, strlen(wpa2_identity));
#else
esp_wifi_sta_wpa2_ent_set_identity((uint8_t *)wpa2_identity, strlen(wpa2_identity));
#endif
if(method == WPA2_AUTH_PEAP || method == WPA2_AUTH_TTLS) {
#if __has_include ("esp_eap_client.h")
esp_eap_client_set_username((uint8_t *)wpa2_username, strlen(wpa2_username));
esp_eap_client_set_password((uint8_t *)wpa2_password, strlen(wpa2_password));
#else
esp_wifi_sta_wpa2_ent_set_username((uint8_t *)wpa2_username, strlen(wpa2_username));
esp_wifi_sta_wpa2_ent_set_password((uint8_t *)wpa2_password, strlen(wpa2_password));
#endif
}
#if __has_include ("esp_eap_client.h")
esp_wifi_sta_enterprise_enable(); //set config settings to enable function
#else
esp_wifi_sta_wpa2_ent_enable(); //set config settings to enable function
#endif
return connect(wpa2_ssid, NULL, 0, NULL, tryConnect); //connect to wifi
}
bool STAClass::disconnect(bool eraseap, unsigned long timeout){
if(eraseap){
if(!started()){
log_e("STA not started! You must call begin first.");
return false;
}
wifi_config_t conf;
memset(&conf, 0, sizeof(wifi_config_t));
esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &conf);
if(err != ESP_OK){
log_e("STA clear config failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
}
if(!connected()){
log_w("STA already disconnected.");
return true;
}
esp_err_t err = esp_wifi_disconnect();
if(err != ESP_OK){
log_e("STA disconnect failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
if(timeout){
const unsigned long start = millis();
while (connected() && ((millis() - start) < timeout)) {
delay(5);
}
if(connected()){
return false;
}
}
return true;
}
bool STAClass::reconnect(){
if(connected()) {
if(esp_wifi_disconnect() != ESP_OK) {
return false;
}
}
return esp_wifi_connect() == ESP_OK;
}
bool STAClass::erase(){
if(!started()){
log_e("STA not started! You must call begin first.");
return false;
}
return esp_wifi_restore()==ESP_OK;
}
uint8_t STAClass::waitForConnectResult(unsigned long timeoutLength){
//1 and 3 have STA enabled
if((WiFiGenericClass::getMode() & WIFI_MODE_STA) == 0) {
return WL_DISCONNECTED;
}
unsigned long start = millis();
while((!status() || status() >= WL_DISCONNECTED) && (millis() - start) < timeoutLength) {
delay(100);
}
return status();
}
bool STAClass::setAutoReconnect(bool autoReconnect){
_autoReconnect = autoReconnect;
return true;
}
bool STAClass::getAutoReconnect(){
return _autoReconnect;
}
void STAClass::setMinSecurity(wifi_auth_mode_t minSecurity){
_minSecurity = minSecurity;
}
void STAClass::setScanMethod(wifi_scan_method_t scanMethod){
_scanMethod = scanMethod;
}
void STAClass::setSortMethod(wifi_sort_method_t sortMethod){
_sortMethod = sortMethod;
}
String STAClass::SSID() const {
if(!started()){
return String();
}
wifi_ap_record_t info;
if(!esp_wifi_sta_get_ap_info(&info)) {
return String(reinterpret_cast<char*>(info.ssid));
}
return String();
}
String STAClass::psk() const {
if(!started()){
return String();
}
wifi_config_t conf;
esp_wifi_get_config((wifi_interface_t)ESP_IF_WIFI_STA, &conf);
return String(reinterpret_cast<char*>(conf.sta.password));
}
uint8_t * STAClass::BSSID(uint8_t* buff){
static uint8_t bssid[6];
wifi_ap_record_t info;
if(!started()){
return NULL;
}
esp_err_t err = esp_wifi_sta_get_ap_info(&info);
if (buff != NULL) {
if(err) {
memset(buff, 0, 6);
} else {
memcpy(buff, info.bssid, 6);
}
return buff;
}
if(!err) {
memcpy(bssid, info.bssid, 6);
return reinterpret_cast<uint8_t*>(bssid);
}
return NULL;
}
String STAClass::BSSIDstr(){
uint8_t* bssid = BSSID();
if(!bssid){
return String();
}
char mac[18] = { 0 };
sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
return String(mac);
}
int8_t STAClass::RSSI(){
if(!started()){
return 0;
}
wifi_ap_record_t info;
if(!esp_wifi_sta_get_ap_info(&info)) {
return info.rssi;
}
return 0;
}
size_t STAClass::printDriverInfo(Print & out) const {
size_t bytes = 0;
wifi_ap_record_t info;
if(!started()){
return bytes;
}
if(esp_wifi_sta_get_ap_info(&info) != ESP_OK){
return bytes;
}
bytes += out.print(",");
bytes += out.print((const char*)info.ssid);
bytes += out.print(",CH:");
bytes += out.print(info.primary);
bytes += out.print(",RSSI:");
bytes += out.print(info.rssi);
bytes += out.print(",");
if(info.phy_11ax){
bytes += out.print("AX");
} else if(info.phy_11n){
bytes += out.print("N");
} else if(info.phy_11g){
bytes += out.print("G");
} else if(info.phy_11b){
bytes += out.print("B");
}
if(info.phy_lr){
bytes += out.print(",");
bytes += out.print("LR");
}
if(info.authmode == WIFI_AUTH_OPEN){ bytes += out.print(",OPEN"); }
else if(info.authmode == WIFI_AUTH_WEP){ bytes += out.print(",WEP"); }
else if(info.authmode == WIFI_AUTH_WPA_PSK){ bytes += out.print(",WPA_PSK"); }
else if(info.authmode == WIFI_AUTH_WPA2_PSK){ bytes += out.print(",WPA2_PSK"); }
else if(info.authmode == WIFI_AUTH_WPA_WPA2_PSK){ bytes += out.print(",WPA_WPA2_PSK"); }
else if(info.authmode == WIFI_AUTH_ENTERPRISE){ bytes += out.print(",EAP"); }
else if(info.authmode == WIFI_AUTH_WPA3_PSK){ bytes += out.print(",WPA3_PSK"); }
else if(info.authmode == WIFI_AUTH_WPA2_WPA3_PSK){ bytes += out.print(",WPA2_WPA3_PSK"); }
else if(info.authmode == WIFI_AUTH_WAPI_PSK){ bytes += out.print(",WAPI_PSK"); }
else if(info.authmode == WIFI_AUTH_OWE){ bytes += out.print(",OWE"); }
else if(info.authmode == WIFI_AUTH_WPA3_ENT_192){ bytes += out.print(",WPA3_ENT_SUITE_B_192_BIT"); }
return bytes;
}
/**
* @brief Convert wifi_err_reason_t to a string.
* @param [in] reason The reason to be converted.
* @return A string representation of the error code.
* @note: wifi_err_reason_t values as of Mar 2023 (arduino-esp32 r2.0.7) are: (1-39, 46-51, 67-68, 200-208) and are defined in /tools/sdk/esp32/include/esp_wifi/include/esp_wifi_types.h.
*/
const char * STAClass::disconnectReasonName(wifi_err_reason_t reason) {
switch(reason) {
//ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2,0,7)
case WIFI_REASON_UNSPECIFIED: return "UNSPECIFIED";
case WIFI_REASON_AUTH_EXPIRE: return "AUTH_EXPIRE";
case WIFI_REASON_AUTH_LEAVE: return "AUTH_LEAVE";
case WIFI_REASON_ASSOC_EXPIRE: return "ASSOC_EXPIRE";
case WIFI_REASON_ASSOC_TOOMANY: return "ASSOC_TOOMANY";
case WIFI_REASON_NOT_AUTHED: return "NOT_AUTHED";
case WIFI_REASON_NOT_ASSOCED: return "NOT_ASSOCED";
case WIFI_REASON_ASSOC_LEAVE: return "ASSOC_LEAVE";
case WIFI_REASON_ASSOC_NOT_AUTHED: return "ASSOC_NOT_AUTHED";
case WIFI_REASON_DISASSOC_PWRCAP_BAD: return "DISASSOC_PWRCAP_BAD";
case WIFI_REASON_DISASSOC_SUPCHAN_BAD: return "DISASSOC_SUPCHAN_BAD";
case WIFI_REASON_BSS_TRANSITION_DISASSOC: return "BSS_TRANSITION_DISASSOC";
case WIFI_REASON_IE_INVALID: return "IE_INVALID";
case WIFI_REASON_MIC_FAILURE: return "MIC_FAILURE";
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: return "4WAY_HANDSHAKE_TIMEOUT";
case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT: return "GROUP_KEY_UPDATE_TIMEOUT";
case WIFI_REASON_IE_IN_4WAY_DIFFERS: return "IE_IN_4WAY_DIFFERS";
case WIFI_REASON_GROUP_CIPHER_INVALID: return "GROUP_CIPHER_INVALID";
case WIFI_REASON_PAIRWISE_CIPHER_INVALID: return "PAIRWISE_CIPHER_INVALID";
case WIFI_REASON_AKMP_INVALID: return "AKMP_INVALID";
case WIFI_REASON_UNSUPP_RSN_IE_VERSION: return "UNSUPP_RSN_IE_VERSION";
case WIFI_REASON_INVALID_RSN_IE_CAP: return "INVALID_RSN_IE_CAP";
case WIFI_REASON_802_1X_AUTH_FAILED: return "802_1X_AUTH_FAILED";
case WIFI_REASON_CIPHER_SUITE_REJECTED: return "CIPHER_SUITE_REJECTED";
case WIFI_REASON_TDLS_PEER_UNREACHABLE: return "TDLS_PEER_UNREACHABLE";
case WIFI_REASON_TDLS_UNSPECIFIED: return "TDLS_UNSPECIFIED";
case WIFI_REASON_SSP_REQUESTED_DISASSOC: return "SSP_REQUESTED_DISASSOC";
case WIFI_REASON_NO_SSP_ROAMING_AGREEMENT: return "NO_SSP_ROAMING_AGREEMENT";
case WIFI_REASON_BAD_CIPHER_OR_AKM: return "BAD_CIPHER_OR_AKM";
case WIFI_REASON_NOT_AUTHORIZED_THIS_LOCATION: return "NOT_AUTHORIZED_THIS_LOCATION";
case WIFI_REASON_SERVICE_CHANGE_PERCLUDES_TS: return "SERVICE_CHANGE_PERCLUDES_TS";
case WIFI_REASON_UNSPECIFIED_QOS: return "UNSPECIFIED_QOS";
case WIFI_REASON_NOT_ENOUGH_BANDWIDTH: return "NOT_ENOUGH_BANDWIDTH";
case WIFI_REASON_MISSING_ACKS: return "MISSING_ACKS";
case WIFI_REASON_EXCEEDED_TXOP: return "EXCEEDED_TXOP";
case WIFI_REASON_STA_LEAVING: return "STA_LEAVING";
case WIFI_REASON_END_BA: return "END_BA";
case WIFI_REASON_UNKNOWN_BA: return "UNKNOWN_BA";
case WIFI_REASON_TIMEOUT: return "TIMEOUT";
case WIFI_REASON_PEER_INITIATED: return "PEER_INITIATED";
case WIFI_REASON_AP_INITIATED: return "AP_INITIATED";
case WIFI_REASON_INVALID_FT_ACTION_FRAME_COUNT: return "INVALID_FT_ACTION_FRAME_COUNT";
case WIFI_REASON_INVALID_PMKID: return "INVALID_PMKID";
case WIFI_REASON_INVALID_MDE: return "INVALID_MDE";
case WIFI_REASON_INVALID_FTE: return "INVALID_FTE";
case WIFI_REASON_TRANSMISSION_LINK_ESTABLISH_FAILED: return "TRANSMISSION_LINK_ESTABLISH_FAILED";
case WIFI_REASON_ALTERATIVE_CHANNEL_OCCUPIED: return "ALTERATIVE_CHANNEL_OCCUPIED";
case WIFI_REASON_BEACON_TIMEOUT: return "BEACON_TIMEOUT";
case WIFI_REASON_NO_AP_FOUND: return "NO_AP_FOUND";
case WIFI_REASON_AUTH_FAIL: return "AUTH_FAIL";
case WIFI_REASON_ASSOC_FAIL: return "ASSOC_FAIL";
case WIFI_REASON_HANDSHAKE_TIMEOUT: return "HANDSHAKE_TIMEOUT";
case WIFI_REASON_CONNECTION_FAIL: return "CONNECTION_FAIL";
case WIFI_REASON_AP_TSF_RESET: return "AP_TSF_RESET";
case WIFI_REASON_ROAMING: return "ROAMING";
case WIFI_REASON_ASSOC_COMEBACK_TIME_TOO_LONG: return "ASSOC_COMEBACK_TIME_TOO_LONG";
default: return "";
}
}
#endif /* SOC_WIFI_SUPPORTED */

View file

@ -22,6 +22,7 @@
*/ */
#include "WiFi.h" #include "WiFi.h"
#if SOC_WIFI_SUPPORTED
extern "C" { extern "C" {
#include <stdint.h> #include <stdint.h>
@ -99,3 +100,5 @@ bool WiFiClass::isProvEnabled()
} }
WiFiClass WiFi; WiFiClass WiFi;
#endif /* SOC_WIFI_SUPPORTED */

View file

@ -19,8 +19,10 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef WiFi_h #pragma once
#define WiFi_h
#include "soc/soc_caps.h"
#if SOC_WIFI_SUPPORTED
#include <stdint.h> #include <stdint.h>
@ -62,13 +64,13 @@ public:
using WiFiScanClass::channel; using WiFiScanClass::channel;
public: public:
void printDiag(Print& dest); void printDiag(Print& dest);
friend class WiFiClient; friend class NetworkClient;
friend class WiFiServer; friend class NetworkServer;
friend class WiFiUDP; friend class NetworkUDP;
void enableProv(bool status); void enableProv(bool status);
bool isProvEnabled(); bool isProvEnabled();
}; };
extern WiFiClass WiFi; extern WiFiClass WiFi;
#endif #endif /* SOC_WIFI_SUPPORTED */

Some files were not shown because too many files have changed in this diff Show more