fix(Net): Add Unix socket support on windows #4208 (#4209)

* fix(Net): Add Unix socket support on windows #4208

* feat(Net): add abstract local socket support #4208

* fix(PollSet): use localhost socket in PollSet on windows when available #4208

* fix(PollSetTest): comment checking unconnected sockets status (Linux epoll signals them as readable/writable)
This commit is contained in:
Aleksandar Fabijanic 2023-10-23 13:33:46 +02:00 committed by GitHub
parent c918c70e68
commit e40f07099d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 243 additions and 98 deletions

View File

@ -22,7 +22,8 @@
"${POCO_BASE}/JWT/include",
"${POCO_BASE}/Redis/include",
"${POCO_BASE}/MongoDB/include",
"${POCO_BASE}/ApacheConnector/include"
"${POCO_BASE}/ApacheConnector/include",
"/usr/include"
]
},
"configurations": [

View File

@ -149,6 +149,10 @@
// No UNIX socket support
// Define to disable unix sockets
// UNIX local sockets are default-enabled on
// all UNIX systems, on Windows if available
// See Net/SocketDefs.h
// See https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
// #define POCO_NET_NO_UNIX_SOCKET

View File

@ -37,8 +37,11 @@ class IPAddress;
class Net_API SocketAddress
/// This class represents an internet (IP) endpoint/socket
/// address. The address can belong either to the
/// IPv4 or the IPv6 address family and consists of a
/// host address and a port number.
/// IPv4, IPv6 or Unix local family.
/// IP addresses consist of a host address and a port number.
/// An Unix local socket address consists of a path to socket file.
/// Abstract local sockets, which operate without the need for
/// interaction with the filesystem, are supported on Linux only.
{
public:
// The following declarations keep the Family type
@ -49,7 +52,7 @@ public:
#if defined(POCO_HAVE_IPv6)
static const Family IPv6 = AddressFamily::IPv6;
#endif
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
static const Family UNIX_LOCAL = AddressFamily::UNIX_LOCAL;
#endif
@ -124,16 +127,30 @@ public:
/// [::ffff:192.168.1.120]:2040
/// www.appinf.com:8080
///
/// On POSIX platforms supporting UNIX_LOCAL sockets, hostAndPort
/// can also be the absolute path of a local socket, starting with a
/// slash, e.g. "/tmp/local.socket".
/// On platforms supporting UNIX_LOCAL sockets, hostAndPort
/// can also be a valid absolute local socket file path.
///
/// Examples:
/// /tmp/local.sock
/// C:\Temp\local.sock
///
/// On Linux, abstract local sockets are supported as well.
/// Abstract local sockets operate in a namespace that has
/// no need for a filesystem. They are identified by
/// a null byte at the beginning of the path.
///
/// Example:
/// \0abstract.sock
///
SocketAddress(Family family, const std::string& addr);
/// Creates a SocketAddress of the given family from a
/// string representation of the address, which is
/// either an IP address and port number, separated by
/// a colon for IPv4 or IPv6 addresses, or a path for
/// either (1) an IP address and port number, separated by
/// a colon for IPv4 or IPv6 addresses, or (2) path for
/// UNIX_LOCAL sockets.
/// See `SocketAddress(const string&)` documentation
/// for more details.
SocketAddress(const SocketAddress& addr);
/// Creates a SocketAddress by copying another one.
@ -181,7 +198,7 @@ public:
enum
{
MAX_ADDRESS_LENGTH =
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
sizeof(struct sockaddr_un)
#elif defined(POCO_HAVE_IPv6)
sizeof(struct sockaddr_in6)
@ -214,7 +231,7 @@ private:
void newIPv6(const IPAddress& hostAddress, Poco::UInt16 portNumber);
#endif
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
void newLocal(const sockaddr_un* sockAddr);
void newLocal(const std::string& path);
#endif
@ -265,7 +282,7 @@ inline void SocketAddress::newIPv6(const IPAddress& hostAddress, Poco::UInt16 po
#endif // POCO_HAVE_IPv6
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
inline void SocketAddress::newLocal(const sockaddr_un* sockAddr)
{
_pImpl = new Poco::Net::Impl::LocalSocketAddressImpl(sockAddr);
@ -276,12 +293,12 @@ inline void SocketAddress::newLocal(const std::string& path)
{
_pImpl = new Poco::Net::Impl::LocalSocketAddressImpl(path.c_str(), path.size());
}
#endif // POCO_OS_FAMILY_UNIX
#endif // POCO_HAS_UNIX_SOCKET
inline bool SocketAddress::operator == (const SocketAddress& socketAddress) const
{
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
if (family() == UNIX_LOCAL)
return toString() == socketAddress.toString();
else

View File

@ -177,7 +177,7 @@ inline SocketAddressImpl::Family IPv6SocketAddressImpl::family() const
#endif // POCO_HAVE_IPv6
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
class Net_API LocalSocketAddressImpl: public SocketAddressImpl

View File

@ -30,6 +30,14 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#include <ws2def.h>
#if !defined (POCO_NET_NO_UNIX_SOCKET)
#if (__cplusplus >= 201703L)
#if __has_include(<afunix.h>)
#include <afunix.h>
#define POCO_HAS_UNIX_SOCKET
#endif
#endif
#endif
#define POCO_INVALID_SOCKET INVALID_SOCKET
#define poco_socket_t SOCKET
#define poco_socklen_t int
@ -148,7 +156,6 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#if defined(POCO_OS_FAMILY_UNIX)
#if (POCO_OS == POCO_OS_LINUX) || (POCO_OS == POCO_OS_ANDROID)
// Net/src/NetworkInterface.cpp changed #include <linux/if.h> to #include <net/if.h>
// no more conflict, can use #include <net/if.h> here
@ -161,7 +168,6 @@
#else
#include <net/if.h>
#endif
#endif
#if (POCO_OS == POCO_OS_SOLARIS) || (POCO_OS == POCO_OS_MAC_OS_X)
#include <sys/sockio.h>
#include <sys/filio.h>
@ -228,6 +234,9 @@
#define POCO_TRY_AGAIN TRY_AGAIN
#define POCO_NO_RECOVERY NO_RECOVERY
#define POCO_NO_DATA NO_DATA
#if !defined (POCO_NET_NO_UNIX_SOCKET)
#define POCO_HAS_UNIX_SOCKET
#endif
#endif
@ -389,7 +398,7 @@ struct AddressFamily
{
UNKNOWN = AF_UNSPEC,
/// Unspecified family
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
UNIX_LOCAL = AF_UNIX,
/// UNIX domain socket address family. Available on UNIX/POSIX platforms only.
#endif

View File

@ -36,7 +36,8 @@ DatagramSocketImpl::DatagramSocketImpl(SocketAddress::Family family)
else if (family == SocketAddress::IPv6)
init(AF_INET6);
#endif
#if defined(POCO_OS_FAMILY_UNIX)
// on windows, UDP is not supported for local sockets
#if defined(POCO_OS_FAMILY_UNIX) && defined(POCO_HAS_UNIX_SOCKET)
else if (family == SocketAddress::UNIX_LOCAL)
init(AF_UNIX);
#endif

View File

@ -53,7 +53,7 @@ MulticastSocket::MulticastSocket()
MulticastSocket::MulticastSocket(SocketAddress::Family family): DatagramSocket(family)
{
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
if (family == SocketAddress::UNIX_LOCAL)
throw Poco::InvalidArgumentException("Cannot create a MulticastSocket with UNIX_LOCAL socket");
#endif

View File

@ -14,6 +14,7 @@
#include "Poco/Net/PollSet.h"
#include "Poco/Net/SocketImpl.h"
#include "Poco/TemporaryFile.h"
#include "Poco/Mutex.h"
#include <set>
@ -68,9 +69,14 @@ public:
using SocketMode = std::pair<Socket, int>;
using SocketMap = std::map<void*, SocketMode>;
PollSetImpl(): _events(1024),
_port(0),
_eventfd(eventfd(_port, 0)),
static const epoll_event EPOLL_NULL_EVENT;
PollSetImpl(): _events(FD_SETSIZE, EPOLL_NULL_EVENT),
#if defined(WEPOLL_H_)
_eventfd(eventfd()),
#else
_eventfd(eventfd(0, 0)),
#endif // WEPOLL_H_
_epollfd(epoll_create(1))
{
int err = addFD(_eventfd, PollSet::POLL_READ, EPOLL_CTL_ADD);
@ -87,7 +93,6 @@ public:
~PollSetImpl()
{
#ifdef WEPOLL_H_
if (_eventfd >= 0) eventfd(_port, _eventfd);
if (_epollfd) close(_epollfd);
#else
if (_eventfd > 0) close(_eventfd.exchange(0));
@ -153,10 +158,7 @@ public:
if (_epollfd < 0) SocketImpl::error();
#endif
}
#ifdef WEPOLL_H_
eventfd(_port, _eventfd);
_eventfd = eventfd(_port);
#else
#ifndef WEPOLL_H_
close(_eventfd.exchange(0));
_eventfd = eventfd(0, 0);
#endif
@ -231,10 +233,16 @@ public:
void wakeUp()
{
#ifdef WEPOLL_H_
StreamSocket ss(SocketAddress("127.0.0.1", _port));
#else
uint64_t val = 1;
#ifdef WEPOLL_H_
#ifdef POCO_HAS_UNIX_SOCKET
poco_check_ptr (_pSockFile);
StreamSocket ss(SocketAddress(_pSockFile->path()));
#else
StreamSocket ss(SocketAddress("127.0.0.1", _port));
#endif
ss.sendBytes(&val, sizeof(val));
#else
// This is guaranteed to write into a valid fd,
// or 0 (meaning PollSet is being destroyed).
// Errors are ignored.
@ -296,41 +304,46 @@ private:
return epoll_ctl(_epollfd, op, fd, &ev);
}
#ifdef WEPOLL_H_
#ifndef WEPOLL_H_
using EPollHandle = std::atomic<int>;
#else // WEPOLL_H_
using EPollHandle = std::atomic<HANDLE>;
int eventfd(int& port, int rmFD = 0)
{
if (rmFD == 0)
#ifdef POCO_HAS_UNIX_SOCKET
int eventfd()
{
_pSocket = new ServerSocket(SocketAddress("127.0.0.1", 0));
if (!_pSockFile)
{
_pSockFile.reset(new TemporaryFile);
_pSocket.reset(new ServerSocket(SocketAddress(_pSockFile->path())));
}
_pSocket->setBlocking(false);
port = _pSocket->address().port();
return static_cast<int>(_pSocket->impl()->sockfd());
}
else
std::unique_ptr<TemporaryFile> _pSockFile;
#else // no unix socket, listen on localhost
int eventfd()
{
delete _pSocket;
_pSocket = 0;
port = 0;
if (!_pSocket)
_pSocket.reset(new ServerSocket(SocketAddress("127.0.0.1", 0)));
_port = _pSocket->address().port();
_pSocket->setBlocking(false);
return static_cast<int>(_pSocket->impl()->sockfd());
}
return 0;
}
int _port = 0;
#endif // POCO_HAS_UNIX_SOCKET
std::unique_ptr<ServerSocket> _pSocket;
#endif // WEPOLL_H_
mutable Mutex _mutex;
SocketMap _socketMap;
SocketMap _socketMap;
std::vector<struct epoll_event> _events;
int _port;
std::atomic<int> _eventfd;
#ifdef WEPOLL_H_
std::atomic <HANDLE> _epollfd;
ServerSocket* _pSocket;
#else
std::atomic<int> _epollfd;
#endif
EPollHandle _epollfd;
};
const epoll_event PollSetImpl::EPOLL_NULL_EVENT = {0, {0}};
#elif defined(POCO_HAVE_FD_POLL)

View File

@ -20,12 +20,14 @@
#include "Poco/NumberParser.h"
#include "Poco/BinaryReader.h"
#include "Poco/BinaryWriter.h"
#include "Poco/RegularExpression.h"
#include <algorithm>
#include <cstring>
using Poco::RefCountedObject;
using Poco::NumberParser;
using Poco::RegularExpression;
using Poco::UInt16;
using Poco::InvalidArgumentException;
using Poco::Net::Impl::SocketAddressImpl;
@ -33,7 +35,7 @@ using Poco::Net::Impl::IPv4SocketAddressImpl;
#ifdef POCO_HAVE_IPv6
using Poco::Net::Impl::IPv6SocketAddressImpl;
#endif
#ifdef POCO_OS_FAMILY_UNIX
#ifdef POCO_HAS_UNIX_SOCKET
using Poco::Net::Impl::LocalSocketAddressImpl;
#endif
@ -63,7 +65,7 @@ const SocketAddress::Family SocketAddress::IPv4;
#if defined(POCO_HAVE_IPv6)
const SocketAddress::Family SocketAddress::IPv6;
#endif
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
const SocketAddress::Family SocketAddress::UNIX_LOCAL;
#endif
#endif
@ -143,7 +145,7 @@ SocketAddress::SocketAddress(const SocketAddress& socketAddress)
else if (socketAddress.family() == IPv6)
newIPv6(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr()));
#endif
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
else if (socketAddress.family() == UNIX_LOCAL)
newLocal(reinterpret_cast<const sockaddr_un*>(socketAddress.addr()));
#endif
@ -164,7 +166,7 @@ SocketAddress::SocketAddress(const struct sockaddr* sockAddr, poco_socklen_t len
else if (length == sizeof(struct sockaddr_in6) && sockAddr->sa_family == AF_INET6)
newIPv6(reinterpret_cast<const struct sockaddr_in6*>(sockAddr));
#endif
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
else if (length > 0 && length <= sizeof(struct sockaddr_un) && sockAddr->sa_family == AF_UNIX)
newLocal(reinterpret_cast<const sockaddr_un*>(sockAddr));
#endif
@ -181,7 +183,7 @@ bool SocketAddress::operator < (const SocketAddress& socketAddress) const
{
if (family() < socketAddress.family()) return true;
if (family() > socketAddress.family()) return false;
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
if (family() == UNIX_LOCAL) return toString() < socketAddress.toString();
#endif
if (host() < socketAddress.host()) return true;
@ -200,7 +202,7 @@ SocketAddress& SocketAddress::operator = (const SocketAddress& socketAddress)
else if (socketAddress.family() == IPv6)
newIPv6(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr()));
#endif
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
else if (socketAddress.family() == UNIX_LOCAL)
newLocal(reinterpret_cast<const sockaddr_un*>(socketAddress.addr()));
#endif
@ -325,7 +327,7 @@ void SocketAddress::init(Family fam, const std::string& hostAddress, Poco::UInt1
void SocketAddress::init(Family fam, const std::string& address)
{
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
if (fam == UNIX_LOCAL)
{
newLocal(address);
@ -364,6 +366,15 @@ void SocketAddress::init(const std::string& hostAndPort)
{
poco_assert (!hostAndPort.empty());
#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_HAS_UNIX_SOCKET)
RegularExpression re(R"((?:[a-zA-Z]\:|\\\\[\w\s\.]+\\[\w\s\.$]+)\\(?:[\w\s\.]+\\)*[\w\s\.]*?$)");
if (re.match(hostAndPort))
{
newLocal(hostAndPort);
return;
}
#endif
std::string host;
std::string port;
std::string::const_iterator it = hostAndPort.begin();

View File

@ -127,7 +127,7 @@ std::string IPv6SocketAddressImpl::toString() const
#endif // POCO_HAVE_IPv6
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
//
@ -146,22 +146,36 @@ LocalSocketAddressImpl::LocalSocketAddressImpl(const char* path)
{
poco_assert (std::strlen(path) < sizeof(_pAddr->sun_path));
#if POCO_OS != POCO_OS_LINUX
if (path[0] == 0)
throw Poco::InvalidArgumentException("LocalSocketAddressImpl(): "
"abstract sockets are only supported on Linux");
#endif
_pAddr = new sockaddr_un;
poco_set_sun_len(_pAddr, std::strlen(path) + sizeof(struct sockaddr_un) - sizeof(_pAddr->sun_path) + 1);
std::memset(_pAddr, 0, sizeof(sockaddr_un));
std::size_t length = strlen(path);
poco_set_sun_len(_pAddr, length + sizeof(struct sockaddr_un) - sizeof(_pAddr->sun_path) + 1);
_pAddr->sun_family = AF_UNIX;
std::strcpy(_pAddr->sun_path, path);
std::memcpy(&_pAddr->sun_path, path, length);
}
LocalSocketAddressImpl::LocalSocketAddressImpl(const char* path, std::size_t length)
{
poco_assert (length < sizeof(_pAddr->sun_path));
poco_assert (length && length < sizeof(_pAddr->sun_path));
#if POCO_OS != POCO_OS_LINUX
if (path[0] == 0)
throw Poco::InvalidArgumentException("LocalSocketAddressImpl(): "
"abstract sockets are only supported on Linux");
#endif
_pAddr = new sockaddr_un;
std::memset(_pAddr, 0, sizeof(sockaddr_un));
poco_set_sun_len(_pAddr, length + sizeof(struct sockaddr_un) - sizeof(_pAddr->sun_path) + 1);
_pAddr->sun_family = AF_UNIX;
std::memcpy(_pAddr->sun_path, path, length);
_pAddr->sun_path[length] = 0;
std::memcpy(&_pAddr->sun_path, path, length);
}
@ -178,7 +192,7 @@ std::string LocalSocketAddressImpl::toString() const
}
#endif // POCO_OS_FAMILY_UNIX
#endif // POCO_HAS_UNIX_SOCKET
} } } // namespace Poco::Net::Impl

View File

@ -227,8 +227,15 @@ void SocketImpl::bind(const SocketAddress& address, bool reuseAddress, bool reus
{
init(address.af());
}
setReuseAddress(reuseAddress);
setReusePort(reusePort);
#ifdef POCO_HAS_UNIX_SOCKET
if (address.family() != SocketAddress::Family::UNIX_LOCAL)
#endif
{
setReuseAddress(reuseAddress);
setReusePort(reusePort);
}
#if defined(POCO_VXWORKS)
int rc = ::bind(_sockfd, (sockaddr*) address.addr(), address.length());
#else

View File

@ -34,7 +34,7 @@ StreamSocketImpl::StreamSocketImpl(SocketAddress::Family family)
else if (family == SocketAddress::IPv6)
init(AF_INET6);
#endif
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
else if (family == SocketAddress::UNIX_LOCAL)
init(AF_UNIX);
#endif

View File

@ -139,7 +139,7 @@ void TCPServer::run()
if (!_pConnectionFilter || _pConnectionFilter->accept(ss))
{
// enable nodelay per default: OSX really needs that
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
if (ss.address().family() != AddressFamily::UNIX_LOCAL)
#endif
{

View File

@ -11,7 +11,9 @@
// SPDX-License-Identifier: BSL-1.0
//
#ifndef NOMINMAX
#define NOMINMAX
#endif // NOMINMAX
#include "Poco/Net/WebSocketImpl.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/WebSocket.h"

View File

@ -72,6 +72,11 @@ void EchoServer::run()
{
ss.sendBytes(buffer, n);
n = ss.receiveBytes(buffer, sizeof(buffer));
if (n == 0)
{
_stop = true;
break;
}
}
}
catch (Poco::Exception& exc)

View File

@ -326,10 +326,9 @@ void PollSetTest::testPoll()
void PollSetTest::testPollNoServer()
{
StreamSocket ss1;
StreamSocket ss2;
ss1.connectNB(SocketAddress("127.0.0.1", 0xFEFE));
ss2.connectNB(SocketAddress("127.0.0.1", 0xFEFF));
StreamSocket ss1(SocketAddress::IPv4);
StreamSocket ss2(SocketAddress::IPv4);
PollSet ps;
assertTrue(ps.empty());
ps.add(ss1, PollSet::POLL_READ | PollSet::POLL_WRITE | PollSet::POLL_ERROR);
@ -337,26 +336,35 @@ void PollSetTest::testPollNoServer()
assertTrue(!ps.empty());
assertTrue(ps.has(ss1));
assertTrue(ps.has(ss2));
// should be like this, but Linux epoll disagrees ...
//assertEqual(0, static_cast<int>(ps.poll(Timespan(100)).size()));
ss1.connectNB(SocketAddress("127.0.0.1", 0xFEFE));
ss2.connectNB(SocketAddress("127.0.0.1", 0xFEFF));
PollSet::SocketModeMap sm;
int signalled = 0;
int signalledErrors = 0;
Stopwatch sw; sw.start();
do
{
sm = ps.poll(Timespan(1000000));
for (auto s : sm)
{
assertTrue(0 != (s.second & PollSet::POLL_ERROR));
++signalledErrors;
}
signalled += static_cast<int>(sm.size());
sm.clear();
int secs = sw.elapsedSeconds();
if (secs > 10)
{
fail(Poco::format("testPollNoServer() timed out after %ds, "
"sockets signalled=%d (expected 2)",
secs, signalled), __LINE__);
secs, signalledErrors), __LINE__);
}
} while (signalled < 2);
assertTrue(signalled == 2);
} while (signalledErrors < 2);
assertEqual(2, signalledErrors);
}
@ -365,11 +373,9 @@ void PollSetTest::testPollClosedServer()
{
EchoServer echoServer1;
EchoServer echoServer2;
StreamSocket ss1;
StreamSocket ss2;
ss1.connect(SocketAddress("127.0.0.1", echoServer1.port()));
ss2.connect(SocketAddress("127.0.0.1", echoServer2.port()));
StreamSocket ss1(SocketAddress::IPv4);
StreamSocket ss2(SocketAddress::IPv4);
PollSet ps;
assertTrue(ps.empty());
@ -379,6 +385,11 @@ void PollSetTest::testPollClosedServer()
assertTrue(ps.has(ss1));
assertTrue(ps.has(ss2));
//assertEqual(0, static_cast<int>(ps.poll(Timespan(100)).size()));
ss1.connect(SocketAddress("127.0.0.1", echoServer1.port()));
ss2.connect(SocketAddress("127.0.0.1", echoServer2.port()));
std::string str = "HELLO";
int len = static_cast<int>(str.length());
@ -393,14 +404,23 @@ void PollSetTest::testPollClosedServer()
int secs = sw.elapsedSeconds();
if (secs > 10)
{
fail(Poco::format("testPollClosedServer() timed out "
fail(Poco::format("testPollClosedServer(1) timed out "
"waiting on server after %ds", secs), __LINE__);
}
}
echoServer2.stop();
assertTrue (len == ss2.sendBytes(str.data(), len));
while (!echoServer2.done()) Thread::sleep(10);
while (!echoServer2.done())
{
Thread::sleep(10);
int secs = sw.elapsedSeconds();
if (secs > 10)
{
fail(Poco::format("testPollClosedServer(2) timed out "
"waiting on server after %ds", secs), __LINE__);
}
}
int signalled = 0;
sw.restart();

View File

@ -11,6 +11,7 @@
#include "SocketAddressTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
#include "Poco/Path.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/NetException.h"
#include <iostream>
@ -23,6 +24,7 @@ using Poco::Net::HostNotFoundException;
using Poco::Net::ServiceNotFoundException;
using Poco::Net::NoAddressFoundException;
using Poco::Net::AddressFamilyMismatchException;
using Poco::Path;
using Poco::InvalidArgumentException;
@ -184,25 +186,27 @@ void SocketAddressTest::testSocketAddress6()
void SocketAddressTest::testSocketAddressUnixLocal()
{
#ifdef POCO_OS_FAMILY_UNIX
SocketAddress sa1(SocketAddress::UNIX_LOCAL, "/tmp/sock1");
#ifdef POCO_HAS_UNIX_SOCKET
std::string name1 = Path::tempHome() + "sock1";
SocketAddress sa1(SocketAddress::UNIX_LOCAL, name1);
assertTrue (sa1.af() == AF_UNIX);
assertTrue (sa1.family() == SocketAddress::UNIX_LOCAL);
assertTrue (sa1.toString() == "/tmp/sock1");
assertTrue (sa1.toString() == name1);
SocketAddress sa2(SocketAddress::UNIX_LOCAL, "/tmp/sock2");
std::string name2 = Path::tempHome() + "sock2";
SocketAddress sa2(SocketAddress::UNIX_LOCAL, name2);
assertTrue (sa1 != sa2);
assertTrue (sa1 < sa2);
SocketAddress sa3(SocketAddress::UNIX_LOCAL, "/tmp/sock1");
SocketAddress sa3(SocketAddress::UNIX_LOCAL, name1);
assertTrue (sa1 == sa3);
assertTrue (!(sa1 < sa3));
SocketAddress sa4("/tmp/sock1");
SocketAddress sa4(name1);
assertTrue (sa1 == sa4);
assertTrue (sa4.toString() == "/tmp/sock1");
assertTrue (sa4.toString() == name1);
#else
std::cout << "[UNIX LOCAL DISABLED]" << std::endl;
std::cout << "[UNIX LOCAL SOCKET DISABLED]" << std::endl;
#endif
}

View File

@ -22,6 +22,7 @@
#include "Poco/FIFOBuffer.h"
#include "Poco/Delegate.h"
#include "Poco/File.h"
#include "Poco/Path.h"
#include <iostream>
@ -36,6 +37,8 @@ using Poco::TimeoutException;
using Poco::InvalidArgumentException;
using Poco::Buffer;
using Poco::FIFOBuffer;
using Poco::Path;
using Poco::File;
using Poco::delegate;
@ -536,12 +539,14 @@ void SocketTest::testSelect3()
void SocketTest::testEchoUnixLocal()
{
#if defined(POCO_OS_FAMILY_UNIX)
#if defined(POCO_HAS_UNIX_SOCKET)
#if POCO_OS == POCO_OS_ANDROID
Poco::File socketFile("/data/local/tmp/SocketTest.sock");
File socketFile("/data/local/tmp/SocketTest.sock");
#elif defined(POCO_OS_FAMILY_WINDOWS)
File socketFile(Path::tempHome() + "SocketTest.sock");
#else
Poco::File socketFile("/tmp/SocketTest.sock");
#endif
File socketFile("/tmp/SocketTest.sock");
#endif // POCO_OS == POCO_OS_ANDROID
if (socketFile.exists()) socketFile.remove();
SocketAddress localAddr(SocketAddress::UNIX_LOCAL, socketFile.path());
EchoServer echoServer(localAddr);
@ -554,7 +559,37 @@ void SocketTest::testEchoUnixLocal()
assertTrue (n == 5);
assertTrue (std::string(buffer, n) == "hello");
ss.close();
socketFile.remove();
if (socketFile.exists()) socketFile.remove();
echoServer.stop();
#else // POCO_HAS_UNIX_SOCKET
#pragma message("[UNIX LOCAL SOCKET DISABLED]")
std::cout << "[UNIX LOCAL SOCKET DISABLED]" << std::endl;
#endif
}
void SocketTest::testUnixLocalAbstract()
{
// abstract local sockets don't work on windows
// see https://github.com/microsoft/WSL/issues/4240
// they are a nonportable Linux extension
#if (POCO_OS == POCO_OS_LINUX) && defined(POCO_HAS_UNIX_SOCKET)
std::string addr("\0look ma - no file!", 20);
SocketAddress localAddr(SocketAddress::UNIX_LOCAL, addr);
EchoServer echoServer(localAddr);
StreamSocket ss(SocketAddress::UNIX_LOCAL);
ss.connect(localAddr);
int n = ss.sendBytes("hello", 5);
assertTrue(n == 5);
char buffer[256];
n = ss.receiveBytes(buffer, sizeof(buffer));
assertTrue(n == 5);
assertTrue(std::string(buffer, n) == "hello");
ss.close();
echoServer.stop();
#else // POCO_HAS_UNIX_SOCKET
#pragma message("[ABSTRACT UNIX LOCAL SOCKET DISABLED]")
std::cout << "[ABSTRACT UNIX LOCAL SOCKET DISABLED]" << std::endl;
#endif
}
@ -610,6 +645,7 @@ CppUnit::Test* SocketTest::suite()
CppUnit_addTest(pSuite, SocketTest, testSelect2);
CppUnit_addTest(pSuite, SocketTest, testSelect3);
CppUnit_addTest(pSuite, SocketTest, testEchoUnixLocal);
CppUnit_addTest(pSuite, SocketTest, testUnixLocalAbstract);
return pSuite;
}

View File

@ -42,6 +42,7 @@ public:
void testSelect2();
void testSelect3();
void testEchoUnixLocal();
void testUnixLocalAbstract();
void setUp();
void tearDown();