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:
committed by
Henrik Ekblad
parent
95f719b604
commit
a4c7b249c1
@@ -19,9 +19,11 @@
|
||||
* Based on Arduino ethernet library, Copyright (c) 2010 Arduino LLC. All right reserved.
|
||||
*/
|
||||
|
||||
#include "EthernetClient.h"
|
||||
#include <cstdio>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <cstring>
|
||||
@@ -30,7 +32,6 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <errno.h>
|
||||
#include "log.h"
|
||||
#include "EthernetClient.h"
|
||||
|
||||
EthernetClient::EthernetClient() : _sock(-1)
|
||||
{
|
||||
@@ -67,7 +68,7 @@ int EthernetClient::connect(const char* host, uint16_t port)
|
||||
}
|
||||
|
||||
if (::connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
|
||||
close(sockfd);
|
||||
::close(sockfd);
|
||||
logError("connect: %s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
@@ -113,8 +114,7 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size)
|
||||
int rc = send(_sock, buf + bytes, size, MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
if (rc == -1) {
|
||||
logError("send: %s\n", strerror(errno));
|
||||
close(_sock);
|
||||
_sock = -1;
|
||||
close();
|
||||
break;
|
||||
}
|
||||
bytes += rc;
|
||||
@@ -141,16 +141,16 @@ int EthernetClient::available()
|
||||
int count = 0;
|
||||
|
||||
if (_sock != -1) {
|
||||
ioctl(_sock, FIONREAD, &count);
|
||||
return count;
|
||||
ioctl(_sock, SIOCINQ, &count);
|
||||
}
|
||||
return 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int EthernetClient::read()
|
||||
{
|
||||
uint8_t b;
|
||||
if ( recv(_sock, &b, 1, 0) > 0 ) {
|
||||
if ( recv(_sock, &b, 1, MSG_DONTWAIT) > 0 ) {
|
||||
// recv worked
|
||||
return b;
|
||||
} else {
|
||||
@@ -159,22 +159,35 @@ int EthernetClient::read()
|
||||
}
|
||||
}
|
||||
|
||||
int EthernetClient::read(uint8_t *buf, size_t size)
|
||||
int EthernetClient::read(uint8_t *buf, size_t bytes)
|
||||
{
|
||||
return recv(_sock, buf, size, 0);
|
||||
return recv(_sock, buf, bytes, MSG_DONTWAIT);
|
||||
}
|
||||
|
||||
int EthernetClient::peek()
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
return recv(_sock, &b, 1, MSG_PEEK | MSG_DONTWAIT);
|
||||
if (recv(_sock, &b, 1, MSG_PEEK | MSG_DONTWAIT) > 0) {
|
||||
return b;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void EthernetClient::flush()
|
||||
{
|
||||
// There isn't much we can do here
|
||||
return;
|
||||
int count = 0;
|
||||
|
||||
if (_sock != -1) {
|
||||
while (true) {
|
||||
ioctl(_sock, SIOCOUTQ, &count);
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EthernetClient::stop()
|
||||
@@ -203,7 +216,7 @@ void EthernetClient::stop()
|
||||
|
||||
// if it hasn't closed, close it forcefully
|
||||
if (s != ETHERNETCLIENT_W5100_CLOSED) {
|
||||
close(_sock);
|
||||
::close(_sock);
|
||||
}
|
||||
_sock = -1;
|
||||
}
|
||||
@@ -249,17 +262,15 @@ uint8_t EthernetClient::status()
|
||||
|
||||
uint8_t EthernetClient::connected()
|
||||
{
|
||||
if (_sock == -1) {
|
||||
return 0;
|
||||
}
|
||||
return status() == ETHERNETCLIENT_W5100_ESTABLISHED || available();
|
||||
}
|
||||
|
||||
if (peek() < 0) {
|
||||
if (errno == EAGAIN) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
void EthernetClient::close()
|
||||
{
|
||||
if (_sock != -1) {
|
||||
::close(_sock);
|
||||
_sock = -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EthernetClient::getSocketNumber()
|
||||
|
||||
Reference in New Issue
Block a user