mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-13 10:32:57 +01: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
|
||||
/// 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();
|
||||
/// Destroys the ServerSocket.
|
||||
|
||||
|
@ -85,6 +85,10 @@ public:
|
||||
|
||||
#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();
|
||||
/// Destroys the Socket and releases the
|
||||
/// SocketImpl.
|
||||
|
@ -142,6 +142,13 @@ public:
|
||||
/// If the library has not been built with IPv6 support,
|
||||
/// 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);
|
||||
/// 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()
|
||||
{
|
||||
}
|
||||
|
@ -54,6 +54,15 @@ Socket::Socket(const Socket& socket):
|
||||
_pImpl->duplicate();
|
||||
}
|
||||
|
||||
|
||||
Socket Socket::fromFileDescriptor(poco_socket_t fd)
|
||||
{
|
||||
Socket s;
|
||||
s.impl()->useFileDescriptor(fd);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
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)
|
||||
{
|
||||
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
|
||||
#include "EchoServer.h"
|
||||
#include "Poco/Net/ServerSocket.h"
|
||||
#include "Poco/Net/StreamSocket.h"
|
||||
#include "Poco/Net/SocketAddress.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()
|
||||
{
|
||||
_stop = true;
|
||||
|
@ -31,6 +31,9 @@ public:
|
||||
EchoServer(const Poco::Net::SocketAddress& address);
|
||||
/// Creates the EchoServer using the given address.
|
||||
|
||||
EchoServer(const Poco::Net::ServerSocket& sock);
|
||||
/// Creates the EchoServer using the already created socket
|
||||
|
||||
~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)
|
||||
{
|
||||
@ -650,6 +695,7 @@ CppUnit::Test* SocketTest::suite()
|
||||
CppUnit_addTest(pSuite, SocketTest, testSelect3);
|
||||
CppUnit_addTest(pSuite, SocketTest, testEchoUnixLocal);
|
||||
CppUnit_addTest(pSuite, SocketTest, testUnixLocalAbstract);
|
||||
CppUnit_addTest(pSuite, SocketTest, testUseFd);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
void testSelect3();
|
||||
void testEchoUnixLocal();
|
||||
void testUnixLocalAbstract();
|
||||
void testUseFd();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
Loading…
Reference in New Issue
Block a user