mirror of
https://github.com/pocoproject/poco.git
synced 2025-07-03 17:17:12 +02:00
enh(Net): Allow passing raw fd's into ServerSocket (#4156)
* Allow creating ServerSocket's from fd's * more sensible approach * fix whitespace issue * add test * build fixes for windows
This commit is contained in:
parent
94418e5bc8
commit
3ae282db2e
@ -60,6 +60,10 @@ public:
|
|||||||
/// After successful construction, the server socket
|
/// After successful construction, the server socket
|
||||||
/// is ready to accept connections.
|
/// is ready to accept connections.
|
||||||
|
|
||||||
|
static ServerSocket fromFileDescriptor(poco_socket_t fd);
|
||||||
|
// Creates a socket from an existing file descriptor.
|
||||||
|
// Ownership is taken by poco
|
||||||
|
|
||||||
virtual ~ServerSocket();
|
virtual ~ServerSocket();
|
||||||
/// Destroys the ServerSocket.
|
/// Destroys the ServerSocket.
|
||||||
|
|
||||||
|
@ -85,6 +85,10 @@ public:
|
|||||||
|
|
||||||
#endif // POCO_NEW_STATE_ON_MOVE
|
#endif // POCO_NEW_STATE_ON_MOVE
|
||||||
|
|
||||||
|
static Socket fromFileDescriptor(poco_socket_t fd);
|
||||||
|
// Creates a socket from an existing file descriptor.
|
||||||
|
// Ownership is taken by poco
|
||||||
|
|
||||||
virtual ~Socket();
|
virtual ~Socket();
|
||||||
/// Destroys the Socket and releases the
|
/// Destroys the Socket and releases the
|
||||||
/// SocketImpl.
|
/// SocketImpl.
|
||||||
|
@ -142,6 +142,13 @@ public:
|
|||||||
/// If the library has not been built with IPv6 support,
|
/// If the library has not been built with IPv6 support,
|
||||||
/// a Poco::NotImplementedException will be thrown.
|
/// a Poco::NotImplementedException will be thrown.
|
||||||
|
|
||||||
|
void useFileDescriptor(poco_socket_t fd);
|
||||||
|
/// Use a external file descriptor for the socket. Required to be careful
|
||||||
|
/// about what kind of file descriptor you're passing to make sure it's compatable
|
||||||
|
/// with how you plan on using it. These specifics are platform-specific.
|
||||||
|
/// Not valid to call this if the internal socket is already initialized.
|
||||||
|
/// Poco takes ownership of the file descriptor, closing it when this socket is closed.
|
||||||
|
|
||||||
virtual void listen(int backlog = 64);
|
virtual void listen(int backlog = 64);
|
||||||
/// Puts the socket into listening state.
|
/// Puts the socket into listening state.
|
||||||
///
|
///
|
||||||
|
@ -57,6 +57,14 @@ ServerSocket::ServerSocket(SocketImpl* pImpl, bool ignore): Socket(pImpl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ServerSocket ServerSocket::fromFileDescriptor(poco_socket_t fd)
|
||||||
|
{
|
||||||
|
ServerSocket s;
|
||||||
|
s.impl()->useFileDescriptor(fd);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ServerSocket::~ServerSocket()
|
ServerSocket::~ServerSocket()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,15 @@ Socket::Socket(const Socket& socket):
|
|||||||
_pImpl->duplicate();
|
_pImpl->duplicate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Socket Socket::fromFileDescriptor(poco_socket_t fd)
|
||||||
|
{
|
||||||
|
Socket s;
|
||||||
|
s.impl()->useFileDescriptor(fd);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if POCO_NEW_STATE_ON_MOVE
|
#if POCO_NEW_STATE_ON_MOVE
|
||||||
|
|
||||||
Socket::Socket(Socket&& socket):
|
Socket::Socket(Socket&& socket):
|
||||||
|
@ -276,6 +276,14 @@ void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool reu
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SocketImpl::useFileDescriptor(poco_socket_t fd)
|
||||||
|
{
|
||||||
|
poco_assert (_sockfd == POCO_INVALID_SOCKET);
|
||||||
|
|
||||||
|
_sockfd = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SocketImpl::listen(int backlog)
|
void SocketImpl::listen(int backlog)
|
||||||
{
|
{
|
||||||
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
|
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "EchoServer.h"
|
#include "EchoServer.h"
|
||||||
|
#include "Poco/Net/ServerSocket.h"
|
||||||
#include "Poco/Net/StreamSocket.h"
|
#include "Poco/Net/StreamSocket.h"
|
||||||
#include "Poco/Net/SocketAddress.h"
|
#include "Poco/Net/SocketAddress.h"
|
||||||
#include "Poco/Timespan.h"
|
#include "Poco/Timespan.h"
|
||||||
@ -42,6 +43,17 @@ EchoServer::EchoServer(const Poco::Net::SocketAddress& address):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EchoServer::EchoServer(const Poco::Net::ServerSocket& sock):
|
||||||
|
_socket(sock),
|
||||||
|
_thread("EchoServer"),
|
||||||
|
_stop(false),
|
||||||
|
_done(false)
|
||||||
|
{
|
||||||
|
_thread.start(*this);
|
||||||
|
_ready.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
EchoServer::~EchoServer()
|
EchoServer::~EchoServer()
|
||||||
{
|
{
|
||||||
_stop = true;
|
_stop = true;
|
||||||
|
@ -31,6 +31,9 @@ public:
|
|||||||
EchoServer(const Poco::Net::SocketAddress& address);
|
EchoServer(const Poco::Net::SocketAddress& address);
|
||||||
/// Creates the EchoServer using the given address.
|
/// Creates the EchoServer using the given address.
|
||||||
|
|
||||||
|
EchoServer(const Poco::Net::ServerSocket& sock);
|
||||||
|
/// Creates the EchoServer using the already created socket
|
||||||
|
|
||||||
~EchoServer();
|
~EchoServer();
|
||||||
/// Destroys the EchoServer.
|
/// Destroys the EchoServer.
|
||||||
|
|
||||||
|
@ -598,6 +598,51 @@ void SocketTest::testUnixLocalAbstract()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SocketTest::testUseFd()
|
||||||
|
{
|
||||||
|
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||||
|
struct addrinfo addr_hint = {};
|
||||||
|
addr_hint.ai_family = AF_INET;
|
||||||
|
addr_hint.ai_socktype = SOCK_STREAM;
|
||||||
|
addr_hint.ai_protocol = IPPROTO_TCP;
|
||||||
|
addr_hint.ai_flags = AI_PASSIVE;
|
||||||
|
struct addrinfo* addr_result;
|
||||||
|
getaddrinfo(nullptr, "0", &addr_hint, &addr_result);
|
||||||
|
poco_socket_t listenfd = socket(addr_result->ai_family, addr_result->ai_socktype, addr_result->ai_protocol);
|
||||||
|
bind(listenfd, addr_result->ai_addr, (int)addr_result->ai_addrlen);
|
||||||
|
freeaddrinfo(addr_result);
|
||||||
|
listen(listenfd, SOMAXCONN);
|
||||||
|
SOCKADDR_IN serv_addr;
|
||||||
|
int addr_len = sizeof(serv_addr);
|
||||||
|
getsockname(listenfd, (SOCKADDR*)&serv_addr, &addr_len);
|
||||||
|
auto server_port = ntohs(serv_addr.sin_port);
|
||||||
|
#elif defined(POCO_OS_FAMILY_UNIX)
|
||||||
|
poco_socket_t listenfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
struct sockaddr_in serv_addr = {};
|
||||||
|
serv_addr.sin_family = AF_INET;
|
||||||
|
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
serv_addr.sin_port = htons(0);
|
||||||
|
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||||
|
listen(listenfd, 1);
|
||||||
|
socklen_t len = sizeof(serv_addr);
|
||||||
|
getsockname(listenfd, (struct sockaddr*)&serv_addr, &len);
|
||||||
|
auto server_port = ntohs(serv_addr.sin_port);
|
||||||
|
#else
|
||||||
|
std::cout << "[USE FD TEST DISABLED]";
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
EchoServer server(ServerSocket::fromFileDescriptor(listenfd));
|
||||||
|
StreamSocket ss;
|
||||||
|
ss.connect(SocketAddress("127.0.0.1", server_port));
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SocketTest::onReadable(bool& b)
|
void SocketTest::onReadable(bool& b)
|
||||||
{
|
{
|
||||||
@ -650,6 +695,7 @@ CppUnit::Test* SocketTest::suite()
|
|||||||
CppUnit_addTest(pSuite, SocketTest, testSelect3);
|
CppUnit_addTest(pSuite, SocketTest, testSelect3);
|
||||||
CppUnit_addTest(pSuite, SocketTest, testEchoUnixLocal);
|
CppUnit_addTest(pSuite, SocketTest, testEchoUnixLocal);
|
||||||
CppUnit_addTest(pSuite, SocketTest, testUnixLocalAbstract);
|
CppUnit_addTest(pSuite, SocketTest, testUnixLocalAbstract);
|
||||||
|
CppUnit_addTest(pSuite, SocketTest, testUseFd);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ public:
|
|||||||
void testSelect3();
|
void testSelect3();
|
||||||
void testEchoUnixLocal();
|
void testEchoUnixLocal();
|
||||||
void testUnixLocalAbstract();
|
void testUnixLocalAbstract();
|
||||||
|
void testUseFd();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user