pip micro disable piintrospection piwaitevent

PIP_NO_SOCET
This commit is contained in:
2025-10-18 11:20:18 +03:00
parent 4885623492
commit cf89d77981
14 changed files with 506 additions and 459 deletions

View File

@@ -18,64 +18,65 @@
*/
#include "piethernet.h"
#include "piconfig.h"
#include "piconstchars.h"
#include "piincludes_p.h"
#include "piliterals.h"
#include "pipropertystorage.h"
#include "pisysteminfo.h"
#include "pitranslator.h"
// clang-format off
#ifdef QNX
# include <arpa/inet.h>
# include <fcntl.h>
# include <hw/nicinfo.h>
# include <ifaddrs.h>
# include <net/if.h>
# include <net/if_dl.h>
# include <netdb.h>
# include <netinet/in.h>
# include <sys/ioctl.h>
# include <sys/socket.h>
# include <sys/time.h>
# include <sys/types.h>
# ifdef BLACKBERRY
# include <netinet/in.h>
# else
# include <sys/dcmd_io-net.h>
# endif
# define ip_mreqn ip_mreq
# define imr_address imr_interface
#else
# ifdef WINDOWS
# include <io.h>
# include <winsock2.h>
# include <iphlpapi.h>
# include <psapi.h>
# include <ws2tcpip.h>
# define ip_mreqn ip_mreq
# define imr_address imr_interface
# else
# include <fcntl.h>
# include <sys/ioctl.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <arpa/inet.h>
# include <sys/socket.h>
# include <netdb.h>
# include <net/if.h>
# if !defined(ANDROID) && !defined(LWIP)
# include <ifaddrs.h>
# endif
# ifdef LWIP
# include <lwip/sockets.h>
# endif
# endif
#endif
// clang-format on
#include "piwaitevent_p.h"
#ifndef PIP_NO_SOCKET
#include <errno.h>
# include "piconfig.h"
# include "piconstchars.h"
# include "piincludes_p.h"
# include "piliterals.h"
# include "pipropertystorage.h"
# include "pisysteminfo.h"
# include "pitranslator.h"
# ifdef QNX
# include <arpa/inet.h>
# include <fcntl.h>
# include <hw/nicinfo.h>
# include <ifaddrs.h>
# include <net/if.h>
# include <net/if_dl.h>
# include <netdb.h>
# include <netinet/in.h>
# include <sys/ioctl.h>
# include <sys/socket.h>
# include <sys/time.h>
# include <sys/types.h>
# ifdef BLACKBERRY
# include <netinet/in.h>
# else
# include <sys/dcmd_io-net.h>
# endif
# define ip_mreqn ip_mreq
# define imr_address imr_interface
# else
# ifdef WINDOWS
# include <io.h>
# include <iphlpapi.h>
# include <psapi.h>
# include <winsock2.h>
# include <ws2tcpip.h>
# define ip_mreqn ip_mreq
# define imr_address imr_interface
# else
# include <arpa/inet.h>
# include <fcntl.h>
# include <net/if.h>
# include <netdb.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <sys/ioctl.h>
# include <sys/socket.h>
# if !defined(ANDROID) && !defined(LWIP)
# include <ifaddrs.h>
# endif
# ifdef LWIP
# include <lwip/sockets.h>
# endif
# endif
# endif
# include "piwaitevent_p.h"
# include <errno.h>
/** \class PIEthernet piethernet.h
@@ -100,11 +101,11 @@
*
* */
#ifndef WINDOWS
# ifndef WINDOWS
PIString getSockAddr(sockaddr * s) {
return s == 0 ? PIString() : PIStringAscii(inet_ntoa(((sockaddr_in *)s)->sin_addr));
}
#endif
# endif
REGISTER_DEVICE(PIEthernet)
@@ -196,11 +197,11 @@ void PIEthernet::construct() {
setMulticastTTL(1);
server_thread_.setData(this);
server_thread_.setName("_S.tcpserver"_a);
#ifdef MICRO_PIP
# ifdef LWIP
setThreadedReadBufferSize(512);
#else
# else
setThreadedReadBufferSize(64_KiB);
#endif
# endif
// setPriority(piHigh);
}
@@ -304,9 +305,9 @@ bool PIEthernet::openDevice() {
PRIVATE->addr_.sin_addr.s_addr = INADDR_ANY;
else
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
#ifdef QNX
# ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
# endif
// piCout << "bind to" << (params[PIEthernet::Broadcast] ? "255.255.255.255" : ip_) << ":" << port_ << " ...";
int tries = 0;
while ((bind(sock, (sockaddr *)&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 2)) {
@@ -379,14 +380,14 @@ void PIEthernet::applyBuffers() {
void PIEthernet::applyTimeout(int fd, int opt, PISystemTime tm) {
if (fd == 0) return;
// piCoutObj << "setReadIsBlocking" << yes;
#ifdef WINDOWS
// piCoutObj << "setReadIsBlocking" << yes;
# ifdef WINDOWS
DWORD _tm = tm.toMilliseconds();
#else
# else
timeval _tm;
_tm.tv_sec = tm.seconds;
_tm.tv_usec = tm.nanoseconds / 1000;
#endif
# endif
ethSetsockopt(fd, SOL_SOCKET, opt, &_tm, sizeof(_tm));
}
@@ -411,30 +412,30 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
return true;
}
addr_r.set(path());
#ifndef LWIP
# ifndef LWIP
struct ip_mreqn mreq;
#else
# else
struct ip_mreq mreq;
#endif
# endif
piZeroMemory(mreq);
#ifdef LINUX
# ifdef LINUX
// mreq.imr_address.s_addr = INADDR_ANY;
/*PIEthernet::InterfaceList il = interfaces();
const PIEthernet::Interface * ci = il.getByAddress(addr_r.ipString());
if (ci != 0) mreq.imr_ifindex = ci->index;*/
#endif
# endif
if (params[PIEthernet::Broadcast])
#ifndef LWIP
# ifndef LWIP
mreq.imr_address.s_addr = INADDR_ANY;
#else
# else
mreq.imr_interface.s_addr = INADDR_ANY;
#endif
# endif
else
#ifndef LWIP
# ifndef LWIP
mreq.imr_address.s_addr = addr_r.ip();
#else
# else
mreq.imr_interface.s_addr = addr_r.ip();
#endif
# endif
// piCout << "join group" << group << "ip" << ip_ << "with index" << mreq.imr_ifindex << "socket" << sock;
mreq.imr_multiaddr.s_addr = inet_addr(group.dataAscii());
@@ -457,24 +458,24 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
return false;
}
addr_r.set(path());
#ifndef LWIP
# ifndef LWIP
struct ip_mreqn mreq;
#else
# else
struct ip_mreq mreq;
#endif
# endif
piZeroMemory(mreq);
if (params[PIEthernet::Broadcast])
#ifndef LWIP
# ifndef LWIP
mreq.imr_address.s_addr = INADDR_ANY;
#else
# else
mreq.imr_interface.s_addr = INADDR_ANY;
#endif
# endif
else
#ifndef LWIP
# ifndef LWIP
mreq.imr_address.s_addr = addr_r.ip();
#else
# else
mreq.imr_interface.s_addr = addr_r.ip();
#endif
# endif
mreq.imr_multiaddr.s_addr = inet_addr(group.dataAscii());
if (ethSetsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
piCoutObj << "Can`t leave multicast group" << group << "," << ethErrorString();
@@ -498,9 +499,9 @@ bool PIEthernet::connect(bool threaded) {
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
# ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
# endif
connecting_ = true;
connected_ = connectTCP();
connecting_ = false;
@@ -535,9 +536,9 @@ bool PIEthernet::listen(bool threaded) {
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
# ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
# endif
opened_ = false;
int tries = 0;
while ((bind(sock, (sockaddr *)&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 2)) {
@@ -661,9 +662,9 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
# ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
# endif
// piCoutObj << "connect to " << path() << "...";
connected_ = connectTCP();
// piCoutObj << "connect to " << path() << connected_;
@@ -678,7 +679,7 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
}
if (!connected_) return -1;
errorClear();
#ifdef WINDOWS
# ifdef WINDOWS
{
long wr = waitForEvent(PRIVATE->event, FD_READ | FD_CLOSE);
switch (wr) {
@@ -694,34 +695,34 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
default: break;
}
}
#else
# else
if (PRIVATE->event.wait(sock)) {
errorClear();
rs = ethRecv(sock, read_to, max_size);
}
#endif
# endif
// piCoutObj << "readed" << rs;
if (rs <= 0) {
lerr = ethErrorCore();
// piCoutObj << "readed" << rs << "error" << lerr;
// async normal returns
#ifdef WINDOWS
# ifdef WINDOWS
if (lerr == WSAEWOULDBLOCK) {
#else
# else
if (lerr == EWOULDBLOCK || lerr == EAGAIN || lerr == EINTR) {
#endif
# endif
// piCoutObj << "Ignore would_block" << lerr;
return -1;
}
// if no disconnect on timeout
if (!params[DisonnectOnTimeout]) {
#ifdef WINDOWS
# ifdef WINDOWS
if (lerr == WSAETIMEDOUT) {
#else
# else
if (lerr == ETIMEDOUT) {
#endif
# endif
// piCoutObj << "Ignore read timeout";
return -1;
}
@@ -745,7 +746,7 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
case UDP: {
piZeroMemory(PRIVATE->raddr_);
// piCoutObj << "read from" << path() << "...";
#ifdef WINDOWS
# ifdef WINDOWS
long wr = waitForEvent(PRIVATE->event, FD_READ | FD_CLOSE);
switch (wr) {
case FD_READ:
@@ -758,9 +759,9 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
break;
default: break;
}
#else
# else
rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr *)&PRIVATE->raddr_);
#endif
# endif
// piCoutObj << "read from" << path() << rs << "bytes";
if (rs > 0) {
addr_lr.set(uint(PRIVATE->raddr_.sin_addr.s_addr), ntohs(PRIVATE->raddr_.sin_port));
@@ -793,11 +794,11 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
return ethSendto(sock_s,
data,
max_size,
#ifndef WINDOWS
# ifndef WINDOWS
isOptionSet(BlockingWrite) ? 0 : MSG_DONTWAIT
#else
# else
0
#endif
# endif
,
(sockaddr *)&PRIVATE->saddr_,
sizeof(PRIVATE->saddr_));
@@ -809,9 +810,9 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
# ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
# endif
// piCoutObj << "connect to " << ip << ":" << port_;
connected_ = connectTCP();
if (!connected_) piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString();
@@ -847,11 +848,11 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
int sr = ::send(sock, remain_data, remain_size, 0);
if (sr < 0) {
int err = ethErrorCore();
#ifdef WINDOWS
# ifdef WINDOWS
if (err == WSAEWOULDBLOCK) {
#else
# else
if (err == EAGAIN || err == EWOULDBLOCK) {
#endif
# endif
piMinSleep();
// piCoutObj << "wait for write";
continue;
@@ -910,30 +911,30 @@ void PIEthernet::server_func(void * eth) {
}
sockaddr_in client_addr;
socklen_t slen = sizeof(client_addr);
#ifdef WINDOWS
# ifdef WINDOWS
long wr = ce->waitForEvent(ce->PRIVATEWB->event, FD_ACCEPT | FD_CLOSE);
if (wr != FD_ACCEPT) {
piMSleep(10);
return;
}
#else
# else
if (!ce->PRIVATEWB->event.wait(ce->sock)) {
piMSleep(10);
return;
}
#endif
# endif
// piCout << "server" << "accept ...";
int s = accept(ce->sock, (sockaddr *)&client_addr, &slen);
// piCout << "server" << "accept done" << ethErrorString();
if (s == -1) {
int lerr = ethErrorCore();
#ifdef WINDOWS
# ifdef WINDOWS
if (lerr == WSAETIMEDOUT) {
#elif defined(ANDROID)
# elif defined(ANDROID)
if ((lerr == EAGAIN || lerr == EINTR)) {
#else
# else
if (lerr == EAGAIN) {
#endif
# endif
piMSleep(10);
return;
}
@@ -969,7 +970,7 @@ void PIEthernet::setType(Type t, bool reopen) {
bool PIEthernet::connectTCP() {
::connect(sock, (sockaddr *)&(PRIVATE->addr_), sizeof(PRIVATE->addr_));
// piCout << errorString();
#ifdef WINDOWS
# ifdef WINDOWS
long wr = waitForEvent(PRIVATE->event, FD_CONNECT | FD_CLOSE);
switch (wr) {
case FD_CONNECT:
@@ -977,7 +978,7 @@ bool PIEthernet::connectTCP() {
return ethIsWriteable(sock);
default: break;
}
#else
# else
if (PRIVATE->event.wait(sock, PIWaitEvent::CheckWrite)) {
if (ethIsWriteable(sock))
return true;
@@ -986,12 +987,12 @@ bool PIEthernet::connectTCP() {
init();
}
}
#endif
# endif
return false;
}
#ifdef WINDOWS
# ifdef WINDOWS
long PIEthernet::waitForEvent(PIWaitEvent & event, long mask) {
if (!event.isCreate() || sock < 0) return 0;
if (WSAEventSelect(sock, event.getEvent(), mask) == SOCKET_ERROR) {
@@ -1008,7 +1009,7 @@ long PIEthernet::waitForEvent(PIWaitEvent & event, long mask) {
}
return 0;
}
#endif
# endif
bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
@@ -1118,7 +1119,7 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
Interface ci;
ci.index = -1;
ci.mtu = 1500;
#ifdef WINDOWS
# ifdef WINDOWS
int ret = 0;
ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO);
PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_INFO));
@@ -1169,10 +1170,10 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
}
}
if (pAdapterInfo) HeapFree(GetProcessHeap(), 0, pAdapterInfo);
#else
# ifdef MICRO_PIP
# else
# ifdef ANDROID
# ifdef LWIP
# else
# ifdef ANDROID
struct ifconf ifc;
int s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
ifc.ifc_len = 256;
@@ -1200,7 +1201,7 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
il << ci;
}
delete ifc.ifc_buf;
# else
# else
struct ifaddrs *ret, *cif = 0;
int s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (getifaddrs(&ret) == 0) {
@@ -1218,8 +1219,8 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
ci.address = getSockAddr(cif->ifa_addr);
ci.netmask = getSockAddr(cif->ifa_netmask);
ci.mac.clear();
# ifdef QNX
# ifndef BLACKBERRY
# ifdef QNX
# ifndef BLACKBERRY
int fd = ::open((PIString("/dev/io-net/") + ci.name).dataAscii(), O_RDONLY);
if (fd != 0) {
nic_config_t nic;
@@ -1227,9 +1228,9 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
::close(fd);
ci.mac = macFromBytes(PIByteArray(nic.permanent_address, 6));
}
# endif
# else
# ifdef MAC_OS
# endif
# else
# ifdef MAC_OS
PIString req = PISystemInfo::instance()->ifconfigPath + " " + ci.name + " | grep ether";
FILE * fp = popen(req.dataAscii(), "r");
if (fp != 0) {
@@ -1240,7 +1241,7 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
}
pclose(fp);
}
# else
# else
if (s != -1) {
struct ifreq ir;
memset(&ir, 0, sizeof(ir));
@@ -1252,8 +1253,8 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
ci.mtu = ir.ifr_mtu;
}
}
# endif
# endif
# endif
ci.flags = 0;
if (cif->ifa_flags & IFF_UP) ci.flags |= PIEthernet::ifActive;
if (cif->ifa_flags & IFF_RUNNING) ci.flags |= PIEthernet::ifRunning;
@@ -1274,18 +1275,18 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
piCout << "[PIEthernet]"
<< "Can`t get interfaces: %1"_tr("PIEthernet").arg(errorString());
if (s != -1) ::close(s);
# endif
# endif
# endif
#endif
return il;
}
PINetworkAddress PIEthernet::interfaceAddress(const PIString & interface_) {
#if defined(WINDOWS) || defined(MICRO_PIP)
# if defined(WINDOWS) || defined(LWIP)
piCout << "[PIEthernet] Not implemented, use \"PIEthernet::allAddresses\" or \"PIEthernet::interfaces\" instead";
return PINetworkAddress();
#else
# else
struct ifreq ifr;
piZeroMemory(ifr);
strcpy(ifr.ifr_name, interface_.dataAscii());
@@ -1294,7 +1295,7 @@ PINetworkAddress PIEthernet::interfaceAddress(const PIString & interface_) {
::close(s);
struct sockaddr_in * sa = (struct sockaddr_in *)&ifr.ifr_addr;
return PINetworkAddress(uint(sa->sin_addr.s_addr));
#endif
# endif
}
@@ -1317,16 +1318,16 @@ PIVector<PINetworkAddress> PIEthernet::allAddresses() {
// System wrap
int PIEthernet::ethErrorCore() {
#ifdef WINDOWS
# ifdef WINDOWS
return WSAGetLastError();
#else
# else
return errno;
#endif
# endif
}
PIString PIEthernet::ethErrorString() {
#ifdef WINDOWS
# ifdef WINDOWS
char * msg = nullptr;
int err = WSAGetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
@@ -1343,18 +1344,18 @@ PIString PIEthernet::ethErrorString() {
} else
ret += '?';
return ret;
#else
# else
return errorString();
#endif
# endif
}
int PIEthernet::ethRecv(int sock, void * buf, int size, int flags) {
if (sock < 0) return -1;
return recv(sock,
#ifdef WINDOWS
# ifdef WINDOWS
(char *)
#endif
# endif
buf,
size,
flags);
@@ -1363,29 +1364,29 @@ int PIEthernet::ethRecv(int sock, void * buf, int size, int flags) {
int PIEthernet::ethRecvfrom(int sock, void * buf, int size, int flags, sockaddr * addr) {
if (sock < 0) return -1;
#ifdef QNX
# ifdef QNX
return recv(sock, buf, size, flags);
#else
# else
socklen_t len = sizeof(sockaddr);
return recvfrom(sock,
# ifdef WINDOWS
# ifdef WINDOWS
(char *)
# endif
# endif
buf,
size,
flags,
addr,
&len);
#endif
# endif
}
int PIEthernet::ethSendto(int sock, const void * buf, int size, int flags, sockaddr * addr, int addr_len) {
if (sock < 0) return -1;
return sendto(sock,
#ifdef WINDOWS
# ifdef WINDOWS
(const char *)
#endif
# endif
buf,
size,
flags,
@@ -1399,26 +1400,26 @@ void PIEthernet::ethClosesocket(int sock, bool shutdown) {
if (sock < 0) return;
if (shutdown)
::shutdown(sock,
#ifdef WINDOWS
# ifdef WINDOWS
SD_BOTH);
closesocket(sock);
#else
# else
SHUT_RDWR);
::close(sock);
#endif
# endif
}
int PIEthernet::ethSetsockopt(int sock, int level, int optname, const void * optval, int optlen) {
if (sock < 0) return -1;
auto ret = setsockopt(sock,
level,
optname,
#ifdef WINDOWS
(char *)
#endif
optval,
optlen);
level,
optname,
# ifdef WINDOWS
(char *)
# endif
optval,
optlen);
if (ret != 0) piCout << "setsockopt error:" << ethErrorString();
return ret;
}
@@ -1426,11 +1427,11 @@ int PIEthernet::ethSetsockopt(int sock, int level, int optname, const void * opt
int PIEthernet::ethSetsockoptInt(int sock, int level, int optname, int value) {
if (sock < 0) return -1;
#ifdef WINDOWS
# ifdef WINDOWS
DWORD
#else
# else
int
#endif
# endif
so = value;
return ethSetsockopt(sock, level, optname, &so, sizeof(so));
}
@@ -1438,11 +1439,11 @@ int PIEthernet::ethSetsockoptInt(int sock, int level, int optname, int value) {
int PIEthernet::ethSetsockoptBool(int sock, int level, int optname, bool value) {
if (sock < 0) return -1;
#ifdef WINDOWS
# ifdef WINDOWS
BOOL
#else
# else
int
#endif
# endif
so = (value ? 1 : 0);
return ethSetsockopt(sock, level, optname, &so, sizeof(so));
}
@@ -1450,12 +1451,12 @@ int PIEthernet::ethSetsockoptBool(int sock, int level, int optname, bool value)
void PIEthernet::ethNonblocking(int sock) {
if (sock < 0) return;
#ifdef WINDOWS
# ifdef WINDOWS
u_long mode = 1;
ioctlsocket(sock, FIONBIO, &mode);
#else
# else
fcntl(sock, F_SETFL, O_NONBLOCK);
#endif
# endif
}
@@ -1471,7 +1472,7 @@ bool PIEthernet::ethIsWriteable(int sock) {
timeout.tv_sec = timeout.tv_usec = 0;
::select(fds, nullptr, &fd_test, nullptr, &timeout);
return FD_ISSET(sock, &fd_test);*/
#ifdef WINDOWS
# ifdef WINDOWS
fd_set fd_test;
FD_ZERO(&fd_test);
FD_SET(sock, &fd_test);
@@ -1479,10 +1480,12 @@ bool PIEthernet::ethIsWriteable(int sock) {
timeout.tv_sec = timeout.tv_usec = 0;
::select(0, nullptr, &fd_test, nullptr, &timeout);
return FD_ISSET(sock, &fd_test);
#else
# else
int ret = 0;
socklen_t len = sizeof(ret);
getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&ret, &len);
return ret == 0;
#endif
# endif
}
#endif // PIP_NO_SOCKET