[realtek-ambz] Add new WiFiServer library

This commit is contained in:
Kuba Szczodrzyński
2022-04-26 22:54:24 +02:00
parent b71e579e7c
commit 80cb1068ce
16 changed files with 227 additions and 64 deletions

View File

@@ -151,9 +151,13 @@ SoftwareSerial | ❌
SPI | ❌
Wire | ❌
**OTHER LIBRARIES** |
Wi-Fi Station | ✔️
Wi-Fi Access Point | ❌
Wi-Fi Events | ❌
Wi-Fi Client (SSL) | ✔️ (❌)
Wi-Fi Server | ❌
SPIFFS | ❌
BLE | -
Wi-Fi (SSL) | ✔️ (❌)
HTTP | ❌
NTP | ❌
OTA | ❌

View File

@@ -28,6 +28,10 @@ class IWiFiClient : public Client {
IWiFiClient(int sock) {}
~IWiFiClient() {
stop();
}
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;
@@ -66,4 +70,5 @@ class IWiFiClient : public Client {
virtual uint16_t localPort(int sock) const = 0;
using Print::write;
using Client::stop;
};

View File

@@ -20,39 +20,47 @@
#pragma once
#include <Arduino.h>
#include <api/Server.h>
#include <api/Print.h>
#include "WiFiClient.h"
class IWiFiServer : public Server {
#include <type_traits>
template <typename TWiFiClient, typename = std::enable_if<std::is_base_of<IWiFiClient, TWiFiClient>::value>>
class IWiFiServer : public Print { // arduino::Server is useless anyway
public:
void listenOnLocalhost() {}
IWiFiServer(uint16_t port = 80, uint8_t max_clients = 4) {}
IWiFiServer(uint16_t port = 80, uint8_t maxClients = 4) {}
~IWiFiServer() {
end();
stop();
}
WiFiClient available();
WiFiClient accept() {
return available();
}
TWiFiClient available() {
return accept();
};
virtual operator bool() = 0;
void begin(uint16_t port = 0);
void begin(uint16_t port, int reuse_enable);
void end();
void close();
void stop();
virtual bool begin(uint16_t port = 0, bool reuseAddr = true) = 0;
virtual void end() = 0;
virtual TWiFiClient accept() = 0;
int setTimeout(uint32_t seconds);
void stopAll();
void setNoDelay(bool nodelay);
bool getNoDelay();
bool hasClient();
void close() {
end();
}
void stop() {
end();
}
virtual int setTimeout(uint32_t seconds) = 0;
virtual void stopAll() = 0;
virtual void setNoDelay(bool noDelay) = 0;
virtual bool getNoDelay() = 0;
virtual bool hasClient() = 0;
size_t write(uint8_t data) {
return write(&data, 1);

View File

@@ -0,0 +1,5 @@
#pragma once
// ESP32 WiFi examples use WiFiAP.h include
#include <WiFi.h>

View File

@@ -29,6 +29,7 @@ extern "C" {
#include <diag.h>
extern void *pvPortMalloc( size_t xWantedSize );
extern void *os_zalloc( size_t xWantedSize );
extern void vPortFree( void *pv );
extern void *pvPortReAlloc( void *pv, size_t xWantedSize );
extern size_t xPortGetFreeHeapSize( void );
@@ -79,7 +80,7 @@ void sys_info(void) {
}
void * malloc(size_t size)
/* void * malloc(size_t size)
{
void * ret;
if((ret = pvPortMalloc(size)) == NULL)
@@ -99,7 +100,7 @@ void * zalloc(size_t size)
void *calloc(size_t count, size_t size)
{
return zalloc(count * size);
}
} */
void free(void *pv)
{

View File

@@ -16,6 +16,7 @@ extern "C" {
#endif
#include "WiFiClient.h"
#include "WiFiServer.h"
class WiFiClass : public IWiFiClass,
public IWiFiGenericClass,

View File

@@ -21,9 +21,9 @@ bool WiFiClass::softAP(const char *ssid, const char *passphrase, int channel, bo
if (passphrase) {
strcpy((char *)ap_password, passphrase);
wifi.security_type = RTW_SECURITY_WPA2_AES_PSK;
wifi.password = ap_password;
wifi.password_len = strlen(passphrase);
ap.security_type = RTW_SECURITY_WPA2_AES_PSK;
ap.password = ap_password;
ap.password_len = strlen(passphrase);
}
dhcps_deinit();
@@ -96,6 +96,7 @@ bool WiFiClass::softAPdisconnect(bool wifiOff) {
uint8_t WiFiClass::softAPgetStationNum() {
// TODO
// the struct is at wifi_conf.c:2576
return 0;
}

View File

@@ -1,38 +1,27 @@
#include "WiFiClient.h"
#include "WiFiPriv.h"
// I think I don't understand how that works.
// For some reason, LwIP uses a different (extern) errno,
// while this macro refers to a function __errno, which
// reads a totally different variable.
#undef errno
#include <lwip/arch.h>
// disable #defines removing lwip_ prefix
#undef LWIP_COMPAT_SOCKETS
#define LWIP_COMPAT_SOCKETS 0
#include <lwip/sockets.h>
WiFiClient::WiFiClient() : _sock(-1), _connected(false) {
WiFiClient::WiFiClient() {
DiagPrintf("WiFiClient()\r\n");
_sock = -1;
_connected = false;
_rxBuffer = NULL;
_timeout = WIFI_CLIENT_CONNECT_TIMEOUT;
}
WiFiClient::WiFiClient(int sock) {
_sock = sock;
_connected = true;
_rxBuffer.reset(new LwIPRxBuffer(sock));
_rxBuffer = new LwIPRxBuffer(sock);
_timeout = WIFI_CLIENT_CONNECT_TIMEOUT;
}
WiFiClient::~WiFiClient() {
stop();
}
WiFiClient &WiFiClient::operator=(const IWiFiClient &other) {
stop();
// _sock = other._sock;
// _connected = other._connected;
// _rxBuffer = other._rxBuffer;
WiFiClient *oth = (WiFiClient *)&other;
_sock = oth->_sock;
_connected = oth->_connected;
_rxBuffer = oth->_rxBuffer;
return *this;
}
@@ -115,7 +104,8 @@ int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
lwip_close(_sock);
_sock = sock;
_connected = true;
_rxBuffer.reset(new LwIPRxBuffer(_sock));
free(_rxBuffer);
_rxBuffer = new LwIPRxBuffer(_sock);
return 1;
}
@@ -264,6 +254,7 @@ void WiFiClient::stop() {
lwip_close(_sock);
_sock = -1;
_connected = false;
free(_rxBuffer);
_rxBuffer = NULL;
}
@@ -292,7 +283,7 @@ uint8_t WiFiClient::connected() {
return _connected;
}
IPAddress getaddr(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) {
IPAddress __attribute__((noinline)) getaddr(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) {
struct sockaddr addr;
socklen_t len = sizeof(addr);
func(sock, &addr, &len);
@@ -300,7 +291,7 @@ IPAddress getaddr(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) {
return IPAddress((uint32_t)(s->sin_addr.s_addr));
}
uint16_t getport(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) {
uint16_t __attribute__((noinline)) getport(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) {
struct sockaddr addr;
socklen_t len = sizeof(addr);
func(sock, &addr, &len);

View File

@@ -2,18 +2,16 @@
#include <api/LwIPRxBuffer.h>
#include <api/WiFiClient.h>
#include <memory>
class WiFiClient : public IWiFiClient {
private:
int _sock;
bool _connected;
std::shared_ptr<LwIPRxBuffer> _rxBuffer;
LwIPRxBuffer *_rxBuffer;
public:
WiFiClient();
WiFiClient(int sock);
~WiFiClient();
int connect(IPAddress ip, uint16_t port);
int connect(const char *host, uint16_t port);

View File

@@ -16,12 +16,11 @@ bool WiFiClass::mode(WiFiMode mode) {
// initialize wifi first
LwIP_Init();
reset_wifi_struct();
wifi_manager_init();
// wifi_manager_init(); // these are events!
_initialized = true;
}
if (currentMode) {
// stop wifi to change mode
dhcps_deinit();
if (wifi_off() != RTW_SUCCESS)
return false;
vTaskDelay(20);
@@ -29,10 +28,6 @@ bool WiFiClass::mode(WiFiMode mode) {
if (wifi_on((rtw_mode_t)mode) != RTW_SUCCESS)
return false;
if (mode & WIFI_MODE_AP) {
dhcps_init(NETIF_RTW_STA);
}
return true;
}
@@ -52,7 +47,7 @@ WiFiStatus WiFiClass::status() {
bool WiFiClass::enableSTA(bool enable) {
WiFiMode currentMode = getMode();
if ((currentMode & WIFI_MODE_STA != 0) != enable) {
if (((currentMode & WIFI_MODE_STA) != 0) != enable) {
return mode((WiFiMode)(currentMode ^ WIFI_MODE_STA));
}
return true;
@@ -60,7 +55,7 @@ bool WiFiClass::enableSTA(bool enable) {
bool WiFiClass::enableAP(bool enable) {
WiFiMode currentMode = getMode();
if ((currentMode & WIFI_MODE_AP != 0) != enable) {
if (((currentMode & WIFI_MODE_AP) != 0) != enable) {
return mode((WiFiMode)(currentMode ^ WIFI_MODE_AP));
}
return true;

View File

@@ -18,6 +18,18 @@ extern "C" {
#define WIFI_CLIENT_SELECT_TIMEOUT 1000
#define WIFI_CLIENT_FLUSH_BUF_SIZE 1024
// I think I don't understand how that works.
// For some reason, LwIP uses a different (extern) errno,
// while this macro refers to a function __errno, which
// reads a totally different variable.
#undef errno
#include <lwip/arch.h>
// disable #defines removing lwip_ prefix
#undef LWIP_COMPAT_SOCKETS
#define LWIP_COMPAT_SOCKETS 0
#include <lwip/sockets.h>
#include <autoconf.h>
#include <dhcp/dhcps.h>
#include <lwip/api.h>

View File

@@ -0,0 +1,104 @@
#include "WiFiServer.h"
#include "WiFiPriv.h"
WiFiServer::WiFiServer(uint16_t port, uint8_t maxClients)
: _sock(-1), _sockAccepted(-1), _port(port), _maxClients(maxClients), _active(false), _noDelay(false) {}
WiFiServer::operator bool() {
return _active;
}
bool WiFiServer::begin(uint16_t port, bool reuseAddr) {
if (_active)
return true;
if (port)
_port = port;
_sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (_sock < 0)
return false;
int enable = reuseAddr;
lwip_setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(_port);
if (lwip_bind(_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
return false;
if (lwip_listen(_sock, _maxClients) < 0)
return false;
lwip_fcntl(_sock, F_SETFL, O_NONBLOCK);
_active = true;
_noDelay = false;
_sockAccepted = -1;
}
void WiFiServer::end() {
if (_sock == -1)
return;
lwip_close(_sock);
_sock = -1;
_active = -1;
}
WiFiClient WiFiServer::accept() {
if (!_active)
return WiFiClient();
int sock;
if (_sockAccepted) {
sock = _sockAccepted;
_sockAccepted = -1;
} else {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
sock = lwip_accept(_sock, (struct sockaddr *)&addr, &len);
}
if (sock >= 0) {
int enable = 1;
if (lwip_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)) == ERR_OK) {
enable = _noDelay;
if (lwip_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)) == ERR_OK) {
return WiFiClient(sock);
}
}
}
return WiFiClient();
}
int WiFiServer::setTimeout(uint32_t seconds) {
struct timeval tv;
tv.tv_sec = seconds;
tv.tv_usec = 0;
if (lwip_setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
return -1;
return lwip_setsockopt(_sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
}
void WiFiServer::setNoDelay(bool noDelay) {
_noDelay = noDelay;
}
bool WiFiServer::getNoDelay() {
return _noDelay;
}
bool WiFiServer::hasClient() {
if (_sockAccepted >= 0) {
return true;
}
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
_sockAccepted = lwip_accept(_sock, (struct sockaddr *)&addr, &len);
if (_sockAccepted >= 0) {
return true;
}
return false;
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include <api/WiFiServer.h>
#include "WiFiClient.h"
class WiFiServer : public IWiFiServer<WiFiClient> {
private:
int _sock;
int _sockAccepted;
uint16_t _port;
uint8_t _maxClients;
bool _active;
bool _noDelay = false;
public:
WiFiServer(uint16_t port = 80, uint8_t maxClients = 4);
operator bool();
bool begin(uint16_t port = 0, bool reuseAddr = true);
void end();
WiFiClient accept();
size_t write(const uint8_t *buffer, size_t size) {
return 0;
}
void stopAll() {}
int setTimeout(uint32_t seconds);
void setNoDelay(bool noDelay);
bool getNoDelay();
bool hasClient();
};

View File

@@ -17,6 +17,7 @@ env.Prepend(
# fmt: off
join(API_DIR),
join(LT_API_DIR),
join(LT_API_DIR, "compat"),
# fmt: on
]
)

View File

@@ -61,6 +61,7 @@ env.Append(
("bool", "bool"),
# enable LwIPRxBuffer
"LT_HAS_LWIP",
("zalloc", "os_zalloc"),
],
LINKFLAGS=[
"--specs=nosys.specs",
@@ -170,6 +171,7 @@ sources_libs = [
"+<" + CORE_DIR +"/libraries/WiFi/WiFiClient.cpp>",
"+<" + CORE_DIR +"/libraries/WiFi/WiFiGeneric.cpp>",
"+<" + CORE_DIR +"/libraries/WiFi/WiFiScan.cpp>",
"+<" + CORE_DIR +"/libraries/WiFi/WiFiServer.cpp>",
"+<" + CORE_DIR +"/libraries/WiFi/WiFiSTA.cpp>",
# fmt: on
]

View File

@@ -1,4 +1,4 @@
#include <wifi_conf.h>
// wifi_mode is declared in atcmd_wifi.c, which is a part of the built-in trash console
rtw_mode_t wifi_mode = RTW_MODE_STA;
rtw_mode_t wifi_mode = RTW_MODE_NONE;