Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
27d36d8
Fix MacOS (case) filename clashes
manchoz Jul 6, 2021
357dba7
Add examples
manchoz Jul 6, 2021
c39cfee
Add helpers begin methods
manchoz Feb 1, 2021
05a1b80
Fix WebClient example
manchoz Feb 1, 2021
540e0ab
Add Static IP support
manchoz Jul 5, 2021
a5e512a
Manage Client status
manchoz Jul 5, 2021
d1501d0
Add support for Static Network configuration
manchoz Jul 5, 2021
b04124a
Update examples
manchoz Jul 5, 2021
817b47a
Add forgotten mac parameter
manchoz Jul 5, 2021
cf184fd
Add checks on socket validity before operations
manchoz Jul 6, 2021
9172c17
Manage sockets already connected
manchoz Jul 6, 2021
4aad72b
Add client socket management
manchoz Jul 6, 2021
5f802c1
WiFi: Cleanup libraries and error handling
facchinm Jul 7, 2021
4ded56c
WiFi: make library compliant with Arduino APIs
facchinm Jul 7, 2021
ec4109d
Initial: start moving WiFi generic classes into a standalone library
facchinm Jul 8, 2021
e0e8647
WiFi: port Client and Server to the new wrapper class
facchinm Jul 8, 2021
02b1239
TEMP: MbedClient: add horrible Client "constructor"
facchinm Jul 8, 2021
73cbc6b
WiFi: port UDP to new MbedUdp class
facchinm Jul 8, 2021
175d09f
Ethernet: port library to SocketWrapper
facchinm Jul 8, 2021
37edb74
MbedClient: fix copy constructor
facchinm Jul 8, 2021
974f4c2
Network: cleanup libraries and licenses
facchinm Jul 9, 2021
d4bb9d8
Network: apply clang-format on libraries
facchinm Jul 9, 2021
4340946
MbedUdp: make socket non blocking
facchinm Jul 9, 2021
123694b
SocketWrapper: fix download() API visibility
facchinm Jul 9, 2021
bc92047
MbedUDP: take into account write() errors
facchinm Jul 9, 2021
7fd7c9a
Remove protected leftovers
manchoz Jul 13, 2021
d9fa625
Add EthernetServer::available()
manchoz Jul 13, 2021
8c7962f
Add ::dnsServerIP
manchoz Jul 13, 2021
a175f35
Unlock mutexes before return
manchoz Jul 13, 2021
15ca271
Fix Typo
manchoz Jul 13, 2021
d3e8ee3
Manage copy and assignement
manchoz Jul 13, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
WiFi: make library compliant with Arduino APIs
This includes non-blocking available() and allows compatibility with a broader range of existing libraries
  • Loading branch information
facchinm authored and manchoz committed Jul 14, 2021
commit 4ded56c67c5d224e41336adfbcf8f1ae34c5717b
195 changes: 144 additions & 51 deletions libraries/WiFi/src/WiFiClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@

extern WiFiClass WiFi;

#ifndef WIFI_TCP_BUFFER_SIZE
#define WIFI_TCP_BUFFER_SIZE 1508
#endif

#ifndef SOCKET_TIMEOUT
#define SOCKET_TIMEOUT 1000
#define SOCKET_TIMEOUT 1500
#endif

arduino::WiFiClient::WiFiClient():
Expand All @@ -19,45 +15,96 @@ uint8_t arduino::WiFiClient::status() {
return _status;
}

void arduino::WiFiClient::readSocket() {
while (1) {
event->wait_any(0xFF, 100);
uint8_t data[SOCKET_BUFFER_SIZE];
int ret = NSAPI_ERROR_WOULD_BLOCK;
do {
mutex->lock();
if (rxBuffer.availableForStore() == 0) {
yield();
}
if (sock == nullptr || (closing && borrowed_socket)) {
goto cleanup;
}
ret = sock->recv(data, rxBuffer.availableForStore());
if (ret < 0 && ret != NSAPI_ERROR_WOULD_BLOCK) {
goto cleanup;
}
for (int i = 0; i < ret; i++) {
rxBuffer.store_char(data[i]);
}
_status = true;
mutex->unlock();
} while (ret == NSAPI_ERROR_WOULD_BLOCK || ret > 0);
}
cleanup:
_status = false;
mutex->unlock();
return;
}

void arduino::WiFiClient::getStatus() {
if (sock == nullptr) {
_status = false;
return;
event->set(1);
}

void arduino::WiFiClient::setSocket(Socket* _sock) {
sock = _sock;
configureSocket(sock);
}

void arduino::WiFiClient::configureSocket(Socket* _s) {
_s->set_timeout(0);
_s->set_blocking(false);

if (event == nullptr) {
event = new rtos::EventFlags;
}
if (mutex == nullptr) {
mutex = new rtos::Mutex;
}

uint8_t data[256];
int ret = sock->recv(data, rxBuffer.availableForStore());
for (int i = 0; i < ret; i++) {
rxBuffer.store_char(data[i]);
}
if (ret < 0 && ret != NSAPI_ERROR_WOULD_BLOCK) {
_status = false;
}
_status = true;
mutex->lock();
if (reader_th == nullptr) {
reader_th = new rtos::Thread;
reader_th->start(mbed::callback(this, &WiFiClient::readSocket));
}
mutex->unlock();
_s->sigio(mbed::callback(this, &WiFiClient::getStatus));
_status = true;
}

int arduino::WiFiClient::connect(SocketAddress socketAddress) {
if (sock == nullptr) {
sock = new TCPSocket();
if(static_cast<TCPSocket*>(sock)->open(WiFi.getNetwork()) != NSAPI_ERROR_OK){
return 0;
}
sock = new TCPSocket();
_own_socket = true;
}
//sock->sigio(mbed::callback(this, &WiFiClient::getStatus));
//sock->set_blocking(false);
if (sock == nullptr) {
return 0;
}

if(static_cast<TCPSocket*>(sock)->open(WiFi.getNetwork()) != NSAPI_ERROR_OK){
return 0;
}

address = socketAddress;
sock->set_timeout(SOCKET_TIMEOUT);
nsapi_error_t returnCode = static_cast<TCPSocket*>(sock)->connect(socketAddress);
int ret = 0;

switch (returnCode) {
case NSAPI_ERROR_IS_CONNECTED:
case NSAPI_ERROR_OK: {
ret = 1;
break;
}
}
if (ret == 1)

if (ret == 1) {
configureSocket(sock);
_status = true;
} else {
_status = false;
}

return ret;
}
Expand All @@ -73,28 +120,48 @@ int arduino::WiFiClient::connect(const char *host, uint16_t port) {
return connect(socketAddress);
}

int arduino::WiFiClient::connectSSL(SocketAddress socketAddress){
int arduino::WiFiClient::connectSSL(SocketAddress socketAddress) {
if (sock == nullptr) {
sock = new TLSSocket();
if(static_cast<TLSSocket*>(sock)->open(WiFi.getNetwork()) != NSAPI_ERROR_OK){
return 0;
}
_own_socket = true;
}
if (sock == nullptr) {
return 0;
}

if (beforeConnect) {
beforeConnect();
}
sock->set_timeout(SOCKET_TIMEOUT);

if(static_cast<TLSSocket*>(sock)->open(WiFi.getNetwork()) != NSAPI_ERROR_OK){
return 0;
}

address = socketAddress;

restart_connect:
nsapi_error_t returnCode = static_cast<TLSSocket*>(sock)->connect(socketAddress);
int ret = 0;

switch (returnCode) {
case NSAPI_ERROR_IS_CONNECTED:
case NSAPI_ERROR_OK: {
ret = 1;
break;
}
case NSAPI_ERROR_IS_CONNECTED:
case NSAPI_ERROR_OK: {
ret = 1;
break;
}
case NSAPI_ERROR_IN_PROGRESS:
case NSAPI_ERROR_ALREADY: {
delay(100);
goto restart_connect;
}
}
if (ret == 1)

if (ret == 1) {
configureSocket(sock);
_status = true;
} else {
_status = false;
}

return ret;
}
Expand All @@ -111,36 +178,38 @@ int arduino::WiFiClient::connectSSL(const char *host, uint16_t port) {
}

size_t arduino::WiFiClient::write(uint8_t c) {
if (sock == nullptr)
return 0;
auto ret = sock->send(&c, 1);
return ret;
return write(&c, 1);
}

size_t arduino::WiFiClient::write(const uint8_t *buf, size_t size) {
if (sock == nullptr)
return 0;

auto ret = sock->send(buf, size);
return ret;
sock->set_blocking(true);
sock->set_timeout(SOCKET_TIMEOUT);
sock->send(buf, size);
configureSocket(sock);
return size;
}

int arduino::WiFiClient::available() {
if (rxBuffer.available() == 0) {
getStatus();
}
return rxBuffer.available();
int ret = rxBuffer.available();
return ret;
}

int arduino::WiFiClient::read() {
mutex->lock();
if (!available()) {
return -1;
}

return rxBuffer.read_char();
int ret = rxBuffer.read_char();
mutex->unlock();
return ret;
}

int arduino::WiFiClient::read(uint8_t *data, size_t len) {
mutex->lock();
int avail = available();

if (!avail) {
Expand All @@ -154,6 +223,7 @@ int arduino::WiFiClient::read(uint8_t *data, size_t len) {
for (size_t i = 0; i < len; i++) {
data[i] = rxBuffer.read_char();
}
mutex->unlock();

return len;
}
Expand All @@ -167,15 +237,38 @@ void arduino::WiFiClient::flush() {
}

void arduino::WiFiClient::stop() {
if (sock != nullptr) {
sock->close();
if (mutex != nullptr) {
mutex->lock();
}
if (sock != nullptr && borrowed_socket == false) {
if (_own_socket) {
delete sock;
} else {
sock->close();
}
sock = nullptr;
}
closing = true;
if (mutex != nullptr) {
mutex->unlock();
}
if (reader_th != nullptr) {
reader_th->join();
delete reader_th;
reader_th = nullptr;
}
if (event != nullptr) {
delete event;
event = nullptr;
}
if (mutex != nullptr) {
delete mutex;
mutex = nullptr;
}
_status = false;
}

uint8_t arduino::WiFiClient::connected() {
getStatus();
return _status;
}

Expand Down
41 changes: 33 additions & 8 deletions libraries/WiFi/src/WiFiClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,33 @@
#include "api/IPAddress.h"
#include "TLSSocket.h"
#include "TCPSocket.h"
#include "rtos.h"

#ifndef SOCKET_BUFFER_SIZE
#define SOCKET_BUFFER_SIZE 256
#endif

namespace arduino {

class WiFiClient : public arduino::Client {

public:
WiFiClient();
WiFiClient(WiFiClient* orig) {
/*
this->reader_th = orig->reader_th;
this->event = orig->event;
this->mutex = orig->mutex;
this->sock = orig->sock;
this->_status = orig->_status;
this->rxBuffer = orig->rxBuffer;
*/
this->sock = orig->sock;
orig->borrowed_socket = true;
orig->stop();
this->setSocket(orig->sock);
}

virtual ~WiFiClient() {
stop();
}
Expand All @@ -54,12 +74,11 @@ class WiFiClient : public arduino::Client {
void stop();
uint8_t connected();
operator bool() {
return sock != NULL;
return sock != nullptr;
}

void setSocket(Socket* _sock) {
sock = _sock;
}
void setSocket(Socket* _sock);
void configureSocket(Socket* _s);

IPAddress remoteIP();
uint16_t remotePort();
Expand All @@ -76,13 +95,19 @@ class WiFiClient : public arduino::Client {
}

private:
static uint16_t _srcport;
Socket* sock;
RingBufferN<256> rxBuffer;
bool _status;
Socket* sock = nullptr;
RingBufferN<SOCKET_BUFFER_SIZE> rxBuffer;
bool _status = false;
bool borrowed_socket = false;
bool _own_socket = false;
bool closing = false;
mbed::Callback<int(void)> beforeConnect;
SocketAddress address;
rtos::Thread* reader_th = nullptr;
rtos::EventFlags* event = nullptr;
rtos::Mutex* mutex = nullptr;

void readSocket();
void getStatus();
};

Expand Down
7 changes: 0 additions & 7 deletions libraries/WiFi/src/WiFiSSLClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,6 @@ class WiFiSSLClient : public arduino::WiFiClient {
int connect(const char* host, uint16_t port) {
return connectSSL(host, port);
}
void stop() {
if (sock != NULL) {
sock->close();
delete ((TLSSocket*)sock);
sock = NULL;
}
}

private:
int setRootCA() {
Expand Down
Loading