Linux: Fix Ethernet client and server (#836)

- Fix documentation.
- Add function close() to client class.
- Function connected() now return true if the connection is in
  stablished state or there is still unread data.
- Update hasClient() to check if any client has disconnected.
- Fix _accept() to better handle the case of maximum clients reached.
- Fix peek() to return the next byte of the read queue.
- Simplifies write() of the server class.
- Implements flush().
- Updates read() to non-blocking type, the same way as in Arduino.
This commit is contained in:
Marcelo Aquino
2017-05-13 09:49:16 +02:00
committed by Henrik Ekblad
parent 95f719b604
commit a4c7b249c1
4 changed files with 83 additions and 77 deletions
+27 -37
View File
@@ -19,6 +19,7 @@
* Based on Arduino ethernet library, Copyright (c) 2010 Arduino LLC. All right reserved.
*/
#include "EthernetServer.h"
#include <cstdio>
#include <sys/socket.h>
#include <cstring>
@@ -30,7 +31,6 @@
#include <fcntl.h>
#include "log.h"
#include "EthernetClient.h"
#include "EthernetServer.h"
EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port),
max_clients(max_clients), sockfd(-1)
@@ -108,6 +108,24 @@ void EthernetServer::begin(IPAddress address)
bool EthernetServer::hasClient()
{
// Check if any client has disconnected
for (size_t i = 0; i < clients.size(); ++i) {
EthernetClient client(clients[i]);
if (!client.connected()) {
// Checks if this disconnected client is also on the new clients list
for (std::list<int>::iterator it = new_clients.begin(); it != new_clients.end(); ++it) {
if (*it == clients[i]) {
new_clients.erase(it);
break;
}
}
client.stop();
clients[i] = clients.back();
clients.pop_back();
logDebug("Ethernet client disconnected.\n");
}
}
_accept();
return !new_clients.empty();
@@ -136,14 +154,9 @@ size_t EthernetServer::write(const uint8_t *buffer, size_t size)
while (i < clients.size()) {
EthernetClient client(clients[i]);
if (client.connected()) {
if (client.status() == ETHERNETCLIENT_W5100_ESTABLISHED) {
n += client.write(buffer, size);
i++;
} else if (!client.available()) {
client.stop();
clients[i] = clients.back();
clients.pop_back();
logDebug("Client disconnected.\n");
}
}
@@ -170,36 +183,6 @@ void EthernetServer::_accept()
struct sockaddr_storage client_addr;
char ipstr[INET_ADDRSTRLEN];
if (new_clients.size() + clients.size() == max_clients) {
// no free slots, search for a dead client
bool no_free_slots = true;
for (size_t i = 0; i < clients.size();) {
EthernetClient client(clients[i]);
if (client.connected() || client.available()) {
i++;
} else {
clients[i] = clients.back();
clients.pop_back();
no_free_slots = false;
break;
}
}
if (no_free_slots) {
for (std::list<int>::iterator it = new_clients.begin(); it != new_clients.end(); ++it) {
EthernetClient client(*it);
if (!client.connected() && !client.available()) {
new_clients.erase(it);
no_free_slots = false;
break;
}
}
}
if (no_free_slots) {
logDebug("Max number of ethernet clients reached.\n");
return;
}
}
sin_size = sizeof client_addr;
new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);
if (new_fd == -1) {
@@ -209,6 +192,13 @@ void EthernetServer::_accept()
return;
}
if (clients.size() == max_clients) {
// no free slots, search for a dead client
close(new_fd);
logDebug("Max number of ethernet clients reached.\n");
return;
}
new_clients.push_back(new_fd);
clients.push_back(new_fd);