mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 10:13:51 +01:00
* 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:
parent
c918c70e68
commit
e40f07099d
3
.vscode/c_cpp_properties.json
vendored
3
.vscode/c_cpp_properties.json
vendored
@ -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": [
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
void testSelect2();
|
||||
void testSelect3();
|
||||
void testEchoUnixLocal();
|
||||
void testUnixLocalAbstract();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
Loading…
Reference in New Issue
Block a user