[realtek-ambz] Add new WiFiClient library
This commit is contained in:
@@ -24,41 +24,46 @@
|
||||
|
||||
class IWiFiClient : public Client {
|
||||
public:
|
||||
IWiFiClient(int fd) {}
|
||||
IWiFiClient() {}
|
||||
|
||||
int connect(IPAddress ip, uint16_t port, int32_t timeout);
|
||||
int connect(const char *host, uint16_t port, int32_t timeout);
|
||||
IWiFiClient(int sock) {}
|
||||
|
||||
size_t write(Stream &stream);
|
||||
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;
|
||||
|
||||
int fd() const;
|
||||
int socket();
|
||||
int setTimeout(uint32_t seconds);
|
||||
virtual size_t write(Stream &stream) = 0;
|
||||
|
||||
IWiFiClient &operator=(const WiFiClient &other);
|
||||
virtual int fd() const = 0;
|
||||
virtual int socket() = 0;
|
||||
virtual int setTimeout(uint32_t seconds) = 0;
|
||||
|
||||
bool operator==(const bool value) {
|
||||
virtual IWiFiClient &operator=(const IWiFiClient &other) = 0;
|
||||
virtual bool operator==(const IWiFiClient &other) const = 0;
|
||||
|
||||
operator bool() {
|
||||
return connected();
|
||||
}
|
||||
|
||||
virtual bool operator==(const bool value) {
|
||||
return bool() == value;
|
||||
}
|
||||
|
||||
bool operator!=(const bool value) {
|
||||
virtual bool operator!=(const bool value) {
|
||||
return bool() != value;
|
||||
}
|
||||
|
||||
bool operator==(const IWiFiClient &);
|
||||
|
||||
bool operator!=(const IWiFiClient &rhs) {
|
||||
return !this->operator==(rhs);
|
||||
virtual bool operator!=(const IWiFiClient &other) {
|
||||
return !this->operator==(other);
|
||||
};
|
||||
|
||||
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;
|
||||
virtual IPAddress remoteIP() const = 0;
|
||||
virtual IPAddress remoteIP(int sock) const = 0;
|
||||
virtual uint16_t remotePort() const = 0;
|
||||
virtual uint16_t remotePort(int sock) const = 0;
|
||||
virtual IPAddress localIP() const = 0;
|
||||
virtual IPAddress localIP(int sock) const = 0;
|
||||
virtual uint16_t localPort() const = 0;
|
||||
virtual uint16_t localPort(int sock) const = 0;
|
||||
|
||||
using Print::write;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
#include "Flash.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <flash_api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
FlashClass::FlashClass() {
|
||||
flash = NULL;
|
||||
}
|
||||
|
||||
@@ -2,15 +2,8 @@
|
||||
|
||||
#include "api/Flash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <flash_api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
struct flash_s;
|
||||
typedef struct flash_s flash_t;
|
||||
|
||||
class FlashClass : public IFlashClass {
|
||||
private:
|
||||
|
||||
@@ -15,6 +15,8 @@ extern "C" {
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#include "WiFiClient.h"
|
||||
|
||||
class WiFiClass : public IWiFiClass,
|
||||
public IWiFiGenericClass,
|
||||
public IWiFiSTAClass,
|
||||
|
||||
341
arduino/realtek-ambz/libraries/WiFi/WiFiClient.cpp
Normal file
341
arduino/realtek-ambz/libraries/WiFi/WiFiClient.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
#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) {
|
||||
_timeout = WIFI_CLIENT_CONNECT_TIMEOUT;
|
||||
}
|
||||
|
||||
WiFiClient::WiFiClient(int sock) {
|
||||
_sock = sock;
|
||||
_connected = true;
|
||||
_rxBuffer.reset(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;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool WiFiClient::operator==(const IWiFiClient &other) const {
|
||||
return _sock == other.fd() && remoteIP() == other.remoteIP() && remotePort() == other.remotePort();
|
||||
}
|
||||
|
||||
int WiFiClient::connect(IPAddress ip, uint16_t port) {
|
||||
return connect(ip, port, _timeout);
|
||||
}
|
||||
|
||||
int WiFiClient::connect(const char *host, uint16_t port) {
|
||||
return connect(host, port, _timeout);
|
||||
}
|
||||
|
||||
int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout) {
|
||||
IPAddress ip = WiFi.hostByName(host);
|
||||
if (!ip)
|
||||
return 0;
|
||||
return connect(ip, port, timeout);
|
||||
}
|
||||
|
||||
int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
int sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sock < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
lwip_fcntl(sock, F_SETFL, lwip_fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = ip;
|
||||
addr.sin_port = htons(port);
|
||||
fd_set fdset;
|
||||
struct timeval tv;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sock, &fdset);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = timeout * 1000;
|
||||
|
||||
int res = lwip_connect(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (res < 0 && errno != EINPROGRESS) {
|
||||
printf("lwip_connect() errno %d\r\n", errno);
|
||||
lwip_close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = lwip_select(sock + 1, NULL, &fdset, NULL, timeout < 0 ? NULL : &tv);
|
||||
if (res < 0) {
|
||||
printf("lwip_select() errno %d\r\n", errno);
|
||||
lwip_close(sock);
|
||||
return 0;
|
||||
}
|
||||
if (res == 0) {
|
||||
printf("lwip_select() timeout errno %d\r\n", errno);
|
||||
lwip_close(sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sockerr;
|
||||
socklen_t len = (socklen_t)sizeof(sockerr);
|
||||
res = lwip_getsockopt(sock, SOL_SOCKET, SO_ERROR, &sockerr, &len);
|
||||
|
||||
if (res < 0 || sockerr != 0) {
|
||||
lwip_close(sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int enable = 1;
|
||||
lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
lwip_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
||||
lwip_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));
|
||||
lwip_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
|
||||
|
||||
lwip_fcntl(sock, F_SETFL, lwip_fcntl(sock, F_GETFL, 0) & ~O_NONBLOCK);
|
||||
|
||||
if (_sock != -1)
|
||||
lwip_close(_sock);
|
||||
_sock = sock;
|
||||
_connected = true;
|
||||
_rxBuffer.reset(new LwIPRxBuffer(_sock));
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(uint8_t data) {
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(Stream &stream) {
|
||||
uint8_t *buf = (uint8_t *)malloc(1360);
|
||||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
size_t toRead = 0, toWrite = 0, written = 0;
|
||||
size_t available = stream.available();
|
||||
while (available) {
|
||||
toRead = (available > 1360) ? 1360 : available;
|
||||
toWrite = stream.readBytes(buf, toRead);
|
||||
written += write(buf, toWrite);
|
||||
available = stream.available();
|
||||
}
|
||||
free(buf);
|
||||
return written;
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(const uint8_t *buf, size_t size) {
|
||||
if (_sock < 0 || !_connected || !size) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int retry = WIFI_CLIENT_WRITE_RETRY;
|
||||
int written = 0;
|
||||
while (retry) {
|
||||
fd_set fdset;
|
||||
struct timeval tv;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(_sock, &fdset);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = WIFI_CLIENT_SELECT_TIMEOUT * 1000;
|
||||
retry--;
|
||||
|
||||
if (lwip_select(_sock + 1, NULL, &fdset, NULL, &tv) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FD_ISSET(_sock, &fdset)) {
|
||||
int res = lwip_send(_sock, buf, size, MSG_DONTWAIT);
|
||||
if (res > 0) {
|
||||
written += res;
|
||||
if (res >= size) {
|
||||
retry = 0;
|
||||
} else {
|
||||
buf += res;
|
||||
size -= res;
|
||||
retry = WIFI_CLIENT_WRITE_RETRY;
|
||||
}
|
||||
} else if (res < 0 && errno != EAGAIN) {
|
||||
setWriteError(res);
|
||||
_connected = false;
|
||||
retry = 0;
|
||||
} else {
|
||||
// Try again
|
||||
}
|
||||
}
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
int WiFiClient::available() {
|
||||
if (!_connected)
|
||||
return 0;
|
||||
int res = _rxBuffer->available();
|
||||
if (_rxBuffer->failed()) {
|
||||
stop();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int WiFiClient::fd() const {
|
||||
return _sock;
|
||||
}
|
||||
|
||||
int WiFiClient::socket() {
|
||||
return _sock;
|
||||
}
|
||||
|
||||
int WiFiClient::setTimeout(uint32_t seconds) {
|
||||
Client::setTimeout(seconds * 1000);
|
||||
lwip_setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &_timeout, sizeof(_timeout));
|
||||
return lwip_setsockopt(_sock, SOL_SOCKET, SO_SNDTIMEO, &_timeout, sizeof(_timeout));
|
||||
}
|
||||
|
||||
int WiFiClient::read() {
|
||||
uint8_t data;
|
||||
int res = read(&data, 1);
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (res == 0)
|
||||
return -1;
|
||||
return data;
|
||||
}
|
||||
|
||||
int WiFiClient::read(uint8_t *buf, size_t size) {
|
||||
int res = -1;
|
||||
if (_rxBuffer) {
|
||||
res = _rxBuffer->read(buf, size);
|
||||
if (_rxBuffer->failed()) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int WiFiClient::peek() {
|
||||
int res = -1;
|
||||
if (_rxBuffer) {
|
||||
res = _rxBuffer->peek();
|
||||
if (_rxBuffer->failed()) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void WiFiClient::flush() {
|
||||
int res;
|
||||
size_t len = available();
|
||||
if (!len)
|
||||
return;
|
||||
uint8_t *buf = (uint8_t *)malloc(WIFI_CLIENT_FLUSH_BUF_SIZE);
|
||||
if (!buf)
|
||||
return;
|
||||
while (len) {
|
||||
res = lwip_recv(_sock, buf, LWIP_MIN(len, WIFI_CLIENT_FLUSH_BUF_SIZE), MSG_DONTWAIT);
|
||||
if (res < 0) {
|
||||
stop();
|
||||
break;
|
||||
}
|
||||
len -= res;
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void WiFiClient::stop() {
|
||||
if (_sock != -1)
|
||||
lwip_close(_sock);
|
||||
_sock = -1;
|
||||
_connected = false;
|
||||
_rxBuffer = NULL;
|
||||
}
|
||||
|
||||
uint8_t WiFiClient::connected() {
|
||||
if (_connected) {
|
||||
uint8_t dummy;
|
||||
if (lwip_recv(_sock, &dummy, 0, MSG_DONTWAIT) < 0) {
|
||||
switch (errno) {
|
||||
case EWOULDBLOCK:
|
||||
case ENOENT: // caused by vfs
|
||||
_connected = true;
|
||||
break;
|
||||
case ENOTCONN:
|
||||
case EPIPE:
|
||||
case ECONNRESET:
|
||||
case ECONNREFUSED:
|
||||
case ECONNABORTED:
|
||||
_connected = false;
|
||||
break;
|
||||
default:
|
||||
_connected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _connected;
|
||||
}
|
||||
|
||||
IPAddress getaddr(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) {
|
||||
struct sockaddr addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
func(sock, &addr, &len);
|
||||
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
|
||||
return IPAddress((uint32_t)(s->sin_addr.s_addr));
|
||||
}
|
||||
|
||||
uint16_t getport(int sock, int (*func)(int, struct sockaddr *, socklen_t *)) {
|
||||
struct sockaddr addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
func(sock, &addr, &len);
|
||||
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
|
||||
return ntohs(s->sin_port);
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::remoteIP() const {
|
||||
return getaddr(_sock, lwip_getpeername);
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::remoteIP(int fd) const {
|
||||
return getaddr(fd, lwip_getpeername);
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::remotePort() const {
|
||||
return getport(_sock, lwip_getpeername);
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::remotePort(int fd) const {
|
||||
return getport(fd, lwip_getpeername);
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::localIP() const {
|
||||
return getaddr(_sock, lwip_getsockname);
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::localIP(int fd) const {
|
||||
return getaddr(fd, lwip_getsockname);
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::localPort() const {
|
||||
return getport(_sock, lwip_getsockname);
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::localPort(int fd) const {
|
||||
return getport(fd, lwip_getsockname);
|
||||
}
|
||||
51
arduino/realtek-ambz/libraries/WiFi/WiFiClient.h
Normal file
51
arduino/realtek-ambz/libraries/WiFi/WiFiClient.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <api/LwIPRxBuffer.h>
|
||||
#include <api/WiFiClient.h>
|
||||
#include <memory>
|
||||
|
||||
class WiFiClient : public IWiFiClient {
|
||||
private:
|
||||
int _sock;
|
||||
bool _connected;
|
||||
std::shared_ptr<LwIPRxBuffer> _rxBuffer;
|
||||
|
||||
public:
|
||||
WiFiClient();
|
||||
WiFiClient(int sock);
|
||||
~WiFiClient();
|
||||
|
||||
int connect(IPAddress ip, uint16_t port);
|
||||
int connect(const char *host, uint16_t port);
|
||||
int connect(IPAddress ip, uint16_t port, int32_t timeout);
|
||||
int connect(const char *host, uint16_t port, int32_t timeout);
|
||||
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const uint8_t *buf, size_t size);
|
||||
size_t write(Stream &stream);
|
||||
|
||||
int available();
|
||||
int fd() const;
|
||||
int socket();
|
||||
int setTimeout(uint32_t seconds);
|
||||
|
||||
int read();
|
||||
int read(uint8_t *buf, size_t size);
|
||||
int peek();
|
||||
void flush();
|
||||
void stop();
|
||||
uint8_t connected();
|
||||
|
||||
WiFiClient &operator=(const IWiFiClient &other);
|
||||
|
||||
bool operator==(const IWiFiClient &other) const;
|
||||
|
||||
IPAddress remoteIP() const;
|
||||
IPAddress remoteIP(int sock) const;
|
||||
uint16_t remotePort() const;
|
||||
uint16_t remotePort(int sock) const;
|
||||
IPAddress localIP() const;
|
||||
IPAddress localIP(int sock) const;
|
||||
uint16_t localPort() const;
|
||||
uint16_t localPort(int sock) const;
|
||||
};
|
||||
@@ -4,7 +4,19 @@
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#define LWIP_NETIF_HOSTNAME 1 // this is defined in PIO builder
|
||||
// these are defined in PIO builder (for IDE to understand)
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
#define LWIP_NETIF_HOSTNAME 1
|
||||
// this should define all errno values, as well as the extern int
|
||||
#define LWIP_PROVIDE_ERRNO 1
|
||||
#define LWIP_SO_RCVBUF 1
|
||||
|
||||
#define MAX_SOCK_NUM 4
|
||||
#define WIFI_CLIENT_CONNECT_TIMEOUT 3000
|
||||
#define WIFI_CLIENT_READ_TIMEOUT 3000
|
||||
#define WIFI_CLIENT_WRITE_RETRY 10
|
||||
#define WIFI_CLIENT_SELECT_TIMEOUT 1000
|
||||
#define WIFI_CLIENT_FLUSH_BUF_SIZE 1024
|
||||
|
||||
#include <autoconf.h>
|
||||
#include <dhcp/dhcps.h>
|
||||
@@ -12,6 +24,7 @@ extern "C" {
|
||||
#include <lwip/dns.h>
|
||||
#include <lwip/err.h>
|
||||
#include <lwip_netconf.h>
|
||||
#include <sys/time.h>
|
||||
#include <wifi_conf.h>
|
||||
#include <wifi_constants.h>
|
||||
#include <wifi_structures.h>
|
||||
|
||||
Reference in New Issue
Block a user