BIND 10 trac2145, updated. ca3773316b8833c1ca7573475eeacfa72a1817d7 revamp socket code to make it more portable, i.e., less bound to Unix
BIND 10 source code commits
bind10-changes at lists.isc.org
Sat Aug 18 21:56:16 UTC 2012
The branch, trac2145 has been updated
via ca3773316b8833c1ca7573475eeacfa72a1817d7 (commit)
from 802589cc9ba0d647b7cb80b84f951f7f3cc6615a (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ca3773316b8833c1ca7573475eeacfa72a1817d7
Author: Francis Dupont <fdupont at isc.org>
Date: Sat Aug 18 23:56:03 2012 +0200
revamp socket code to make it more portable, i.e., less bound to Unix
-----------------------------------------------------------------------
Summary of changes:
src/bin/auth/tests/config_unittest.cc | 10 +-
src/bin/bind10/bind10_src.py.in | 16 +-
src/bin/bind10/tests/bind10_test.py.in | 32 ++--
src/bin/dhcp4/ctrl_dhcp4_srv.cc | 5 +-
src/bin/dhcp6/ctrl_dhcp6_srv.cc | 5 +-
src/bin/resolver/tests/resolver_config_unittest.cc | 17 +-
src/bin/sockcreator/README | 4 +-
src/bin/sockcreator/main.cc | 2 +-
src/bin/sockcreator/sockcreator.cc | 151 ++++++++-------
src/bin/sockcreator/sockcreator.h | 53 +++---
src/bin/sockcreator/tests/sockcreator_tests.cc | 105 ++++++-----
src/bin/xfrout/tests/xfrout_test.py.in | 12 +-
src/bin/xfrout/xfrout.py.in | 2 +-
src/lib/asiodns/asiodns_messages.mes | 12 +-
src/lib/asiodns/dns_service.cc | 22 ++-
src/lib/asiodns/dns_service.h | 8 +-
src/lib/asiodns/sync_udp_server.cc | 10 +-
src/lib/asiodns/sync_udp_server.h | 3 +-
src/lib/asiodns/tcp_server.cc | 7 +-
src/lib/asiodns/tcp_server.h | 6 +-
src/lib/asiodns/tests/dns_server_unittest.cc | 59 +++---
src/lib/asiodns/tests/dns_service_unittest.cc | 33 ++--
src/lib/asiodns/udp_server.cc | 18 +-
src/lib/asiodns/udp_server.h | 6 +-
src/lib/asiolink/io_asio_socket.h | 12 +-
src/lib/asiolink/io_socket.cc | 6 +-
src/lib/asiolink/io_socket.h | 4 +-
src/lib/asiolink/tcp_socket.h | 4 +-
src/lib/asiolink/tests/io_socket_unittest.cc | 5 +-
src/lib/asiolink/udp_socket.h | 4 +-
src/lib/cc/session.cc | 7 +-
src/lib/cc/session.h | 3 +-
src/lib/cc/tests/session_unittests.cc | 7 +-
src/lib/dhcp/iface_mgr.cc | 74 ++++----
src/lib/dhcp/iface_mgr.h | 56 +++---
src/lib/dhcp/tests/iface_mgr_unittest.cc | 57 +++---
src/lib/python/isc/bind10/sockcreator.py | 4 +-
.../python/isc/bind10/tests/sockcreator_test.py | 4 +-
.../isc/util/cio/socketsessionforwarder_python.cc | 10 +-
.../isc/util/cio/socketsessionreceiver_python.cc | 23 ++-
src/lib/resolve/tests/recursive_query_unittest.cc | 48 ++---
src/lib/server_common/portconfig.cc | 4 +-
src/lib/server_common/socket_request.cc | 107 ++++++-----
src/lib/server_common/socket_request.h | 5 +-
.../server_common/tests/socket_requestor_test.cc | 64 +++----
src/lib/testutils/mockups.h | 34 ++--
src/lib/util/io/Makefile.am | 5 +-
src/lib/util/io/{fd.cc => socket.cc} | 10 +-
src/lib/util/io/{fd.h => socket.h} | 22 ++-
src/lib/util/io/{fd_share.cc => socket_share.cc} | 46 ++---
src/lib/util/io/{fd_share.h => socket_share.h} | 42 +++--
src/lib/util/io/socketsession.cc | 96 +++++-----
src/lib/util/io/socketsession.h | 34 ++--
.../{fdshare_python.cc => socketshare_python.cc} | 63 ++++---
src/lib/util/tests/Makefile.am | 4 +-
.../{fd_share_tests.cc => socket_share_tests.cc} | 26 +--
.../util/tests/{fd_tests.cc => socket_tests.cc} | 20 +-
src/lib/util/tests/socketsession_unittest.cc | 199 ++++++++++----------
src/lib/util/unittests/fork.cc | 11 +-
src/lib/util/unittests/fork.h | 8 +-
src/lib/util/unittests/mock_socketsession.h | 11 +-
src/lib/xfr/xfrout_client.cc | 6 +-
src/lib/xfr/xfrout_client.h | 8 +-
63 files changed, 932 insertions(+), 819 deletions(-)
rename src/lib/util/io/{fd.cc => socket.cc} (90%)
rename src/lib/util/io/{fd.h => socket.h} (78%)
rename src/lib/util/io/{fd_share.cc => socket_share.cc} (79%)
rename src/lib/util/io/{fd_share.h => socket_share.h} (59%)
rename src/lib/util/io/{fdshare_python.cc => socketshare_python.cc} (53%)
rename src/lib/util/tests/{fd_share_tests.cc => socket_share_tests.cc} (76%)
rename src/lib/util/tests/{fd_tests.cc => socket_tests.cc} (86%)
-----------------------------------------------------------------------
diff --git a/src/bin/auth/tests/config_unittest.cc b/src/bin/auth/tests/config_unittest.cc
index c4d1db7..288ab7e 100644
--- a/src/bin/auth/tests/config_unittest.cc
+++ b/src/bin/auth/tests/config_unittest.cc
@@ -125,10 +125,12 @@ TEST_F(AuthConfigTest, listenAddressConfig) {
// listenAddressConfig should have attempted to create 4 DNS server
// objects: two IP addresses, TCP and UDP for each. For UDP, the "SYNC_OK"
// option should have been specified.
- EXPECT_EQ(2, dnss_.getTCPFdParams().size());
- EXPECT_EQ(2, dnss_.getUDPFdParams().size());
- EXPECT_EQ(DNSService::SERVER_SYNC_OK, dnss_.getUDPFdParams().at(0).options);
- EXPECT_EQ(DNSService::SERVER_SYNC_OK, dnss_.getUDPFdParams().at(1).options);
+ EXPECT_EQ(2, dnss_.getTCPSocketParams().size());
+ EXPECT_EQ(2, dnss_.getUDPSocketParams().size());
+ EXPECT_EQ(DNSService::SERVER_SYNC_OK,
+ dnss_.getUDPSocketParams().at(0).options);
+ EXPECT_EQ(DNSService::SERVER_SYNC_OK,
+ dnss_.getUDPSocketParams().at(1).options);
}
class StatisticsIntervalConfigTest : public AuthConfigTest {
diff --git a/src/bin/bind10/bind10_src.py.in b/src/bin/bind10/bind10_src.py.in
index 7b71737..455bff4 100755
--- a/src/bin/bind10/bind10_src.py.in
+++ b/src/bin/bind10/bind10_src.py.in
@@ -250,7 +250,7 @@ class BoB:
self._socket_cache = None
self._tmpdir = None
self._srv_socket = None
- self._unix_sockets = {}
+ self._ctrl_sockets = {}
def __propagate_component_config(self, config):
comps = dict(config)
@@ -854,7 +854,7 @@ class BoB:
# a problem. If there appear such problems, we should do something
# about it.
unix_socket.sendall(CREATOR_SOCKET_OK)
- libutil_io_python.send_fd(unix_socket.fileno(), fd)
+ libutil_io_python.send_socket(unix_socket.fileno(), fd)
except Exception as e:
logger.info(BIND10_NO_SOCKET, token, e)
unix_socket.sendall(CREATOR_SOCKET_UNAVAILABLE)
@@ -926,7 +926,7 @@ class BoB:
others we care about.
"""
(socket, conn) = self._srv_socket.accept()
- self._unix_sockets[socket.fileno()] = (socket, b'')
+ self._ctrl_sockets[socket.fileno()] = (socket, b'')
def _socket_data(self, socket_fileno):
"""
@@ -934,7 +934,7 @@ class BoB:
attention. We try to read data from there. If it is closed, we remove
it.
"""
- (sock, previous) = self._unix_sockets[socket_fileno]
+ (sock, previous) = self._ctrl_sockets[socket_fileno]
while True:
try:
data = sock.recv(1, socket.MSG_DONTWAIT)
@@ -942,12 +942,12 @@ class BoB:
# These two might be different on some systems
if se.errno == errno.EAGAIN or se.errno == errno.EWOULDBLOCK:
# No more data now. Oh, well, just store what we have.
- self._unix_sockets[socket_fileno] = (sock, previous)
+ self._ctrl_sockets[socket_fileno] = (sock, previous)
return
else:
data = b'' # Pretend it got closed
if len(data) == 0: # The socket got to it's end
- del self._unix_sockets[socket_fileno]
+ del self._ctrl_sockets[socket_fileno]
self.socket_consumer_dead(sock)
sock.close()
return
@@ -984,7 +984,7 @@ class BoB:
(rlist, wlist, xlist) = \
select.select([wakeup_fd, ccs_fd,
self._srv_socket.fileno()] +
- list(self._unix_sockets.keys()), [], [],
+ list(self._ctrl_sockets.keys()), [], [],
wait_time)
except select.error as err:
if err.args[0] == errno.EINTR:
@@ -1005,7 +1005,7 @@ class BoB:
os.read(wakeup_fd, 32)
elif fd == self._srv_socket.fileno():
self._srv_accept()
- elif fd in self._unix_sockets:
+ elif fd in self._ctrl_sockets:
self._socket_data(fd)
# global variables, needed for signal handlers
diff --git a/src/bin/bind10/tests/bind10_test.py.in b/src/bin/bind10/tests/bind10_test.py.in
index 0a17230..f90a61b 100644
--- a/src/bin/bind10/tests/bind10_test.py.in
+++ b/src/bin/bind10/tests/bind10_test.py.in
@@ -130,16 +130,16 @@ class TestCacheCommands(unittest.TestCase):
# What was and wasn't called.
self.__drop_app_called = None
self.__get_socket_called = None
- self.__send_fd_called = None
+ self.__send_socket_called = None
self.__get_token_called = None
self.__drop_socket_called = None
- bind10_src.libutil_io_python.send_fd = self.__send_fd
+ bind10_src.libutil_io_python.send_socket = self.__send_socket
- def __send_fd(self, to, socket):
+ def __send_socket(self, to, socket):
"""
- A function to hook the send_fd in the bind10_src.
+ A function to hook the send_socket in the bind10_src.
"""
- self.__send_fd_called = (to, socket)
+ self.__send_socket_called = (to, socket)
class FalseSocket:
"""
@@ -213,13 +213,13 @@ class TestCacheCommands(unittest.TestCase):
self.assertIsNone(self.__get_socket_called)
self.assertEqual(b"0\n", socket.send)
# It should not have sent any socket.
- self.assertIsNone(self.__send_fd_called)
+ self.assertIsNone(self.__send_socket_called)
# Now prepare a valid scenario
self.__raise_exception = None
socket.send = b""
self.__boss.socket_request_handler(b"token", socket)
self.assertEqual(b"1\n", socket.send)
- self.assertEqual((42, 13), self.__send_fd_called)
+ self.assertEqual((42, 13), self.__send_socket_called)
self.assertEqual(("token", 42), self.__get_socket_called)
def get_token(self, protocol, address, port, share_mode, share_name):
@@ -1384,11 +1384,11 @@ class SocketSrvTest(unittest.TestCase):
self.__boss._srv_socket = self.__FalseSocket(self)
self.__boss._srv_accept()
# After we accepted, a new socket is added there
- socket = self.__boss._unix_sockets[13][0]
+ socket = self.__boss._ctrl_sockets[13][0]
# The socket is properly stored there
self.assertTrue(isinstance(socket, self.__FalseSocket))
# And the buffer (yet empty) is there
- self.assertEqual({13: (socket, b'')}, self.__boss._unix_sockets)
+ self.assertEqual({13: (socket, b'')}, self.__boss._ctrl_sockets)
def __socket_data(self, socket):
self.__boss.runnable = False
@@ -1401,7 +1401,7 @@ class SocketSrvTest(unittest.TestCase):
self.__boss._srv_socket = self.__FalseSocket(self)
self.__boss._socket_data = self.__socket_data
self.__boss.ccs = self.__CCS()
- self.__boss._unix_sockets = {13: (self.__FalseSocket(self, 13), b'')}
+ self.__boss._ctrl_sockets = {13: (self.__FalseSocket(self, 13), b'')}
self.__boss.runnable = True
bind10_src.select.select = self.__select_data
self.__boss.run(2)
@@ -1410,7 +1410,7 @@ class SocketSrvTest(unittest.TestCase):
def __prepare_data(self, data):
socket = self.__FalseSocket(self, 13)
- self.__boss._unix_sockets = {13: (socket, b'')}
+ self.__boss._ctrl_sockets = {13: (socket, b'')}
socket.data = data
self.__boss.socket_consumer_dead = self.__consumer_dead
self.__boss.socket_request_handler = self.__socket_request_handler
@@ -1430,7 +1430,7 @@ class SocketSrvTest(unittest.TestCase):
socket = self.__prepare_data(None)
self.__boss._socket_data(13)
self.assertEqual(socket, self.__consumer_dead_called)
- self.assertEqual({}, self.__boss._unix_sockets)
+ self.assertEqual({}, self.__boss._ctrl_sockets)
self.assertTrue(socket.closed)
def test_socket_short(self):
@@ -1440,7 +1440,7 @@ class SocketSrvTest(unittest.TestCase):
"""
socket = self.__prepare_data(b'tok')
self.__boss._socket_data(13)
- self.assertEqual({13: (socket, b'tok')}, self.__boss._unix_sockets)
+ self.assertEqual({13: (socket, b'tok')}, self.__boss._ctrl_sockets)
self.assertFalse(socket.closed)
self.assertIsNone(self.__consumer_dead_called)
self.assertIsNone(self.__socket_request_handler_called)
@@ -1453,9 +1453,9 @@ class SocketSrvTest(unittest.TestCase):
"""
socket = self.__prepare_data(b"en\nanothe")
# The data to finish
- self.__boss._unix_sockets[13] = (socket, b'tok')
+ self.__boss._ctrl_sockets[13] = (socket, b'tok')
self.__boss._socket_data(13)
- self.assertEqual({13: (socket, b'anothe')}, self.__boss._unix_sockets)
+ self.assertEqual({13: (socket, b'anothe')}, self.__boss._ctrl_sockets)
self.assertFalse(socket.closed)
self.assertIsNone(self.__consumer_dead_called)
self.assertEqual((b'token', socket),
@@ -1470,7 +1470,7 @@ class SocketSrvTest(unittest.TestCase):
"There's more memory available, but not for you"))
self.__boss._socket_data(13)
self.assertEqual(sock, self.__consumer_dead_called)
- self.assertEqual({}, self.__boss._unix_sockets)
+ self.assertEqual({}, self.__boss._ctrl_sockets)
self.assertTrue(sock.closed)
class TestFunctions(unittest.TestCase):
diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
index 724ddf2..456a5d0 100644
--- a/src/bin/dhcp4/ctrl_dhcp4_srv.cc
+++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
@@ -28,6 +28,7 @@
#include <asiolink/asiolink.h>
using namespace std;
+using namespace asio::detail;
using namespace isc::util;
using namespace isc::dhcp;
using namespace isc::util;
@@ -105,7 +106,7 @@ void ControlledDhcpv4Srv::establishSession() {
/// Integrate the asynchronous I/O model of BIND 10 configuration
/// control with the "select" model of the DHCP server. This is
/// fully explained in \ref dhcpv4Session.
- int ctrl_socket = cc_session_->getSocketDesc();
+ socket_type ctrl_socket = cc_session_->getSocketDesc();
cout << "b10-dhcp4: Control session started, socket="
<< ctrl_socket << endl;
IfaceMgr::instance().set_session_socket(ctrl_socket, sessionReader);
@@ -123,7 +124,7 @@ void ControlledDhcpv4Srv::disconnectSession() {
}
// deregister session socket
- IfaceMgr::instance().set_session_socket(IfaceMgr::INVALID_SOCKET, NULL);
+ IfaceMgr::instance().set_session_socket(invalid_socket, NULL);
}
ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t port /*= DHCP4_SERVER_PORT*/)
diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.cc b/src/bin/dhcp6/ctrl_dhcp6_srv.cc
index 461d5f1..dc07e5b 100644
--- a/src/bin/dhcp6/ctrl_dhcp6_srv.cc
+++ b/src/bin/dhcp6/ctrl_dhcp6_srv.cc
@@ -28,6 +28,7 @@
#include <asiolink/asiolink.h>
using namespace std;
+using namespace asio::detail;
using namespace isc::util;
using namespace isc::dhcp;
using namespace isc::util;
@@ -105,7 +106,7 @@ void ControlledDhcpv6Srv::establishSession() {
/// Integrate the asynchronous I/O model of BIND 10 configuration
/// control with the "select" model of the DHCP server. This is
/// fully explained in \ref dhcpv6Session.
- int ctrl_socket = cc_session_->getSocketDesc();
+ socket_type ctrl_socket = cc_session_->getSocketDesc();
cout << "b10-dhcp6: Control session started, socket="
<< ctrl_socket << endl;
IfaceMgr::instance().set_session_socket(ctrl_socket, sessionReader);
@@ -123,7 +124,7 @@ void ControlledDhcpv6Srv::disconnectSession() {
}
// deregister session socket
- IfaceMgr::instance().set_session_socket(IfaceMgr::INVALID_SOCKET, NULL);
+ IfaceMgr::instance().set_session_socket(invalid_socket, NULL);
}
ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t port /*= DHCP6_SERVER_PORT*/)
diff --git a/src/bin/resolver/tests/resolver_config_unittest.cc b/src/bin/resolver/tests/resolver_config_unittest.cc
index 369ca5c..c89f9d7 100644
--- a/src/bin/resolver/tests/resolver_config_unittest.cc
+++ b/src/bin/resolver/tests/resolver_config_unittest.cc
@@ -53,6 +53,7 @@
#include <testutils/socket_request.h>
using namespace std;
+using asio::detail::socket_type;
using boost::scoped_ptr;
using namespace isc::acl;
using isc::acl::dns::RequestContext;
@@ -195,10 +196,10 @@ private:
struct ScopedSocket : public boost::noncopyable {
public:
- ScopedSocket(int fd) : fd_(fd) {}
- ~ScopedSocket() { close(fd_); }
+ ScopedSocket(socket_type sd) : sd_(sd) {}
+ ~ScopedSocket() { close(sd_); }
private:
- const int fd_;
+ const socket_type sd_;
};
int
@@ -323,10 +324,12 @@ TEST_F(ResolverConfig, listenAddresses) {
// listenAddressConfig should have attempted to create 4 DNS server
// objects: two IP addresses, TCP and UDP for each. For UDP, the "SYNC_OK"
// option (or anything else) should have NOT been specified.
- EXPECT_EQ(2, dnss.getTCPFdParams().size());
- EXPECT_EQ(2, dnss.getUDPFdParams().size());
- EXPECT_EQ(DNSService::SERVER_DEFAULT, dnss.getUDPFdParams().at(0).options);
- EXPECT_EQ(DNSService::SERVER_DEFAULT, dnss.getUDPFdParams().at(1).options);
+ EXPECT_EQ(2, dnss.getTCPSocketParams().size());
+ EXPECT_EQ(2, dnss.getUDPSocketParams().size());
+ EXPECT_EQ(DNSService::SERVER_DEFAULT,
+ dnss.getUDPSocketParams().at(0).options);
+ EXPECT_EQ(DNSService::SERVER_DEFAULT,
+ dnss.getUDPSocketParams().at(1).options);
// Check it requests the correct addresses
const char* tokens[] = {
diff --git a/src/bin/sockcreator/README b/src/bin/sockcreator/README
index e142d19..4e24e8f 100644
--- a/src/bin/sockcreator/README
+++ b/src/bin/sockcreator/README
@@ -20,8 +20,8 @@ binary protocol from stdin and does what the commands ask. Command is a single
byte (usually from the printable range, so it is easier to debug and guess
what it does), followed by parameters.
-Note that as send_fd and recv_fd works only with unix domain socket, it's stdio
-must be a socket, not pipe.
+Note that as send_socket and recv_socket works only with unix domain socket,
+it's stdio must be a socket, not pipe.
* 'T': It has no parameters. It asks the socket creator to terminate.
diff --git a/src/bin/sockcreator/main.cc b/src/bin/sockcreator/main.cc
index 17efd04..2f6832e 100644
--- a/src/bin/sockcreator/main.cc
+++ b/src/bin/sockcreator/main.cc
@@ -24,7 +24,7 @@ main() {
* but ability to bind ports? It would be nice.
*/
try {
- run(STDIN_FILENO, STDOUT_FILENO, getSock, isc::util::io::send_fd, close);
+ run(STDIN_FILENO, STDOUT_FILENO, getSock, isc::util::io::send_socket, close);
} catch (const SocketCreatorError& ec) {
return (ec.getExitCode());
}
diff --git a/src/bin/sockcreator/sockcreator.cc b/src/bin/sockcreator/sockcreator.cc
index 167e3f0..205795b 100644
--- a/src/bin/sockcreator/sockcreator.cc
+++ b/src/bin/sockcreator/sockcreator.cc
@@ -14,7 +14,7 @@
#include "sockcreator.h"
-#include <util/io/fd.h>
+#include <util/io/socket.h>
#include <util/io/sockaddr_util.h>
#include <cerrno>
@@ -33,69 +33,62 @@ namespace {
// Simple wrappers for read_data/write_data that throw an exception on error.
void
-readMessage(const int fd, void* where, const size_t length) {
- if (read_data(fd, where, length) < length) {
+readMessage(const socket_type s, void* where, const size_t length) {
+ if (read_data(s, where, length) < length) {
isc_throw(ReadError, "Error reading from socket creator client");
}
}
void
-writeMessage(const int fd, const void* what, const size_t length) {
- if (!write_data(fd, what, length)) {
+writeMessage(const socket_type s, const void* what, const size_t length) {
+ if (!write_data(s, what, length)) {
isc_throw(WriteError, "Error writing to socket creator client");
}
}
// Exit on a protocol error after informing the client of the problem.
void
-protocolError(const int fd, const char reason = 'I') {
+protocolError(const socket_type s, const char reason = 'I') {
// Tell client we have a problem
char message[2];
message[0] = 'F';
message[1] = reason;
- writeMessage(fd, message, sizeof(message));
+ writeMessage(s, message, sizeof(message));
// ... and exit
isc_throw(ProtocolError, "Fatal error, reason: " << reason);
}
// Return appropriate socket type constant for the socket type requested.
-// The output_fd argument is required to report a protocol error.
+// The output_sd argument is required to report a protocol error.
int
-getSocketType(const char type_code, const int output_fd) {
- int socket_type = 0;
+getSocketType(const char type_code, const socket_type output_sd) {
+ int s_type = 0;
switch (type_code) {
case 'T':
- socket_type = SOCK_STREAM;
+ s_type = SOCK_STREAM;
break;
case 'U':
- socket_type = SOCK_DGRAM;
+ s_type = SOCK_DGRAM;
break;
default:
- protocolError(output_fd); // Does not return
+ protocolError(output_sd); // Does not return
}
- return (socket_type);
+ return (s_type);
}
// Convert return status from getSock() to a character to be sent back to
// the caller.
char
-getErrorCode(const int status) {
+getErrorCode(const bool bind_failed) {
char error_code = ' ';
- switch (status) {
- case -1:
- error_code = 'S';
- break;
-
- case -2:
+ if (bind_failed) {
error_code = 'B';
- break;
-
- default:
- isc_throw(InternalError, "Error creating socket");
+ } else {
+ error_code = 'S';
}
return (error_code);
}
@@ -109,16 +102,16 @@ getErrorCode(const int status) {
// The arguments passed (and the exceptions thrown) are the same as those for
// run().
void
-handleRequest(const int input_fd, const int output_fd,
- const get_sock_t get_sock, const send_fd_t send_fd_fun,
+handleRequest(const socket_type input_sd, const socket_type output_sd,
+ const get_sock_t get_sock, const send_sd_t send_sd_fun,
const close_t close_fun)
{
// Read the message from the client
char type[2];
- readMessage(input_fd, type, sizeof(type));
+ readMessage(input_sd, type, sizeof(type));
// Decide what type of socket is being asked for
- const int sock_type = getSocketType(type[0], output_fd);
+ const int s_type = getSocketType(type[0], output_sd);
// Read the address they ask for depending on what address family was
// specified.
@@ -136,8 +129,8 @@ handleRequest(const int input_fd, const int output_fd,
addr_len = sizeof(addr_in);
memset(&addr_in, 0, sizeof(addr_in));
addr_in.sin_family = AF_INET;
- readMessage(input_fd, &addr_in.sin_port, sizeof(addr_in.sin_port));
- readMessage(input_fd, &addr_in.sin_addr.s_addr,
+ readMessage(input_sd, &addr_in.sin_port, sizeof(addr_in.sin_port));
+ readMessage(input_sd, &addr_in.sin_addr.s_addr,
sizeof(addr_in.sin_addr.s_addr));
break;
@@ -146,22 +139,24 @@ handleRequest(const int input_fd, const int output_fd,
addr_len = sizeof(addr_in6);
memset(&addr_in6, 0, sizeof(addr_in6));
addr_in6.sin6_family = AF_INET6;
- readMessage(input_fd, &addr_in6.sin6_port,
+ readMessage(input_sd, &addr_in6.sin6_port,
sizeof(addr_in6.sin6_port));
- readMessage(input_fd, &addr_in6.sin6_addr.s6_addr,
+ readMessage(input_sd, &addr_in6.sin6_addr.s6_addr,
sizeof(addr_in6.sin6_addr.s6_addr));
break;
default:
- protocolError(output_fd);
+ protocolError(output_sd);
}
// Obtain the socket
- const int result = get_sock(sock_type, addr, addr_len, close_fun);
- if (result >= 0) {
+ bool bind_failed;
+ const socket_type result = get_sock(s_type, addr, &bind_failed,
+ addr_len, close_fun);
+ if (result != invalid_socket) {
// Got the socket, send it to the client.
- writeMessage(output_fd, "S", 1);
- if (send_fd_fun(output_fd, result) != 0) {
+ writeMessage(output_sd, "S", 1);
+ if (send_sd_fun(output_sd, result) != 0) {
// Error. Close the socket (ignore any error from that operation)
// and abort.
close_fun(result);
@@ -170,19 +165,19 @@ handleRequest(const int input_fd, const int output_fd,
// Successfully sent the socket, so free up resources we still hold
// for it.
- if (close_fun(result) == -1) {
+ if (close_fun(result) == socket_error_retval) {
isc_throw(InternalError, "Error closing socket");
}
} else {
// Error. Tell the client.
char error_message[2];
error_message[0] = 'E';
- error_message[1] = getErrorCode(result);
- writeMessage(output_fd, error_message, sizeof(error_message));
+ error_message[1] = getErrorCode(bind_failed);
+ writeMessage(output_sd, error_message, sizeof(error_message));
// ...and append the reason code to the error message
const int error_number = errno;
- writeMessage(output_fd, &error_number, sizeof(error_number));
+ writeMessage(output_sd, &error_number, sizeof(error_number));
}
}
@@ -190,46 +185,50 @@ handleRequest(const int input_fd, const int output_fd,
// It is borrowed from bind-9 lib/isc/unix/socket.c and modified
// to compile here.
//
-// The function returns -2 if it fails or the socket file descriptor
-// on success (for convenience, so the result can be just returned).
-int
-mtu(int fd) {
+// The function returns false if it fails or true on success
+bool
+mtu(socket_type s) {
#ifdef IPV6_USE_MIN_MTU /* RFC 3542, not too common yet*/
const int on(1);
// use minimum MTU
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &on, sizeof(on)) < 0) {
- return (-2);
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &on, sizeof(on)) < 0) {
+ return (false);
}
#else // Try the following as fallback
#ifdef IPV6_MTU
// Use minimum MTU on systems that don't have the IPV6_USE_MIN_MTU
const int mtu = 1280;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU, &mtu, sizeof(mtu)) < 0) {
- return (-2);
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU, &mtu, sizeof(mtu)) < 0) {
+ return (false);
}
#endif
#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
// Turn off Path MTU discovery on IPv6/UDP sockets.
const int action = IPV6_PMTUDISC_DONT;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &action,
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &action,
sizeof(action)) < 0) {
- return (-2);
+ return (false);
}
#endif
#endif
- return (fd);
+ return (true);
}
-// This one closes the socket if result is negative. Used not to leak socket
+// This one closes the socket if result is false. Used not to leak socket
// on error.
-int maybeClose(const int result, const int socket, const close_t close_fun) {
- if (result < 0) {
- if (close_fun(socket) == -1) {
+socket_type
+maybeClose(const bool result,
+ const socket_type socket,
+ const close_t close_fun)
+{
+ if (!result) {
+ if (close_fun(socket) == socket_error_retval) {
isc_throw(InternalError, "Error closing socket");
}
+ return (invalid_socket);
}
- return (result);
+ return (socket);
}
} // Anonymous namespace
@@ -238,28 +237,34 @@ namespace isc {
namespace socket_creator {
// Get the socket and bind to it.
-int
-getSock(const int type, struct sockaddr* bind_addr, const socklen_t addr_len,
- const close_t close_fun) {
- const int sock = socket(bind_addr->sa_family, type, 0);
- if (sock == -1) {
- return (-1);
+socket_type
+getSock(const int type, struct sockaddr* bind_addr, bool* bind_failed,
+ const socklen_t addr_len, const close_t close_fun)
+{
+ *bind_failed = false;
+ const socket_type sock = socket(bind_addr->sa_family, type, 0);
+ if (sock == invalid_socket) {
+ return (invalid_socket);
}
const int on = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
// This is part of the binding process, so it's a bind error
- return (maybeClose(-2, sock, close_fun));
+ *bind_failed = true;
+ return (maybeClose(false, sock, close_fun));
}
if (bind_addr->sa_family == AF_INET6 &&
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) {
// This is part of the binding process, so it's a bind error
- return (maybeClose(-2, sock, close_fun));
+ *bind_failed = true;
+ return (maybeClose(false, sock, close_fun));
}
if (bind(sock, bind_addr, addr_len) == -1) {
- return (maybeClose(-2, sock, close_fun));
+ *bind_failed = true;
+ return (maybeClose(false, sock, close_fun));
}
if (type == SOCK_DGRAM && bind_addr->sa_family == AF_INET6) {
// Set some MTU flags on IPv6 UDP sockets.
+ *bind_failed = true;
return (maybeClose(mtu(sock), sock, close_fun));
}
return (sock);
@@ -267,23 +272,23 @@ getSock(const int type, struct sockaddr* bind_addr, const socklen_t addr_len,
// Main run loop.
void
-run(const int input_fd, const int output_fd, get_sock_t get_sock,
- send_fd_t send_fd_fun, close_t close_fun)
+run(const socket_type input_sd, const socket_type output_sd,
+ get_sock_t get_sock, send_sd_t send_sd_fun, close_t close_fun)
{
for (;;) {
char command;
- readMessage(input_fd, &command, sizeof(command));
+ readMessage(input_sd, &command, sizeof(command));
switch (command) {
case 'S': // The "get socket" command
- handleRequest(input_fd, output_fd, get_sock,
- send_fd_fun, close_fun);
+ handleRequest(input_sd, output_sd, get_sock,
+ send_sd_fun, close_fun);
break;
case 'T': // The "terminate" command
return;
default: // Don't recognise anything else
- protocolError(output_fd);
+ protocolError(output_sd);
}
}
}
diff --git a/src/bin/sockcreator/sockcreator.h b/src/bin/sockcreator/sockcreator.h
index e5d4783..0aa48f3 100644
--- a/src/bin/sockcreator/sockcreator.h
+++ b/src/bin/sockcreator/sockcreator.h
@@ -21,13 +21,9 @@
#ifndef __SOCKCREATOR_H
#define __SOCKCREATOR_H 1
-#include <util/io/fd_share.h>
+#include <util/io/socket_share.h>
#include <exceptions/exceptions.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
namespace isc {
namespace socket_creator {
@@ -75,7 +71,7 @@ public:
// Type of the close() function, so it can be passed as a parameter.
// Argument is the same as that for close(2).
-typedef int (*close_t)(int);
+typedef int (*close_t)(socket_type);
/// \short Create a socket and bind it.
///
@@ -89,12 +85,10 @@ typedef int (*close_t)(int);
/// after the creation.
///
/// \return The file descriptor of the newly created socket, if everything
-/// goes well. A negative number is returned if an error occurs -
-/// -1 if the socket() call fails or -2 if bind() fails. In case of
-/// error, errno is set (or left intact from socket() or bind()).
-int
-getSock(const int type, struct sockaddr* bind_addr, const socklen_t addr_len,
- const close_t close_fun);
+/// goes well.
+socket_type
+getSock(const int type, struct sockaddr* bind_addr, bool* bind_failed,
+ const socklen_t addr_len, const close_t close_fun);
// Define some types for functions used to perform socket-related operations.
// These are typedefed so that alternatives can be passed through to the
@@ -102,44 +96,45 @@ getSock(const int type, struct sockaddr* bind_addr, const socklen_t addr_len,
// Type of the function to get a socket and to pass it as parameter.
// Arguments are those described above for getSock().
-typedef int (*get_sock_t)(const int, struct sockaddr *, const socklen_t,
- const close_t close_fun);
+typedef socket_type (*get_sock_t)
+ (const int, struct sockaddr *, bool* bind_failed,
+ const socklen_t, const close_t close_fun);
-// Type of the send_fd() function, so it can be passed as a parameter.
-// Arguments are the same as those of the send_fd() function.
-typedef int (*send_fd_t)(const int, const int);
+// Type of the send_sd() function, so it can be passed as a parameter.
+// Arguments are the same as those of the send_sd() function.
+typedef int (*send_sd_t)(const socket_type, const socket_type);
/// \brief Infinite loop parsing commands and returning the sockets.
///
-/// This reads commands and socket descriptions from the input_fd file
+/// This reads commands and socket descriptions from the input_sd socket
/// descriptor, creates sockets and writes the results (socket or error) to
-/// output_fd.
+/// output_sd.
///
/// It terminates either if a command asks it to or when unrecoverable error
/// happens.
///
-/// \param input_fd File number of the stream from which the input commands
-/// are read.
-/// \param output_fd File number of the stream to which the response is
-/// written. The socket is sent as part of a control message associated
+/// \param input_sd Socket number of the stream from which the input commands
+/// are received.
+/// \param output_sd Socket number of the stream to which the response is
+/// sent. The socket is sent as part of a control message associated
/// with that stream.
/// \param get_sock_fun The function that is used to create the sockets.
/// This should be left on the default value, the parameter is here
/// for testing purposes.
-/// \param send_fd_fun The function that is used to send the socket over
-/// a file descriptor. This should be left on the default value, it is
+/// \param send_sd_fun The function that is used to send the socket over
+/// a socket descriptor. This should be left on the default value, it is
/// here for testing purposes.
-/// \param close_fun The close function used to close sockets, coming from
-/// unistd.h. It can be overriden in tests.
+/// \param close_fun The close function used to close sockets.
+/// It can be overriden in tests.
///
/// \exception isc::socket_creator::ReadError Error reading from input
/// \exception isc::socket_creator::WriteError Error writing to output
/// \exception isc::socket_creator::ProtocolError Unrecognised command received
/// \exception isc::socket_creator::InternalError Other error
void
-run(const int input_fd, const int output_fd, get_sock_t get_sock_fun,
- send_fd_t send_fd_fun, close_t close_fun);
+run(const socket_type input_sd, const socket_type output_sd,
+ get_sock_t get_sock_fun, send_sd_t send_sd_fun, close_t close_fun);
} // namespace socket_creator
} // NAMESPACE ISC
diff --git a/src/bin/sockcreator/tests/sockcreator_tests.cc b/src/bin/sockcreator/tests/sockcreator_tests.cc
index 9604567..64b3774 100644
--- a/src/bin/sockcreator/tests/sockcreator_tests.cc
+++ b/src/bin/sockcreator/tests/sockcreator_tests.cc
@@ -15,7 +15,7 @@
#include "../sockcreator.h"
#include <util/unittests/fork.h>
-#include <util/io/fd.h>
+#include <util/io/socket.h>
#include <boost/lexical_cast.hpp>
#include <gtest/gtest.h>
@@ -66,14 +66,14 @@ setAddressFamilyFields(sockaddr_in6* address) {
// is parameterised on the type of structure required to hold the address.
void
-tcpCheck(const int socknum) {
+tcpCheck(const socket_type socknum) {
// Sufficient to be able to listen on the socket.
EXPECT_EQ(0, listen(socknum, 1));
}
template <typename ADDRTYPE>
void
-udpCheck(const int socknum) {
+udpCheck(const socket_type socknum) {
// UDP testing is more complicated than TCP: send a packet to ourselves and
// see if it arrives.
@@ -98,27 +98,28 @@ udpCheck(const int socknum) {
// The check function (tcpCheck/udpCheck) is passed as a parameter to the test
// code, so provide a conveniet typedef.
-typedef void (*socket_check_t)(const int);
+typedef void (*socket_check_t)(const socket_type);
-// Address-family-specific scoket checks.
+// Address-family-specific socket checks.
//
// The first argument is used to select the overloaded check function.
// The other argument is the socket descriptor number.
// IPv4 check
-void addressFamilySpecificCheck(const sockaddr_in*, const int, const int) {
+void addressFamilySpecificCheck(const sockaddr_in*, const socket_type,
+ const int) {
}
// IPv6 check
-void addressFamilySpecificCheck(const sockaddr_in6*, const int socknum,
- const int socket_type)
+void addressFamilySpecificCheck(const sockaddr_in6*, const socket_type socknum,
+ const int s_type)
{
int options;
socklen_t len = sizeof(options);
EXPECT_EQ(0, getsockopt(socknum, IPPROTO_IPV6, IPV6_V6ONLY, &options,
&len));
EXPECT_NE(0, options);
- if (socket_type == SOCK_DGRAM) {
+ if (s_type == SOCK_DGRAM) {
// Some more checks for UDP - MTU
#ifdef IPV6_USE_MIN_MTU /* RFC 3542, not too common yet*/
// use minimum MTU
@@ -144,10 +145,12 @@ void addressFamilySpecificCheck(const sockaddr_in6*, const int socknum,
// Just ignore the fd and pretend success. We close invalid fds in the tests.
int
-closeIgnore(int) {
+closeIgnore(socket_type) {
return (0);
}
+bool bind_failed(false);
+
// Generic version of the socket test. It creates the socket and checks that
// it is a valid descriptor. The family-specific check functions are called
// to check that the socket is valid. The function is parameterised according
@@ -157,16 +160,17 @@ closeIgnore(int) {
// socket_type Type of socket to create (SOCK_DGRAM or SOCK_STREAM)
// socket_check Associated check function - udpCheck() or tcpCheck()
template <typename ADDRTYPE>
-void testAnyCreate(int socket_type, socket_check_t socket_check) {
+void testAnyCreate(int s_type, socket_check_t socket_check) {
// Create the socket.
ADDRTYPE addr;
memset(&addr, 0, sizeof(addr));
setAddressFamilyFields(&addr);
sockaddr* addr_ptr = reinterpret_cast<sockaddr*>(&addr);
- const int socket = getSock(socket_type, addr_ptr, sizeof(addr),
- closeIgnore);
- ASSERT_GE(socket, 0) << "Couldn't create socket: failed with " <<
+ const socket_type socket = getSock(s_type, addr_ptr, &bind_failed,
+ sizeof(addr), closeIgnore);
+ ASSERT_NE(socket, invalid_socket) <<
+ "Couldn't create socket: failed with " <<
"return code " << socket << " and error " << strerror(errno);
// Perform socket-type-specific testing.
@@ -179,7 +183,7 @@ void testAnyCreate(int socket_type, socket_check_t socket_check) {
EXPECT_NE(0, options);
// ...and the address-family specific tests.
- addressFamilySpecificCheck(&addr, socket, socket_type);
+ addressFamilySpecificCheck(&addr, socket, s_type);
// Tidy up and exit.
EXPECT_EQ(0, close(socket));
@@ -208,7 +212,7 @@ bool close_called(false);
// You can use it as a close mockup. If you care about checking if it was really
// called, you can use the close_called variable. But set it to false before the
// test.
-int closeCall(int socket) {
+int closeCall(socket_type socket) {
close(socket);
close_called = true;
return (0);
@@ -220,8 +224,11 @@ TEST(get_sock, fail_with_nonsense) {
sockaddr addr;
memset(&addr, 0, sizeof(addr));
close_called = false;
- ASSERT_EQ(-1, getSock(0, &addr, sizeof addr, closeCall));
+
+ ASSERT_EQ(invalid_socket,
+ getSock(0, &addr, &bind_failed, sizeof addr, closeCall));
ASSERT_FALSE(close_called); // The "socket" call should have failed already
+ ASSERT_FALSE(bind_failed);
}
// Bind should have failed here
@@ -234,9 +241,12 @@ TEST(get_sock, fail_with_bind) {
// possible to bind it.
addr.sin_addr.s_addr = inet_addr("192.0.2.1");
close_called = false;
- ASSERT_EQ(-2, getSock(SOCK_STREAM, reinterpret_cast<sockaddr*>(&addr),
- sizeof addr, closeCall));
+ ASSERT_EQ(invalid_socket, getSock(SOCK_STREAM,
+ reinterpret_cast<sockaddr*>(&addr),
+ &bind_failed,
+ sizeof addr, closeCall));
ASSERT_TRUE(close_called); // The "socket" call should have failed already
+ ASSERT_TRUE(bind_failed);
}
// The main run() function in the socket creator takes three functions to
@@ -255,12 +265,11 @@ TEST(get_sock, fail_with_bind) {
//
// Other possible return values are:
//
-// -1: The simulated bind() call has failed
-// -2: The simulated socket() call has failed
-int
-getSockDummy(const int type, struct sockaddr* addr, const socklen_t,
- const close_t) {
- int result = 0;
+// invalid_socket: The simulated socket() or bind() call has failed
+socket_type
+getSockDummy(const int type, struct sockaddr* addr, bool* bf,
+ const socklen_t, const close_t) {
+ socket_type result = 0;
int port = 0;
// Validate type field
@@ -293,9 +302,11 @@ getSockDummy(const int type, struct sockaddr* addr, const socklen_t,
if (port != 0xffff) {
errno = 0;
if (port == 0xbbbb) {
- return (-2);
+ *bf = true;
+ return (invalid_socket);
} else if (port == 0xcccc) {
- return (-1);
+ *bf = false;
+ return (invalid_socket);
} else {
result |= 0x10;
}
@@ -305,12 +316,12 @@ getSockDummy(const int type, struct sockaddr* addr, const socklen_t,
// Dummy send function - return data (the result of getSock()) to the destination.
int
-send_FdDummy(const int destination, const int what) {
+send_SdDummy(const socket_type destination, const socket_type what) {
// Make sure it is 1 byte so we know the length. We do not use more during
// the test anyway. And even with the LS bute, we can distinguish between
// the different results.
- const char fd_data = what & 0xff;
- const bool status = write_data(destination, &fd_data, sizeof(fd_data));
+ const char sd_data = what & 0xff;
+ const bool status = write_data(destination, &sd_data, sizeof(sd_data));
return (status ? 0 : -1);
}
@@ -322,31 +333,31 @@ void runTest(const char* input_data, const size_t input_size,
const char* output_data, const size_t output_size,
bool should_succeed = true,
const close_t test_close = closeIgnore,
- const send_fd_t send_fd = send_FdDummy)
+ const send_sd_t send_sd = send_SdDummy)
{
// Prepare the input feeder and output checker processes. The feeder
// process sends data from the client to run() and the checker process
// reads the response and checks it against the expected response.
- int input_fd = 0;
- const pid_t input = provide_input(&input_fd, input_data, input_size);
+ socket_type input_sd = 0;
+ const pid_t input = provide_input(&input_sd, input_data, input_size);
ASSERT_NE(-1, input) << "Couldn't start input feeder";
- int output_fd = 0;
- const pid_t output = check_output(&output_fd, output_data, output_size);
+ socket_type output_sd = 0;
+ const pid_t output = check_output(&output_sd, output_data, output_size);
ASSERT_NE(-1, output) << "Couldn't start output checker";
// Run the body
if (should_succeed) {
- EXPECT_NO_THROW(run(input_fd, output_fd, getSockDummy, send_fd,
+ EXPECT_NO_THROW(run(input_sd, output_sd, getSockDummy, send_sd,
test_close));
} else {
- EXPECT_THROW(run(input_fd, output_fd, getSockDummy, send_fd,
+ EXPECT_THROW(run(input_sd, output_sd, getSockDummy, send_sd,
test_close), isc::socket_creator::SocketCreatorError);
}
// Close the pipes
- close(input_fd);
- close(output_fd);
+ close(input_sd);
+ close(output_sd);
// Check the subprocesses say everything is OK too
EXPECT_TRUE(process_ok(input));
@@ -405,7 +416,7 @@ TEST(run, bad_sockets) {
// A close that fails. (This causes an abort.)
int
-closeFail(int) {
+closeFail(socket_type) {
return (-1);
}
@@ -415,18 +426,18 @@ TEST(run, cant_close) {
false, closeFail);
}
-// A send of the file descriptor that fails. In this case we expect the client
-// to receive the "S" indicating that the descriptor is being sent and nothing
-// else. This causes an abort.
+// A send of the socket descriptor that fails. In this case we expect
+// the client to receive the "S" indicating that the descriptor is
+// being sent and nothing else. This causes an abort.
int
-sendFDFail(const int, const int) {
- return (FD_SYSTEM_ERROR);
+sendSDFail(const socket_type, const socket_type) {
+ return (SOCKET_SYSTEM_ERROR);
}
-TEST(run, cant_send_fd) {
+TEST(run, cant_send_sd) {
runTest("SU4\xff\xff\0\0\0\0", 9,
"S", 1,
- false, closeIgnore, sendFDFail);
+ false, closeIgnore, sendSDFail);
}
} // Anonymous namespace
diff --git a/src/bin/xfrout/tests/xfrout_test.py.in b/src/bin/xfrout/tests/xfrout_test.py.in
index e4fc873..10897d4 100644
--- a/src/bin/xfrout/tests/xfrout_test.py.in
+++ b/src/bin/xfrout/tests/xfrout_test.py.in
@@ -1161,12 +1161,12 @@ class TestUnixSockServer(unittest.TestCase):
# Some test below modify these module-wide attributes. We'll need
# to restore them at the end of each test, so we remember them here.
self.__select_bak = xfrout.select.select
- self.__recv_fd_back = xfrout.recv_fd
+ self.__recv_socket_back = xfrout.recv_socket
def tearDown(self):
# Restore possibly faked module-wide attributes.
xfrout.select.select = self.__select_bak
- xfrout.recv_fd = self.__recv_fd_back
+ xfrout.recv_socket = self.__recv_socket_back
def test_tsig_keyring(self):
"""
@@ -1439,10 +1439,10 @@ class TestUnixSockServer(unittest.TestCase):
self.__select_return_redable = [MySocket(socket.AF_INET6,
socket.SOCK_STREAM)]
- # Check that loop terminates if recv_fd() fails.
+ # Check that loop terminates if recv_socket() fails.
for ret_code in [-1, FD_SYSTEM_ERROR]:
- # fake recv_fd so it returns the faked failure code.
- xfrout.recv_fd = lambda fileno: ret_code
+ # fake recv_socket so it returns the faked failure code.
+ xfrout.recv_socket = lambda fileno: ret_code
# reset the counter, go to the loop.
self.__select_count = 0
@@ -1453,7 +1453,7 @@ class TestUnixSockServer(unittest.TestCase):
# Next, we test the case where recf_fd succeeds but receiving the
# request fails.
self.__select_count = 0
- xfrout.recv_fd = lambda fileno: 1
+ xfrout.recv_socket = lambda fileno: 1
self.unix._receive_query_message = lambda fd: None
self.unix._select_loop(self.__select_return_redable[0])
self.assertEqual(1, self.__select_count)
diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in
index 6576432..4ed2d35 100755
--- a/src/bin/xfrout/xfrout.py.in
+++ b/src/bin/xfrout/xfrout.py.in
@@ -729,7 +729,7 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
the calling thread will terminate.
"""
- sock_fd = recv_fd(request.fileno())
+ sock_fd = recv_socket(request.fileno())
if sock_fd < 0:
logger.warn(XFROUT_RECEIVE_FILE_DESCRIPTOR_ERROR)
return False
diff --git a/src/lib/asiodns/asiodns_messages.mes b/src/lib/asiodns/asiodns_messages.mes
index 8fbafdd..14892be 100644
--- a/src/lib/asiodns/asiodns_messages.mes
+++ b/src/lib/asiodns/asiodns_messages.mes
@@ -14,13 +14,13 @@
$NAMESPACE isc::asiodns
-% ASIODNS_FD_ADD_TCP adding a new TCP server by opened fd %1
-A debug message informing about installing a file descriptor as a server.
-The file descriptor number is noted.
+% ASIODNS_SOCKET_ADD_TCP adding a new TCP server by opened socket %1
+A debug message informing about installing a socket descriptor as a server.
+The socket descriptor number is noted.
-% ASIODNS_FD_ADD_UDP adding a new UDP server by opened fd %1
-A debug message informing about installing a file descriptor as a server.
-The file descriptor number is noted.
+% ASIODNS_SOCKET_ADD_UDP adding a new UDP server by opened socket %1
+A debug message informing about installing a socket descriptor as a server.
+The socket descriptor number is noted.
% ASIODNS_FETCH_COMPLETED upstream fetch to %1(%2) has now completed
A debug message, this records that the upstream fetch (a query made by the
diff --git a/src/lib/asiodns/dns_service.cc b/src/lib/asiodns/dns_service.cc
index 2cfdea5..d07f978 100644
--- a/src/lib/asiodns/dns_service.cc
+++ b/src/lib/asiodns/dns_service.cc
@@ -27,6 +27,7 @@
#include <boost/foreach.hpp>
+using asio::detail::socket_type;
using namespace isc::asiolink;
namespace isc {
@@ -54,8 +55,9 @@ public:
DNSLookup* lookup_;
DNSAnswer* answer_;
- template<class Ptr, class Server> void addServerFromFD(int fd, int af) {
- Ptr server(new Server(io_service_.get_io_service(), fd, af, checkin_,
+ template<class Ptr, class Server>
+ void addServerFromSD(socket_type sd, int af) {
+ Ptr server(new Server(io_service_.get_io_service(), sd, af, checkin_,
lookup_, answer_));
(*server)();
servers_.push_back(server);
@@ -73,21 +75,23 @@ DNSService::~DNSService() {
delete impl_;
}
-void DNSService::addServerTCPFromFD(int fd, int af) {
- impl_->addServerFromFD<DNSServiceImpl::TCPServerPtr, TCPServer>(fd, af);
+void DNSService::addServerTCPFromSD(socket_type sd, int af) {
+ impl_->addServerFromSD<DNSServiceImpl::TCPServerPtr, TCPServer>(sd, af);
}
-void DNSService::addServerUDPFromFD(int fd, int af, ServerFlag options) {
+void
+DNSService::addServerUDPFromSD(socket_type sd, int af, ServerFlag options)
+{
if ((~SERVER_DEFINED_FLAGS & static_cast<unsigned int>(options)) != 0) {
isc_throw(isc::InvalidParameter, "Invalid DNS/UDP server option: "
<< options);
}
if ((options & SERVER_SYNC_OK) != 0) {
- impl_->addServerFromFD<DNSServiceImpl::SyncUDPServerPtr,
- SyncUDPServer>(fd, af);
+ impl_->addServerFromSD<DNSServiceImpl::SyncUDPServerPtr,
+ SyncUDPServer>(sd, af);
} else {
- impl_->addServerFromFD<DNSServiceImpl::UDPServerPtr, UDPServer>(
- fd, af);
+ impl_->addServerFromSD<DNSServiceImpl::UDPServerPtr, UDPServer>(
+ sd, af);
}
}
diff --git a/src/lib/asiodns/dns_service.h b/src/lib/asiodns/dns_service.h
index 8f2f6d7..540d506 100644
--- a/src/lib/asiodns/dns_service.h
+++ b/src/lib/asiodns/dns_service.h
@@ -79,8 +79,8 @@ public:
/// \brief The destructor.
virtual ~DNSServiceBase() {}
- virtual void addServerTCPFromFD(int fd, int af) = 0;
- virtual void addServerUDPFromFD(int fd, int af,
+ virtual void addServerTCPFromSD(asio::detail::socket_type sd, int af) = 0;
+ virtual void addServerUDPFromSD(asio::detail::socket_type sd, int af,
ServerFlag options = SERVER_DEFAULT) = 0;
virtual void clearServers() = 0;
@@ -148,7 +148,7 @@ public:
/// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6.
/// \throw isc::asiolink::IOError when a low-level error happens, like the
/// fd is not a valid descriptor or it can't be listened on.
- virtual void addServerTCPFromFD(int fd, int af);
+ virtual void addServerTCPFromSD(asio::detail::socket_type sd, int af);
/// \brief Add another UDP server to the service from already opened
/// file descriptor
@@ -168,7 +168,7 @@ public:
/// or the given \c options include an unsupported or invalid value.
/// \throw isc::asiolink::IOError when a low-level error happens, like the
/// fd is not a valid descriptor or it can't be listened on.
- virtual void addServerUDPFromFD(int fd, int af,
+ virtual void addServerUDPFromSD(asio::detail::socket_type sd, int af,
ServerFlag options = SERVER_DEFAULT);
/// \brief Remove all servers from the service
diff --git a/src/lib/asiodns/sync_udp_server.cc b/src/lib/asiodns/sync_udp_server.cc
index a31301d..8861f3d 100644
--- a/src/lib/asiodns/sync_udp_server.cc
+++ b/src/lib/asiodns/sync_udp_server.cc
@@ -33,13 +33,15 @@
#include <errno.h>
using namespace std;
+using asio::detail::socket_type;
using namespace isc::asiolink;
namespace isc {
namespace asiodns {
-SyncUDPServer::SyncUDPServer(asio::io_service& io_service, const int fd,
- const int af, asiolink::SimpleCallback* checkin,
+SyncUDPServer::SyncUDPServer(asio::io_service& io_service,
+ const socket_type sd, const int af,
+ asiolink::SimpleCallback* checkin,
DNSLookup* lookup, DNSAnswer* answer) :
output_buffer_(new isc::util::OutputBuffer(0)),
query_(new isc::dns::Message(isc::dns::Message::PARSE)),
@@ -51,11 +53,11 @@ SyncUDPServer::SyncUDPServer(asio::io_service& io_service, const int fd,
isc_throw(InvalidParameter, "Address family must be either AF_INET "
"or AF_INET6, not " << af);
}
- LOG_DEBUG(logger, DBGLVL_TRACE_BASIC, ASIODNS_FD_ADD_UDP).arg(fd);
+ LOG_DEBUG(logger, DBGLVL_TRACE_BASIC, ASIODNS_SOCKET_ADD_UDP).arg(sd);
try {
socket_.reset(new asio::ip::udp::socket(io_service));
socket_->assign(af == AF_INET6 ? asio::ip::udp::v6() :
- asio::ip::udp::v4(), fd);
+ asio::ip::udp::v4(), sd);
} catch (const std::exception& exception) {
// Whatever the thing throws, it is something from ASIO and we
// convert it
diff --git a/src/lib/asiodns/sync_udp_server.h b/src/lib/asiodns/sync_udp_server.h
index 9718422..c1e8ea0 100644
--- a/src/lib/asiodns/sync_udp_server.h
+++ b/src/lib/asiodns/sync_udp_server.h
@@ -52,7 +52,8 @@ public:
/// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6
/// \throw isc::asiolink::IOError when a low-level error happens, like the
/// fd is not a valid descriptor.
- SyncUDPServer(asio::io_service& io_service, const int fd, const int af,
+ SyncUDPServer(asio::io_service& io_service,
+ const asio::detail::socket_type sd, const int af,
isc::asiolink::SimpleCallback* checkin = NULL,
DNSLookup* lookup = NULL, DNSAnswer* answer = NULL);
diff --git a/src/lib/asiodns/tcp_server.cc b/src/lib/asiodns/tcp_server.cc
index 8e4b4d6..9acaa9c 100644
--- a/src/lib/asiodns/tcp_server.cc
+++ b/src/lib/asiodns/tcp_server.cc
@@ -33,6 +33,7 @@
#include <asiodns/logger.h>
using namespace asio;
+using asio::detail::socket_type;
using asio::ip::udp;
using asio::ip::tcp;
@@ -47,7 +48,7 @@ namespace asiodns {
/// The following functions implement the \c TCPServer class.
///
/// The constructor
-TCPServer::TCPServer(io_service& io_service, int fd, int af,
+TCPServer::TCPServer(io_service& io_service, socket_type sd, int af,
const SimpleCallback* checkin,
const DNSLookup* lookup,
const DNSAnswer* answer) :
@@ -59,11 +60,11 @@ TCPServer::TCPServer(io_service& io_service, int fd, int af,
isc_throw(InvalidParameter, "Address family must be either AF_INET "
"or AF_INET6, not " << af);
}
- LOG_DEBUG(logger, DBGLVL_TRACE_BASIC, ASIODNS_FD_ADD_TCP).arg(fd);
+ LOG_DEBUG(logger, DBGLVL_TRACE_BASIC, ASIODNS_SOCKET_ADD_TCP).arg(sd);
try {
acceptor_.reset(new tcp::acceptor(io_service));
- acceptor_->assign(af == AF_INET6 ? tcp::v6() : tcp::v4(), fd);
+ acceptor_->assign(af == AF_INET6 ? tcp::v6() : tcp::v4(), sd);
acceptor_->listen();
} catch (const std::exception& exception) {
// Whatever the thing throws, it is something from ASIO and we convert
diff --git a/src/lib/asiodns/tcp_server.h b/src/lib/asiodns/tcp_server.h
index 01695e4..ad5dade 100644
--- a/src/lib/asiodns/tcp_server.h
+++ b/src/lib/asiodns/tcp_server.h
@@ -39,7 +39,7 @@ class TCPServer : public virtual DNSServer, public virtual coroutine {
public:
/// \brief Constructor
/// \param io_service the asio::io_service to work with
- /// \param fd the file descriptor of opened TCP socket
+ /// \param sd the socket descriptor of opened TCP socket
/// \param af address family of the socket, either AF_INET or AF_INET6
/// \param checkin the callbackprovider for non-DNS events
/// \param lookup the callbackprovider for DNS lookup events
@@ -47,8 +47,8 @@ public:
/// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6
/// \throw isc::asiolink::IOError when a low-level error happens, like the
/// fd is not a valid descriptor or it can't be listened on.
- TCPServer(asio::io_service& io_service, int fd, int af,
- const isc::asiolink::SimpleCallback* checkin = NULL,
+ TCPServer(asio::io_service& io_service, asio::detail::socket_type sd,
+ int af, const isc::asiolink::SimpleCallback* checkin = NULL,
const DNSLookup* lookup = NULL, const DNSAnswer* answer = NULL);
void operator()(asio::error_code ec = asio::error_code(),
diff --git a/src/lib/asiodns/tests/dns_server_unittest.cc b/src/lib/asiodns/tests/dns_server_unittest.cc
index a5e83c7..c84a32e 100644
--- a/src/lib/asiodns/tests/dns_server_unittest.cc
+++ b/src/lib/asiodns/tests/dns_server_unittest.cc
@@ -73,6 +73,7 @@
using namespace isc::asiolink;
using namespace isc::asiodns;
using namespace asio;
+using namespace asio::detail;
namespace {
const char* const server_ip = "::1";
@@ -414,15 +415,15 @@ class DNSServerTestBase : public::testing::Test {
static bool io_service_is_time_out;
};
-// Initialization (by the file descriptor)
+// Initialization (by the socket descriptor)
template<class UDPServerClass>
-class FdInit : public DNSServerTestBase<UDPServerClass> {
+class SocketInit : public DNSServerTestBase<UDPServerClass> {
private:
- // Opens the file descriptor for us
- // It uses the low-level C api, as it seems to be the easiest way to get
- // a raw file descriptor. It also is what the socket creator does and this
- // API is aimed to it.
- int getFd(int type) {
+ // Opens the socket descriptor for us
+ // It uses the low-level C api, as it seems to be the easiest way
+ // to get a raw socket descriptor. It also is what the socket
+ // creator does and this API is aimed to it.
+ socket_type getSocket(int type) {
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
@@ -437,24 +438,24 @@ private:
isc_throw(IOError, "getaddrinfo failed: " << gai_strerror(error));
}
- int sock;
+ socket_type sock;
const int on(1);
// Go as far as you can and stop on failure
// Create the socket
// set the options
// and bind it
- const bool failed((sock = socket(res->ai_family, res->ai_socktype,
- res->ai_protocol)) == -1 ||
+ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ const bool failed(sock == invalid_socket ||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) == -1 ||
bind(sock, res->ai_addr, res->ai_addrlen) == -1);
// No matter if it succeeded or not, free the address info
freeaddrinfo(res);
if (failed) {
- if (sock != -1) {
+ if (sock != invalid_socket) {
close(sock);
}
- return (-1);
+ return (invalid_socket);
} else {
return (sock);
}
@@ -462,14 +463,16 @@ private:
protected:
// Using SetUp here so we can ASSERT_*
void SetUp() {
- const int fdUDP(getFd(SOCK_DGRAM));
- ASSERT_NE(-1, fdUDP) << strerror(errno);
- this->udp_server_ = new UDPServerClass(this->service, fdUDP, AF_INET6,
+ const socket_type socketUDP(getSocket(SOCK_DGRAM));
+ ASSERT_NE(invalid_socket, socketUDP) << strerror(errno);
+ this->udp_server_ = new UDPServerClass(this->service,
+ socketUDP, AF_INET6,
this->checker_, this->lookup_,
this->answer_);
- const int fdTCP(getFd(SOCK_STREAM));
- ASSERT_NE(-1, fdTCP) << strerror(errno);
- this->tcp_server_ = new TCPServer(this->service, fdTCP, AF_INET6,
+ const socket_type socketTCP(getSocket(SOCK_STREAM));
+ ASSERT_NE(invalid_socket, socketTCP) << strerror(errno);
+ this->tcp_server_ = new TCPServer(this->service,
+ socketTCP, AF_INET6,
this->checker_, this->lookup_,
this->answer_);
}
@@ -479,7 +482,7 @@ protected:
template<class Parent>
class DNSServerTest : public Parent { };
-typedef ::testing::Types<FdInit<UDPServer>, FdInit<SyncUDPServer> >
+typedef ::testing::Types<SocketInit<UDPServer>, SocketInit<SyncUDPServer> >
ServerTypes;
TYPED_TEST_CASE(DNSServerTest, ServerTypes);
@@ -629,38 +632,40 @@ TYPED_TEST(DNSServerTestBase, invalidFamily) {
}
// It raises an exception when invalid address family is passed
-TYPED_TEST(DNSServerTestBase, invalidTCPFD) {
+TYPED_TEST(DNSServerTestBase, invalidTCPSocket) {
// We abuse DNSServerTestBase for this test, as we don't need the
// initialization.
/*
- FIXME: The UDP server doesn't fail reliably with an invalid FD.
+ FIXME: The UDP server doesn't fail reliably with an invalid socket.
We need to find a way to trigger it reliably (it seems epoll
asio backend does fail as it tries to insert it right away, but
not the others, maybe we could make it run this at last on epoll-based
systems).
- EXPECT_THROW(UDPServer(service, -1, AF_INET, checker_, lookup_,
+ EXPECT_THROW(UDPServer(service, invalid_socket, AF_INET, checker_, lookup_,
answer_), isc::asiolink::IOError);
*/
- EXPECT_THROW(TCPServer(this->service, -1, AF_INET, this->checker_,
+ EXPECT_THROW(TCPServer(this->service, invalid_socket,
+ AF_INET, this->checker_,
this->lookup_, this->answer_),
isc::asiolink::IOError);
}
-TYPED_TEST(DNSServerTestBase, DISABLED_invalidUDPFD) {
+TYPED_TEST(DNSServerTestBase, DISABLED_invalidUDPSocket) {
/*
- FIXME: The UDP server doesn't fail reliably with an invalid FD.
+ FIXME: The UDP server doesn't fail reliably with an invalid socket.
We need to find a way to trigger it reliably (it seems epoll
asio backend does fail as it tries to insert it right away, but
not the others, maybe we could make it run this at least on epoll-based
systems).
*/
- EXPECT_THROW(TypeParam(this->service, -1, AF_INET, this->checker_,
+ EXPECT_THROW(TypeParam(this->service, invalid_socket,
+ AF_INET, this->checker_,
this->lookup_, this->answer_),
isc::asiolink::IOError);
}
// A specialized test type for SyncUDPServer.
-typedef FdInit<SyncUDPServer> SyncServerTest;
+typedef SocketInit<SyncUDPServer> SyncServerTest;
// Check it rejects some of the unsupported operations
TEST_F(SyncServerTest, unsupportedOps) {
diff --git a/src/lib/asiodns/tests/dns_service_unittest.cc b/src/lib/asiodns/tests/dns_service_unittest.cc
index ce8eee9..9b5e3c5 100644
--- a/src/lib/asiodns/tests/dns_service_unittest.cc
+++ b/src/lib/asiodns/tests/dns_service_unittest.cc
@@ -36,6 +36,7 @@ using namespace isc::asiolink;
using namespace isc::asiodns;
using boost::scoped_ptr;
using boost::lexical_cast;
+using namespace asio::detail;
namespace {
const char* const TEST_SERVER_PORT = "53535";
@@ -71,7 +72,7 @@ public:
IOService& io_service_;
};
-// A test fixture to check creation of UDP servers from a socket FD, changing
+// A test fixture to check creation of UDP servers from a socket, changing
// options.
class UDPDNSServiceTest : public::testing::Test {
private:
@@ -154,18 +155,18 @@ private:
IOService* UDPDNSServiceTest::current_service;
bool UDPDNSServiceTest::io_service_is_time_out;
-// A helper socket FD creator for given address and port. It's generally
+// A helper socket creator for given address and port. It's generally
// expected to succeed; on failure it simply throws an exception to make
// the test fail.
-int
-getSocketFD(int family, const char* const address, const char* const port) {
+socket_type
+getSocketSD(int family, const char* const address, const char* const port) {
struct addrinfo hints, *res = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
- int s = -1;
+ socket_type s = invalid_socket;
int error = getaddrinfo(address, port, &hints, &res);
if (error == 0) {
// If getaddrinfo returns 0, res should be set to a non NULL valid
@@ -173,14 +174,14 @@ getSocketFD(int family, const char* const address, const char* const port) {
// it, so we satisfy them here.
if (res != NULL) {
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (s >= 0) {
+ if (s != invalid_socket) {
error = bind(s, res->ai_addr, res->ai_addrlen);
}
freeaddrinfo(res);
}
}
if (error != 0) {
- if (s >= 0) {
+ if (s != invalid_socket) {
close(s);
}
isc_throw(isc::Unexpected, "failed to open test socket");
@@ -188,20 +189,20 @@ getSocketFD(int family, const char* const address, const char* const port) {
return (s);
}
-TEST_F(UDPDNSServiceTest, defaultUDPServerFromFD) {
+TEST_F(UDPDNSServiceTest, defaultUDPServerFromSD) {
// If no option is explicitly specified, an asynchronous server should be
// created. So the two output buffers should be different.
- dns_service.addServerUDPFromFD(getSocketFD(AF_INET6, TEST_IPV6_ADDR,
+ dns_service.addServerUDPFromSD(getSocketSD(AF_INET6, TEST_IPV6_ADDR,
TEST_SERVER_PORT), AF_INET6);
runService();
EXPECT_TRUE(serverStopSucceed());
EXPECT_NE(first_buffer_, second_buffer_);
}
-TEST_F(UDPDNSServiceTest, explicitDefaultUDPServerFromFD) {
+TEST_F(UDPDNSServiceTest, explicitDefaultUDPServerFromSD) {
// If "default" option is explicitly specified, the effect should be the
// same as the previous case.
- dns_service.addServerUDPFromFD(getSocketFD(AF_INET6, TEST_IPV6_ADDR,
+ dns_service.addServerUDPFromSD(getSocketSD(AF_INET6, TEST_IPV6_ADDR,
TEST_SERVER_PORT),
AF_INET6, DNSService::SERVER_DEFAULT);
runService();
@@ -209,11 +210,11 @@ TEST_F(UDPDNSServiceTest, explicitDefaultUDPServerFromFD) {
EXPECT_NE(first_buffer_, second_buffer_);
}
-TEST_F(UDPDNSServiceTest, syncUDPServerFromFD) {
+TEST_F(UDPDNSServiceTest, syncUDPServerFromSD) {
// If "SYNC_OK" option is specified, a synchronous server should be
// created. It will reuse the output buffer, so the recorded two pointer
// should be identical.
- dns_service.addServerUDPFromFD(getSocketFD(AF_INET6, TEST_IPV6_ADDR,
+ dns_service.addServerUDPFromSD(getSocketSD(AF_INET6, TEST_IPV6_ADDR,
TEST_SERVER_PORT),
AF_INET6, DNSService::SERVER_SYNC_OK);
runService();
@@ -221,10 +222,10 @@ TEST_F(UDPDNSServiceTest, syncUDPServerFromFD) {
EXPECT_EQ(first_buffer_, second_buffer_);
}
-TEST_F(UDPDNSServiceTest, addUDPServerFromFDWithUnknownOption) {
+TEST_F(UDPDNSServiceTest, addUDPServerFromSDWithUnknownOption) {
// Use of undefined/incompatible options should result in an exception.
- EXPECT_THROW(dns_service.addServerUDPFromFD(
- getSocketFD(AF_INET6, TEST_IPV6_ADDR, TEST_SERVER_PORT),
+ EXPECT_THROW(dns_service.addServerUDPFromSD(
+ getSocketSD(AF_INET6, TEST_IPV6_ADDR, TEST_SERVER_PORT),
AF_INET6, static_cast<DNSService::ServerFlag>(2)),
isc::InvalidParameter);
}
diff --git a/src/lib/asiodns/udp_server.cc b/src/lib/asiodns/udp_server.cc
index 0f5456b..b0fd353 100644
--- a/src/lib/asiodns/udp_server.cc
+++ b/src/lib/asiodns/udp_server.cc
@@ -34,6 +34,7 @@
#include <dns/opcode.h>
using namespace asio;
+using asio::detail::socket_type;
using asio::ip::udp;
using isc::log::dlog;
@@ -62,7 +63,7 @@ struct UDPServer::Data {
Data(io_service& io_service, const ip::address& addr, const uint16_t port,
SimpleCallback* checkin, DNSLookup* lookup, DNSAnswer* answer) :
io_(io_service), done_(false),
- checkin_callback_(checkin),lookup_callback_(lookup),
+ checkin_callback_(checkin), lookup_callback_(lookup),
answer_callback_(answer)
{
// We must use different instantiations for v4 and v6;
@@ -75,20 +76,21 @@ struct UDPServer::Data {
}
socket_->bind(udp::endpoint(addr, port));
}
- Data(io_service& io_service, int fd, int af, SimpleCallback* checkin,
- DNSLookup* lookup, DNSAnswer* answer) :
+ Data(io_service& io_service, socket_type sd, int af,
+ SimpleCallback* checkin, DNSLookup* lookup, DNSAnswer* answer) :
io_(io_service), done_(false),
checkin_callback_(checkin),lookup_callback_(lookup),
answer_callback_(answer)
{
if (af != AF_INET && af != AF_INET6) {
- isc_throw(InvalidParameter, "Address family must be either AF_INET "
+ isc_throw(InvalidParameter,
+ "Address family must be either AF_INET "
"or AF_INET6, not " << af);
}
- LOG_DEBUG(logger, DBGLVL_TRACE_BASIC, ASIODNS_FD_ADD_UDP).arg(fd);
+ LOG_DEBUG(logger, DBGLVL_TRACE_BASIC, ASIODNS_SOCKET_ADD_UDP).arg(sd);
try {
socket_.reset(new udp::socket(io_service));
- socket_->assign(af == AF_INET6 ? udp::v6() : udp::v4(), fd);
+ socket_->assign(af == AF_INET6 ? udp::v6() : udp::v4(), sd);
} catch (const std::exception& exception) {
// Whatever the thing throws, it is something from ASIO and we
// convert it
@@ -182,10 +184,10 @@ struct UDPServer::Data {
///
/// The constructor. It just creates new internal state object
/// and lets it handle the initialization.
-UDPServer::UDPServer(io_service& io_service, int fd, int af,
+UDPServer::UDPServer(io_service& io_service, socket_type sd, int af,
SimpleCallback* checkin, DNSLookup* lookup,
DNSAnswer* answer) :
- data_(new Data(io_service, fd, af, checkin, lookup, answer))
+ data_(new Data(io_service, sd, af, checkin, lookup, answer))
{ }
/// The function operator is implemented with the "stackless coroutine"
diff --git a/src/lib/asiodns/udp_server.h b/src/lib/asiodns/udp_server.h
index b32c06c..fb9f0a7 100644
--- a/src/lib/asiodns/udp_server.h
+++ b/src/lib/asiodns/udp_server.h
@@ -41,7 +41,7 @@ class UDPServer : public virtual DNSServer, public virtual coroutine {
public:
/// \brief Constructor
/// \param io_service the asio::io_service to work with
- /// \param fd the file descriptor of opened UDP socket
+ /// \param sd the socket descriptor of opened UDP socket
/// \param af address family, either AF_INET or AF_INET6
/// \param checkin the callbackprovider for non-DNS events
/// \param lookup the callbackprovider for DNS lookup events
@@ -49,8 +49,8 @@ public:
/// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6
/// \throw isc::asiolink::IOError when a low-level error happens, like the
/// fd is not a valid descriptor.
- UDPServer(asio::io_service& io_service, int fd, int af,
- isc::asiolink::SimpleCallback* checkin = NULL,
+ UDPServer(asio::io_service& io_service, asio::detail::socket_type fd,
+ int af, isc::asiolink::SimpleCallback* checkin = NULL,
DNSLookup* lookup = NULL, DNSAnswer* answer = NULL);
/// \brief The function operator
diff --git a/src/lib/asiolink/io_asio_socket.h b/src/lib/asiolink/io_asio_socket.h
index aeac63d..6024163 100644
--- a/src/lib/asiolink/io_asio_socket.h
+++ b/src/lib/asiolink/io_asio_socket.h
@@ -124,8 +124,8 @@ public:
/// This method never throws an exception.
///
/// \return The native representation of the socket. This is the socket
- /// file descriptor for UNIX-like systems.
- virtual int getNative() const = 0;
+ /// descriptor for UNIX-like systems.
+ virtual asio::detail::socket_type getNative() const = 0;
/// \brief Return the transport protocol of the socket.
///
@@ -305,9 +305,11 @@ public:
/// \brief A dummy derived method of \c IOAsioSocket::getNative().
///
- /// \return Always returns -1 as the object is not associated with a real
- /// (native) socket.
- virtual int getNative() const { return (-1); }
+ /// \return Always returns invalid_socket as the object is not
+ /// associated with a real (native) socket.
+ virtual asio::detail::socket_type getNative() const {
+ return (asio::detail::invalid_socket);
+ }
/// \brief A dummy derived method of \c IOAsioSocket::getProtocol().
///
diff --git a/src/lib/asiolink/io_socket.cc b/src/lib/asiolink/io_socket.cc
index e1498dc..70c5352 100644
--- a/src/lib/asiolink/io_socket.cc
+++ b/src/lib/asiolink/io_socket.cc
@@ -12,9 +12,11 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <asio.hpp>
+
#include "io_socket.h"
-#include <asio.hpp>
+using namespace asio::detail;
namespace isc {
namespace asiolink {
@@ -42,7 +44,7 @@ public:
///
/// This version of method always returns -1 as the object is not
/// associated with a real (native) socket.
- virtual int getNative() const { return (-1); }
+ virtual socket_type getNative() const { return (invalid_socket); }
virtual int getProtocol() const { return (protocol_); }
private:
diff --git a/src/lib/asiolink/io_socket.h b/src/lib/asiolink/io_socket.h
index ab6479c..390f9e7 100644
--- a/src/lib/asiolink/io_socket.h
+++ b/src/lib/asiolink/io_socket.h
@@ -82,8 +82,8 @@ public:
/// This method never throws an exception.
///
/// \return The native representation of the socket. This is the socket
- /// file descriptor for UNIX-like systems.
- virtual int getNative() const = 0;
+ /// descriptor for UNIX-like systems.
+ virtual asio::detail::socket_type getNative() const = 0;
/// \brief Return the transport protocol of the socket.
///
diff --git a/src/lib/asiolink/tcp_socket.h b/src/lib/asiolink/tcp_socket.h
index 2505d7b..cacca6d 100644
--- a/src/lib/asiolink/tcp_socket.h
+++ b/src/lib/asiolink/tcp_socket.h
@@ -84,8 +84,8 @@ public:
/// \brief Destructor
virtual ~TCPSocket();
- /// \brief Return file descriptor of underlying socket
- virtual int getNative() const {
+ /// \brief Return descriptor of underlying socket
+ virtual asio::detail::socket_type getNative() const {
return (socket_.native());
}
diff --git a/src/lib/asiolink/tests/io_socket_unittest.cc b/src/lib/asiolink/tests/io_socket_unittest.cc
index 15afc17..675ad9d 100644
--- a/src/lib/asiolink/tests/io_socket_unittest.cc
+++ b/src/lib/asiolink/tests/io_socket_unittest.cc
@@ -20,13 +20,14 @@
#include <asio.hpp>
#include <asiolink/io_socket.h>
+using asio::detail::invalid_socket;
using namespace isc::asiolink;
TEST(IOSocketTest, dummySockets) {
EXPECT_EQ(IPPROTO_UDP, IOSocket::getDummyUDPSocket().getProtocol());
EXPECT_EQ(IPPROTO_TCP, IOSocket::getDummyTCPSocket().getProtocol());
- EXPECT_EQ(-1, IOSocket::getDummyUDPSocket().getNative());
- EXPECT_EQ(-1, IOSocket::getDummyTCPSocket().getNative());
+ EXPECT_EQ(invalid_socket, IOSocket::getDummyUDPSocket().getNative());
+ EXPECT_EQ(invalid_socket, IOSocket::getDummyTCPSocket().getNative());
}
diff --git a/src/lib/asiolink/udp_socket.h b/src/lib/asiolink/udp_socket.h
index c061fba..610b5dc 100644
--- a/src/lib/asiolink/udp_socket.h
+++ b/src/lib/asiolink/udp_socket.h
@@ -70,8 +70,8 @@ public:
/// \brief Destructor
virtual ~UDPSocket();
- /// \brief Return file descriptor of underlying socket
- virtual int getNative() const {
+ /// \brief Return descriptor of underlying socket
+ virtual asio::detail::socket_type getNative() const {
return (socket_.native());
}
diff --git a/src/lib/cc/session.cc b/src/lib/cc/session.cc
index 4455b68..6e1ef54 100644
--- a/src/lib/cc/session.cc
+++ b/src/lib/cc/session.cc
@@ -48,6 +48,7 @@
#include <cc/session.h>
using namespace std;
+using asio::detail::socket_type;
using namespace isc::cc;
using namespace isc::data;
@@ -88,7 +89,7 @@ public:
void startRead(boost::function<void()> user_handler);
void setTimeout(size_t seconds) { timeout_ = seconds; };
size_t getTimeout() const { return timeout_; };
- int getSocketDesc();
+ socket_type getSocketDesc();
long int sequence_; // the next sequence number to use
std::string lname_;
@@ -255,7 +256,7 @@ SessionImpl::internalRead(const asio::error_code& error,
}
}
-int
+socket_type
SessionImpl::getSocketDesc() {
/// @todo boost 1.42 uses native() method, but it is deprecated
/// in 1.49 and native_handle() is recommended instead
@@ -284,7 +285,7 @@ Session::startRead(boost::function<void()> read_callback) {
impl_->startRead(read_callback);
}
-int
+socket_type
Session::getSocketDesc() const {
return impl_->getSocketDesc();
}
diff --git a/src/lib/cc/session.h b/src/lib/cc/session.h
index 9b08232..6b81407 100644
--- a/src/lib/cc/session.h
+++ b/src/lib/cc/session.h
@@ -17,6 +17,7 @@
#include <string>
+#include <asio.hpp>
#include <boost/function.hpp>
#include <exceptions/exceptions.h>
@@ -145,7 +146,7 @@ namespace isc {
/// @brief returns socket descriptor from underlying socket connection
///
/// @param returns socket descriptor used for session connection
- virtual int getSocketDesc() const;
+ virtual asio::detail::socket_type getSocketDesc() const;
private:
void sendmsg(isc::data::ConstElementPtr msg);
void sendmsg(isc::data::ConstElementPtr env,
diff --git a/src/lib/cc/tests/session_unittests.cc b/src/lib/cc/tests/session_unittests.cc
index 528dda9..6152b50 100644
--- a/src/lib/cc/tests/session_unittests.cc
+++ b/src/lib/cc/tests/session_unittests.cc
@@ -28,6 +28,7 @@
#include <cc/data.h>
#include <session_unittests_config.h>
+using namespace asio::detail;
using namespace isc::cc;
TEST(AsioSession, establish) {
@@ -242,10 +243,10 @@ TEST_F(SessionTest, get_socket_descr) {
tds->setSendLname();
sess.establish(BIND10_TEST_SOCKET_FILE);
- int socket = 0;
+ socket_type socket = invalid_socket;
// session is established, so getSocketDesc() should work
EXPECT_NO_THROW(socket = sess.getSocketDesc());
- // expect actual socket handle to be returned, not 0
- EXPECT_LT(0, socket);
+ // expect actual socket handle to be returned, not invalid_socket
+ EXPECT_NE(socket, invalid_socket);
}
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index 4a24260..ac738ac 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -30,6 +30,7 @@
#include <util/io/pktinfo_utilities.h>
using namespace std;
+using namespace asio::detail;
using namespace isc::asiolink;
using namespace isc::util::io::internal;
@@ -110,7 +111,7 @@ bool IfaceMgr::Iface::delAddress(const isc::asiolink::IOAddress& addr) {
return (false);
}
-bool IfaceMgr::Iface::delSocket(uint16_t sockfd) {
+bool IfaceMgr::Iface::delSocket(socket_type sockfd) {
list<SocketInfo>::iterator sock = sockets_.begin();
while (sock!=sockets_.end()) {
if (sock->sockfd_ == sockfd) {
@@ -126,7 +127,7 @@ bool IfaceMgr::Iface::delSocket(uint16_t sockfd) {
IfaceMgr::IfaceMgr()
:control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
control_buf_(new char[control_buf_len_]),
- session_socket_(INVALID_SOCKET), session_callback_(NULL)
+ session_socket_(invalid_socket), session_callback_(NULL)
{
cout << "IfaceMgr initialization." << endl;
@@ -228,7 +229,7 @@ void IfaceMgr::stubDetectIfaces() {
}
bool IfaceMgr::openSockets4(const uint16_t port) {
- int sock;
+ socket_type sock;
int count = 0;
for (IfaceCollection::iterator iface = ifaces_.begin();
@@ -256,7 +257,7 @@ bool IfaceMgr::openSockets4(const uint16_t port) {
}
sock = openSocket(iface->getName(), *addr, port);
- if (sock < 0) {
+ if (sock == invalid_socket) {
cout << "Failed to open unicast socket." << endl;
return (false);
}
@@ -269,7 +270,7 @@ bool IfaceMgr::openSockets4(const uint16_t port) {
}
bool IfaceMgr::openSockets6(const uint16_t port) {
- int sock;
+ socket_type sock;
int count = 0;
for (IfaceCollection::iterator iface = ifaces_.begin();
@@ -293,7 +294,7 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
}
sock = openSocket(iface->getName(), *addr, port);
- if (sock < 0) {
+ if (sock == invalid_socket) {
cout << "Failed to open unicast socket." << endl;
return (false);
}
@@ -315,10 +316,10 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
// To receive multicast traffic, Linux requires binding socket to
// a multicast group. That in turn doesn't work on NetBSD.
- int sock2 = openSocket(iface->getName(),
- IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
- port);
- if (sock2 < 0) {
+ socket_type sock2 = openSocket(iface->getName(),
+ IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
+ port);
+ if (sock2 == invalid_socket) {
isc_throw(Unexpected, "Failed to open multicast socket on "
<< " interface " << iface->getFullName());
iface->delSocket(sock); // delete previously opened socket
@@ -381,8 +382,9 @@ IfaceMgr::getIface(const std::string& ifname) {
return (NULL); // not found
}
-int IfaceMgr::openSocket(const std::string& ifname, const IOAddress& addr,
- const uint16_t port) {
+socket_type IfaceMgr::openSocket(const std::string& ifname,
+ const IOAddress& addr,
+ const uint16_t port) {
Iface* iface = getIface(ifname);
if (!iface) {
isc_throw(BadValue, "There is no " << ifname << " interface present.");
@@ -398,9 +400,9 @@ int IfaceMgr::openSocket(const std::string& ifname, const IOAddress& addr,
}
}
-int IfaceMgr::openSocketFromIface(const std::string& ifname,
- const uint16_t port,
- const uint8_t family) {
+socket_type IfaceMgr::openSocketFromIface(const std::string& ifname,
+ const uint16_t port,
+ const uint8_t family) {
// Search for specified interface among detected interfaces.
for (IfaceCollection::iterator iface = ifaces_.begin();
iface != ifaces_.end();
@@ -442,8 +444,8 @@ int IfaceMgr::openSocketFromIface(const std::string& ifname,
isc_throw(BadValue, "There is no " << ifname << " interface present.");
}
-int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
- const uint16_t port) {
+socket_type IfaceMgr::openSocketFromAddress(const IOAddress& addr,
+ const uint16_t port) {
// Search through detected interfaces and addresses to match
// local address we got.
for (IfaceCollection::iterator iface = ifaces_.begin();
@@ -472,8 +474,8 @@ int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
isc_throw(BadValue, "There is no such address " << addr.toText());
}
-int IfaceMgr::openSocketFromRemoteAddress(const IOAddress& remote_addr,
- const uint16_t port) {
+socket_type IfaceMgr::openSocketFromRemoteAddress(const IOAddress& remote_addr,
+ const uint16_t port) {
// Get local address to be used to connect to remote location.
IOAddress local_address(getLocalAddress(remote_addr, port).getAddress());
return openSocketFromAddress(local_address, port);
@@ -509,7 +511,9 @@ IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
return IOAddress(local_address);
}
-int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port) {
+socket_type IfaceMgr::openSocket4(Iface& iface,
+ const IOAddress& addr,
+ uint16_t port) {
cout << "Creating UDP4 socket on " << iface.getFullName()
<< " " << addr.toText() << "/port=" << port << endl;
@@ -523,8 +527,8 @@ int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port) {
//addr4.sin_addr.s_addr = 0; // anyaddr: this will receive 0.0.0.0 => 255.255.255.255 traffic
// addr4.sin_addr.s_addr = 0xffffffffu; // broadcast address. This will receive 0.0.0.0 => 255.255.255.255 as well
- int sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
+ socket_type sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == invalid_socket) {
isc_throw(Unexpected, "Failed to create UDP6 socket.");
}
@@ -553,7 +557,9 @@ int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port) {
return (sock);
}
-int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
+socket_type IfaceMgr::openSocket6(Iface& iface,
+ const IOAddress& addr,
+ uint16_t port) {
cout << "Creating UDP6 socket on " << iface.getFullName()
<< " " << addr.toText() << "/port=" << port << endl;
@@ -575,8 +581,8 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
// TODO: use sockcreator once it becomes available
// make a socket
- int sock = socket(AF_INET6, SOCK_DGRAM, 0);
- if (sock < 0) {
+ socket_type sock = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (sock == invalid_socket) {
isc_throw(Unexpected, "Failed to create UDP6 socket.");
}
@@ -634,9 +640,9 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
}
bool
-IfaceMgr::joinMulticast(int sock, const std::string& ifname,
-const std::string & mcast) {
-
+IfaceMgr::joinMulticast(socket_type sock,
+ const std::string& ifname,
+ const std::string& mcast) {
struct ipv6_mreq mreq;
if (inet_pton(AF_INET6, mcast.c_str(),
@@ -833,7 +839,7 @@ IfaceMgr::receive4(uint32_t timeout) {
}
// if there is session socket registered...
- if (session_socket_ != INVALID_SOCKET) {
+ if (session_socket_ != invalid_socket) {
// at it to the set as well
FD_SET(session_socket_, &sockets);
if (maxfd < session_socket_)
@@ -862,7 +868,7 @@ IfaceMgr::receive4(uint32_t timeout) {
}
// Let's find out which socket has the data
- if ((session_socket_ != INVALID_SOCKET) && (FD_ISSET(session_socket_, &sockets))) {
+ if ((session_socket_ != invalid_socket) && (FD_ISSET(session_socket_, &sockets))) {
// something received over session socket
cout << "BIND10 command or config available over session socket." << endl;
@@ -1001,7 +1007,7 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout) {
}
// if there is session socket registered...
- if (session_socket_ != INVALID_SOCKET) {
+ if (session_socket_ != invalid_socket) {
// at it to the set as well
FD_SET(session_socket_, &sockets);
if (maxfd < session_socket_)
@@ -1030,7 +1036,7 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout) {
}
// Let's find out which socket has the data
- if ((session_socket_ != INVALID_SOCKET) && (FD_ISSET(session_socket_, &sockets))) {
+ if ((session_socket_ != invalid_socket) && (FD_ISSET(session_socket_, &sockets))) {
// something received over session socket
cout << "BIND10 command or config available over session socket." << endl;
@@ -1177,7 +1183,7 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout) {
return (pkt);
}
-uint16_t IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
+socket_type IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
Iface* iface = getIface(pkt.getIface());
if (iface == NULL) {
isc_throw(BadValue, "Tried to find socket for non-existent interface "
@@ -1199,7 +1205,7 @@ uint16_t IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
<< " does not have any suitable IPv6 sockets open.");
}
-uint16_t IfaceMgr::getSocket(isc::dhcp::Pkt4 const& pkt) {
+socket_type IfaceMgr::getSocket(isc::dhcp::Pkt4 const& pkt) {
Iface* iface = getIface(pkt.getIface());
if (iface == NULL) {
isc_throw(BadValue, "Tried to find socket for non-existent interface "
diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h
index 7de6a44..9ec2e94 100644
--- a/src/lib/dhcp/iface_mgr.h
+++ b/src/lib/dhcp/iface_mgr.h
@@ -56,7 +56,7 @@ public:
/// Holds information about socket.
struct SocketInfo {
- uint16_t sockfd_; /// socket descriptor
+ asio::detail::socket_type sockfd_; /// socket descriptor
isc::asiolink::IOAddress addr_; /// bound address
uint16_t port_; /// socket port
uint16_t family_; /// IPv4 or IPv6
@@ -66,8 +66,8 @@ public:
/// @param sockfd socket descriptor
/// @param addr an address the socket is bound to
/// @param port a port the socket is bound to
- SocketInfo(uint16_t sockfd, const isc::asiolink::IOAddress& addr,
- uint16_t port)
+ SocketInfo(asio::detail::socket_type sockfd,
+ const isc::asiolink::IOAddress& addr, uint16_t port)
:sockfd_(sockfd), addr_(addr), port_(port), family_(addr.getFamily()) { }
};
@@ -190,7 +190,7 @@ public:
///
/// @param sockfd socket descriptor to be closed/removed.
/// @return true if there was such socket, false otherwise
- bool delSocket(uint16_t sockfd);
+ bool delSocket(asio::detail::socket_type sockfd);
/// socket used to sending data
/// TODO: this should be protected
@@ -292,7 +292,7 @@ public:
/// @param pkt a packet to be transmitted
///
/// @return a socket descriptor
- uint16_t getSocket(const isc::dhcp::Pkt6& pkt);
+ asio::detail::socket_type getSocket(const isc::dhcp::Pkt6& pkt);
/// @brief Return most suitable socket for transmitting specified IPv6 packet.
///
@@ -305,7 +305,7 @@ public:
/// @param pkt a packet to be transmitted
///
/// @return a socket descriptor
- uint16_t getSocket(const isc::dhcp::Pkt4& pkt);
+ asio::detail::socket_type getSocket(const isc::dhcp::Pkt4& pkt);
/// debugging method that prints out all available interfaces
///
@@ -375,9 +375,9 @@ public:
///
/// @return socket descriptor, if socket creation, binding and multicast
/// group join were all successful.
- int openSocket(const std::string& ifname,
- const isc::asiolink::IOAddress& addr,
- const uint16_t port);
+ asio::detail::socket_type openSocket(const std::string& ifname,
+ const isc::asiolink::IOAddress& addr,
+ const uint16_t port);
/// @brief Opens UDP/IP socket and binds it to interface specified.
///
@@ -394,9 +394,9 @@ public:
/// @throw isc::Unexpected if failed to create and bind socket.
/// @throw isc::BadValue if there is no address on specified interface
/// that belongs to given family.
- int openSocketFromIface(const std::string& ifname,
- const uint16_t port,
- const uint8_t family);
+ asio::detail::socket_type openSocketFromIface(const std::string& ifname,
+ const uint16_t port,
+ const uint8_t family);
/// @brief Opens UDP/IP socket and binds to address specified
///
@@ -410,8 +410,9 @@ public:
/// @throw isc::Unexpected if failed to create and bind socket
/// @throw isc::BadValue if specified address is not available on
/// any interface
- int openSocketFromAddress(const isc::asiolink::IOAddress& addr,
- const uint16_t port);
+ asio::detail::socket_type
+ openSocketFromAddress(const isc::asiolink::IOAddress& addr,
+ const uint16_t port);
/// @brief Opens UDP/IP socket to be used to connect to remote address
///
@@ -425,8 +426,9 @@ public:
/// @return socket descriptor, if socket creation, binding and multicast
/// group join were all successful.
/// @throw isc::Unexpected if failed to create and bind socket
- int openSocketFromRemoteAddress(const isc::asiolink::IOAddress& remote_addr,
- const uint16_t port);
+ asio::detail::socket_type
+ openSocketFromRemoteAddress(const isc::asiolink::IOAddress& remote_addr,
+ const uint16_t port);
/// Opens IPv6 sockets on detected interfaces.
@@ -462,14 +464,13 @@ public:
///
/// @param socketfd socket descriptor
/// @param callback callback function
- void set_session_socket(int socketfd, SessionCallback callback) {
+ void set_session_socket(asio::detail::socket_type socketfd,
+ SessionCallback callback)
+ {
session_socket_ = socketfd;
session_callback_ = callback;
}
- /// A value of socket descriptor representing "not specified" state.
- static const int INVALID_SOCKET = -1;
-
// don't use private, we need derived classes in tests
protected:
@@ -492,7 +493,10 @@ protected:
/// @param port a port that created socket should be bound to
///
/// @return socket descriptor
- int openSocket4(Iface& iface, const isc::asiolink::IOAddress& addr, uint16_t port);
+ asio::detail::socket_type
+ openSocket4(Iface& iface,
+ const isc::asiolink::IOAddress& addr,
+ uint16_t port);
/// @brief Opens IPv6 socket.
///
@@ -505,7 +509,10 @@ protected:
/// @param port a port that created socket should be bound to
///
/// @return socket descriptor
- int openSocket6(Iface& iface, const isc::asiolink::IOAddress& addr, uint16_t port);
+ asio::detail::socket_type
+ openSocket6(Iface& iface,
+ const isc::asiolink::IOAddress& addr,
+ uint16_t port);
/// @brief Adds an interface to list of known interfaces.
///
@@ -574,7 +581,7 @@ protected:
bool os_receive4(struct msghdr& m, Pkt4Ptr& pkt);
/// socket descriptor of the session socket
- int session_socket_;
+ asio::detail::socket_type session_socket_;
/// a callback that will be called when data arrives over session_socket_
SessionCallback session_callback_;
@@ -598,7 +605,8 @@ private:
/// @return true if multicast join was successful
///
bool
- joinMulticast(int sock, const std::string& ifname,
+ joinMulticast(asio::detail::socket_type sock,
+ const std::string& ifname,
const std::string& mcast);
/// @brief Identifies local network address to be used to
diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc
index 5562551..df30578 100644
--- a/src/lib/dhcp/tests/iface_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc
@@ -28,6 +28,7 @@
#include <dhcp/dhcp4.h>
using namespace std;
+using namespace asio::detail;
using namespace isc;
using namespace isc::asiolink;
using namespace isc::dhcp;
@@ -229,14 +230,14 @@ TEST_F(IfaceMgrTest, sockets6) {
pkt6.setIface(LOOPBACK);
// bind multicast socket to port 10547
- int socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
- EXPECT_GT(socket1, 0); // socket > 0
+ socket_type socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
+ EXPECT_NE(socket1, invalid_socket); // socket > 0
EXPECT_EQ(socket1, ifacemgr->getSocket(pkt6));
// bind unicast socket to port 10548
- int socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10548);
- EXPECT_GT(socket2, 0);
+ socket_type socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10548);
+ EXPECT_NE(socket2, invalid_socket);
// removed code for binding socket twice to the same address/port
// as it caused problems on some platforms (e.g. Mac OS X)
@@ -251,21 +252,21 @@ TEST_F(IfaceMgrTest, socketsFromIface) {
boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
// Open v6 socket on loopback interface and bind to port
- int socket1 = 0;
+ socket_type socket1 = invalid_socket;
EXPECT_NO_THROW(
socket1 = ifacemgr->openSocketFromIface(LOOPBACK, PORT1, AF_INET6);
);
// Socket descriptor must be positive integer
- EXPECT_GT(socket1, 0);
+ EXPECT_NE(socket1, invalid_socket);
close(socket1);
// Open v4 socket on loopback interface and bind to different port
- int socket2 = 0;
+ socket_type socket2 = invalid_socket;
EXPECT_NO_THROW(
socket2 = ifacemgr->openSocketFromIface(LOOPBACK, PORT2, AF_INET);
);
// socket descriptor must be positive integer
- EXPECT_GT(socket2, 0);
+ EXPECT_NE(socket2, invalid_socket);
close(socket2);
}
@@ -275,23 +276,23 @@ TEST_F(IfaceMgrTest, socketsFromAddress) {
boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
// Open v6 socket on loopback interface and bind to port
- int socket1 = 0;
+ socket_type socket1 = invalid_socket;
IOAddress loAddr6("::1");
EXPECT_NO_THROW(
socket1 = ifacemgr->openSocketFromAddress(loAddr6, PORT1);
);
// socket descriptor must be positive integer
- EXPECT_GT(socket1, 0);
+ EXPECT_NE(socket1, invalid_socket);
close(socket1);
// Open v4 socket on loopback interface and bind to different port
- int socket2 = 0;
+ socket_type socket2 = invalid_socket;
IOAddress loAddr("127.0.0.1");
EXPECT_NO_THROW(
socket2 = ifacemgr->openSocketFromAddress(loAddr, PORT2);
);
// socket descriptor must be positive integer
- EXPECT_GT(socket2, 0);
+ EXPECT_NE(socket2, invalid_socket);
close(socket2);
}
@@ -301,21 +302,21 @@ TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
// Open v6 socket to connect to remote address.
// Loopback address is the only one that we know
// so let's treat it as remote address.
- int socket1 = 0;
+ socket_type socket1 = invalid_socket;
IOAddress loAddr6("::1");
EXPECT_NO_THROW(
socket1 = ifacemgr->openSocketFromRemoteAddress(loAddr6, PORT1);
);
- EXPECT_GT(socket1, 0);
+ EXPECT_NE(socket1, invalid_socket);
close(socket1);
// Open v4 socket to connect to remote address.
- int socket2 = 0;
+ socket_type socket2 = invalid_socket;
IOAddress loAddr("127.0.0.1");
EXPECT_NO_THROW(
socket2 = ifacemgr->openSocketFromRemoteAddress(loAddr, PORT2);
);
- EXPECT_GT(socket2, 0);
+ EXPECT_NE(socket2, invalid_socket);
close(socket2);
}
@@ -331,13 +332,13 @@ TEST_F(IfaceMgrTest, DISABLED_sockets6Mcast) {
IOAddress mcastAddr("ff02::1:2");
// bind multicast socket to port 10547
- int socket1 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
- EXPECT_GT(socket1, 0); // socket > 0
+ socket_type socket1 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
+ EXPECT_NE(socket1, invalid_socket); // socket > 0
// expect success. This address/port is already bound, but
// we are using SO_REUSEADDR, so we can bind it twice
- int socket2 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
- EXPECT_GT(socket2, 0);
+ socket_type socket2 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
+ EXPECT_NE(socket2, invalid_socket);
// there's no good way to test negative case here.
// we would need non-multicast interface. We will be able
@@ -359,14 +360,14 @@ TEST_F(IfaceMgrTest, sendReceive6) {
// let's assume that every supported OS have lo interface
IOAddress loAddr("::1");
- int socket1 = 0, socket2 = 0;
+ socket_type socket1 = invalid_socket, socket2 = invalid_socket;
EXPECT_NO_THROW(
socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10546);
);
- EXPECT_GT(socket1, 0);
- EXPECT_GT(socket2, 0);
+ EXPECT_NE(socket1, invalid_socket);
+ EXPECT_NE(socket2, invalid_socket);
// prepare dummy payload
@@ -416,14 +417,14 @@ TEST_F(IfaceMgrTest, sendReceive4) {
// let's assume that every supported OS have lo interface
IOAddress loAddr("127.0.0.1");
- int socket1 = 0, socket2 = 0;
+ socket_type socket1 = invalid_socket, socket2 = invalid_socket;
EXPECT_NO_THROW(
socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000 + 1);
);
- EXPECT_GE(socket1, 0);
- EXPECT_GE(socket2, 0);
+ EXPECT_NE(socket1, invalid_socket);
+ EXPECT_NE(socket2, invalid_socket);
boost::shared_ptr<Pkt4> sendPkt(new Pkt4(DHCPDISCOVER, 1234) );
@@ -506,13 +507,13 @@ TEST_F(IfaceMgrTest, socket4) {
// Let's assume that every supported OS have lo interface.
IOAddress loAddr("127.0.0.1");
// Use unprivileged port (it's convenient for running tests as non-root).
- int socket1 = 0;
+ socket_type socket1 = invalid_socket;
EXPECT_NO_THROW(
socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
);
- EXPECT_GT(socket1, 0);
+ EXPECT_GE(socket1, invalid_socket);
Pkt4 pkt(DHCPDISCOVER, 1234);
pkt.setIface(LOOPBACK);
diff --git a/src/lib/python/isc/bind10/sockcreator.py b/src/lib/python/isc/bind10/sockcreator.py
index c681d07..b064e54 100644
--- a/src/lib/python/isc/bind10/sockcreator.py
+++ b/src/lib/python/isc/bind10/sockcreator.py
@@ -20,7 +20,7 @@ import copy
import subprocess
import copy
from isc.log_messages.bind10_messages import *
-from libutil_io_python import recv_fd
+from libutil_io_python import recv_socket
logger = isc.log.Logger("boss")
@@ -195,7 +195,7 @@ class WrappedSocket:
"""
Read the file descriptor from the socket.
"""
- return recv_fd(self.fileno())
+ return recv_socket(self.fileno())
# FIXME: Any idea how to test this? Starting an external process doesn't sound
# OK
diff --git a/src/lib/python/isc/bind10/tests/sockcreator_test.py b/src/lib/python/isc/bind10/tests/sockcreator_test.py
index f67781c..cfe1f48 100644
--- a/src/lib/python/isc/bind10/tests/sockcreator_test.py
+++ b/src/lib/python/isc/bind10/tests/sockcreator_test.py
@@ -22,7 +22,7 @@ import struct
import socket
from isc.net.addr import IPAddr
import isc.log
-from libutil_io_python import send_fd
+from libutil_io_python import send_socket
from isc.bind10.sockcreator import Parser, CreatorError, WrappedSocket
class FakeCreator:
@@ -302,7 +302,7 @@ class WrapTests(unittest.TestCase):
t2 = WrappedSocket(t2)
# Transfer the descriptor
- send_fd(t1.fileno(), p1.fileno())
+ send_socket(t1.fileno(), p1.fileno())
p1.close()
p1 = socket.fromfd(t2.read_fd(), socket.AF_UNIX, socket.SOCK_STREAM)
diff --git a/src/lib/python/isc/util/cio/socketsessionforwarder_python.cc b/src/lib/python/isc/util/cio/socketsessionforwarder_python.cc
index 583a877..231e9fd 100644
--- a/src/lib/python/isc/util/cio/socketsessionforwarder_python.cc
+++ b/src/lib/python/isc/util/cio/socketsessionforwarder_python.cc
@@ -27,6 +27,8 @@
#include <string>
#include <stdexcept>
+#include <asio.hpp>
+
#include <boost/lexical_cast.hpp>
#include <exceptions/exceptions.h>
@@ -43,6 +45,7 @@ using namespace isc::util::python;
using namespace isc::util::io;
using namespace isc::util::io::internal;
using namespace isc::util::io::python;
+using asio::detail::socket_type;
using boost::lexical_cast;
// Trivial constructor.
@@ -181,19 +184,20 @@ SocketSessionForwarder_push(PyObject* po_self, PyObject* args) {
static_cast<s_SocketSessionForwarder*>(po_self);
try {
- int fd, family, type, protocol;
+ socket_type sd;
+ int family, type, protocol;
PyObject* po_local_end;
PyObject* po_remote_end;
Py_buffer py_buf;
- if (!PyArg_ParseTuple(args, "iiiiOOy*", &fd, &family, &type, &protocol,
+ if (!PyArg_ParseTuple(args, "iiiiOOy*", &sd, &family, &type, &protocol,
&po_local_end, &po_remote_end, &py_buf)) {
return (NULL);
}
struct sockaddr_storage ss_local, ss_remote;
parsePySocketAddress(po_local_end, type, protocol, &ss_local);
parsePySocketAddress(po_remote_end, type, protocol, &ss_remote);
- self->cppobj->push(fd, family, type, protocol,
+ self->cppobj->push(sd, family, type, protocol,
*convertSockAddr(&ss_local),
*convertSockAddr(&ss_remote),
py_buf.buf, py_buf.len);
diff --git a/src/lib/python/isc/util/cio/socketsessionreceiver_python.cc b/src/lib/python/isc/util/cio/socketsessionreceiver_python.cc
index c79f6e0..99629ba 100644
--- a/src/lib/python/isc/util/cio/socketsessionreceiver_python.cc
+++ b/src/lib/python/isc/util/cio/socketsessionreceiver_python.cc
@@ -28,6 +28,8 @@
#include <string>
#include <stdexcept>
+#include <asio.hpp>
+
#include <boost/lexical_cast.hpp>
#include <util/python/pycppwrapper_util.h>
@@ -41,6 +43,7 @@ using namespace std;
using namespace isc::util::python;
using namespace isc::util::io;
using namespace isc::util::io::python;
+using asio::detail::socket_type;
using boost::lexical_cast;
// Trivial constructor.
@@ -72,15 +75,15 @@ SocketSessionReceiver_init(PyObject* po_self, PyObject* args, PyObject*) {
// TypeError below.
PyObject* po_sock;
if (PyArg_ParseTuple(args, "O", &po_sock)) {
- PyObjectContainer fd_container(PyObject_CallMethod(
+ PyObjectContainer sd_container(PyObject_CallMethod(
po_sock,
const_cast<char*>("fileno"),
NULL));
- PyObjectContainer fdarg_container(
- Py_BuildValue("(O)", fd_container.get()));
- int fd;
- if (PyArg_ParseTuple(fdarg_container.get(), "i", &fd)) {
- self->cppobj = new SocketSessionReceiver(fd);
+ PyObjectContainer sdarg_container(
+ Py_BuildValue("(O)", sd_container.get()));
+ socket_type sd;
+ if (PyArg_ParseTuple(sdarg_container.get(), "i", &sd)) {
+ self->cppobj = new SocketSessionReceiver(sd);
return (0);
}
PyErr_SetString(PyExc_TypeError, "Given object's fileno() doesn't "
@@ -157,11 +160,11 @@ SocketSessionReceiver_destroy(PyObject* po_self) {
// A helper struct to automatically close a socket in an RAII manner.
struct ScopedSocket : boost::noncopyable {
- ScopedSocket(int fd) : fd_(fd) {}
+ ScopedSocket(socket_type sd) : sd_(sd) {}
~ScopedSocket() {
- close(fd_);
+ close(sd_);
}
- const int fd_;
+ const socket_type sd_;
};
PyObject*
@@ -180,7 +183,7 @@ SocketSessionReceiver_pop(PyObject* po_self, PyObject*) {
ScopedSocket sock(session.getSocket());
// Build Python socket object
- PyObjectContainer c_args(Py_BuildValue("(iiii)", sock.fd_,
+ PyObjectContainer c_args(Py_BuildValue("(iiii)", sock.sd_,
session.getFamily(),
session.getType(),
session.getProtocol()));
diff --git a/src/lib/resolve/tests/recursive_query_unittest.cc b/src/lib/resolve/tests/recursive_query_unittest.cc
index 02721f1..5120f8a 100644
--- a/src/lib/resolve/tests/recursive_query_unittest.cc
+++ b/src/lib/resolve/tests/recursive_query_unittest.cc
@@ -64,6 +64,7 @@ using namespace isc::asiodns;
using namespace isc::asiolink;
using namespace isc::dns;
using namespace isc::util;
+using namespace asio::detail;
using boost::scoped_ptr;
namespace isc {
@@ -128,30 +129,30 @@ struct ScopedAddrInfo {
struct addrinfo* res_;
};
-// Similar to ScopedAddrInfo but for socket FD. It also supports the "release"
-// operation so it can release the ownership of the FD.
+// Similar to ScopedAddrInfo but for socket. It also supports the "release"
+// operation so it can release the ownership of the handle.
// This is made non copyable to avoid making an accidental copy, which could
// result in duplicate close.
struct ScopedSocket : private boost::noncopyable {
- ScopedSocket() : s_(-1) {}
- ScopedSocket(int s) : s_(s) {}
+ ScopedSocket() : s_(invalid_socket) {}
+ ScopedSocket(socket_type s) : s_(s) {}
~ScopedSocket() {
- if (s_ >= 0) {
+ if (s_ != invalid_socket) {
close(s_);
}
}
- void reset(int new_s) {
- if (s_ >= 0) {
+ void reset(socket_type new_s) {
+ if (s_ != invalid_socket) {
close(s_);
}
s_ = new_s;
}
- int release() {
- int s = s_;
- s_ = -1;
+ socket_type release() {
+ socket_type s = s_;
+ s_ = invalid_socket;
return (s);
}
- int s_;
+ socket_type s_;
};
// This fixture is a framework for various types of network operations
@@ -186,7 +187,7 @@ protected:
sock_.reset(socket(res->ai_family, res->ai_socktype,
res->ai_protocol));
- if (sock_.s_ < 0) {
+ if (sock_.s_ == invalid_socket) {
isc_throw(IOError, "failed to open test socket");
}
const int cc = sendto(sock_.s_, test_data, sizeof(test_data), 0,
@@ -204,7 +205,7 @@ protected:
sock_.reset(socket(res->ai_family, res->ai_socktype,
res->ai_protocol));
- if (sock_.s_ < 0) {
+ if (sock_.s_ == invalid_socket) {
isc_throw(IOError, "failed to open test socket");
}
if (connect(sock_.s_, res->ai_addr, res->ai_addrlen) < 0) {
@@ -226,7 +227,7 @@ protected:
sock_.reset(socket(res->ai_family, res->ai_socktype,
res->ai_protocol));
- if (sock_.s_ < 0) {
+ if (sock_.s_ == invalid_socket) {
isc_throw(IOError, "failed to open test socket");
}
@@ -280,8 +281,8 @@ protected:
ScopedSocket sock(socket(res->ai_family, res->ai_socktype,
res->ai_protocol));
- const int s = sock.s_;
- if (s < 0) {
+ const socket_type s = sock.s_;
+ if (s == invalid_socket) {
isc_throw(isc::Unexpected, "failed to open a test socket");
}
const int on = 1;
@@ -300,9 +301,9 @@ protected:
isc_throw(isc::Unexpected, "failed to bind a test socket");
}
if (protocol == IPPROTO_TCP) {
- dns_service_->addServerTCPFromFD(sock.release(), family);
+ dns_service_->addServerTCPFromSD(sock.release(), family);
} else {
- dns_service_->addServerUDPFromFD(sock.release(), family);
+ dns_service_->addServerUDPFromSD(sock.release(), family);
}
}
@@ -502,7 +503,7 @@ protected:
isc::cache::ResolverCache cache_;
scoped_ptr<ASIOCallBack> callback_;
int callback_protocol_;
- int callback_native_;
+ socket_type callback_native_;
string callback_address_;
vector<uint8_t> callback_data_;
ScopedSocket sock_;
@@ -511,7 +512,8 @@ protected:
RecursiveQueryTest::RecursiveQueryTest() :
dns_service_(NULL), callback_(NULL), callback_protocol_(0),
- callback_native_(-1), resolver_(new isc::util::unittests::TestResolver())
+ callback_native_(invalid_socket),
+ resolver_(new isc::util::unittests::TestResolver())
{
nsas_.reset(new isc::nsas::NameserverAddressStore(resolver_));
}
@@ -677,14 +679,14 @@ TEST_F(RecursiveQueryTest, forwarderSend) {
EXPECT_EQ(q.getClass(), q2->getClass());
}
-int
+socket_type
createTestSocket() {
ScopedAddrInfo sai(resolveAddress(AF_INET, IPPROTO_UDP, true));
struct addrinfo* res = sai.res_;
ScopedSocket sock(socket(res->ai_family, res->ai_socktype,
res->ai_protocol));
- if (sock.s_ < 0) {
+ if (sock.s_ == invalid_socket) {
isc_throw(IOError, "failed to open test socket");
}
if (bind(sock.s_, res->ai_addr, res->ai_addrlen) < 0) {
@@ -710,7 +712,7 @@ setSocketTimeout(int sock, size_t tv_sec, size_t tv_usec) {
// try to read from the socket max time
// *num is incremented for every succesfull read
// returns true if it can read max times, false otherwise
-bool tryRead(int sock, int recv_options, size_t max, int* num) {
+bool tryRead(socket_type sock, int recv_options, size_t max, int* num) {
size_t i = 0;
do {
char inbuff[512];
diff --git a/src/lib/server_common/portconfig.cc b/src/lib/server_common/portconfig.cc
index 530c919..31c402e 100644
--- a/src/lib/server_common/portconfig.cc
+++ b/src/lib/server_common/portconfig.cc
@@ -96,13 +96,13 @@ setAddresses(DNSServiceBase& service, const AddressList& addresses,
address.first, address.second,
SocketRequestor::SHARE_SAME));
current_sockets.push_back(tcp.second);
- service.addServerTCPFromFD(tcp.first, af);
+ service.addServerTCPFromSD(tcp.first, af);
const SocketRequestor::SocketID
udp(socketRequestor().requestSocket(SocketRequestor::UDP,
address.first, address.second,
SocketRequestor::SHARE_SAME));
current_sockets.push_back(udp.second);
- service.addServerUDPFromFD(udp.first, af, server_options);
+ service.addServerUDPFromSD(udp.first, af, server_options);
}
}
diff --git a/src/lib/server_common/socket_request.cc b/src/lib/server_common/socket_request.cc
index e471ad0..4f7565d 100644
--- a/src/lib/server_common/socket_request.cc
+++ b/src/lib/server_common/socket_request.cc
@@ -19,8 +19,8 @@
#include <config/ccsession.h>
#include <cc/session.h>
#include <cc/data.h>
-#include <util/io/fd.h>
-#include <util/io/fd_share.h>
+#include <util/io/socket.h>
+#include <util/io/socket_share.h>
#include <sys/un.h>
#include <sys/socket.h>
@@ -34,14 +34,14 @@ namespace server_common {
namespace {
SocketRequestor* requestor(NULL);
-// Before the boss process calls send_fd, it first sends this
+// Before the boss process calls send_socket, it first sends this
// string to indicate success, followed by the file descriptor
const std::string& CREATOR_SOCKET_OK() {
static const std::string str("1\n");
return (str);
}
-// Before the boss process calls send_fd, it sends this
+// Before the boss process calls send_socket, it sends this
// string to indicate failure. It will not send a file descriptor.
const std::string& CREATOR_SOCKET_UNAVAILABLE() {
static const std::string str("0\n");
@@ -163,20 +163,20 @@ readRequestSocketAnswer(isc::data::ConstElementPtr recv_msg,
//
// This should only be called if the socket had not been connected to
// already. To get the socket and reuse existing ones, use
-// getFdShareSocket()
+// getSdShareSocket()
//
// \param path The domain socket to connect to
// \exception SocketError if the socket cannot be connected to
// \return the socket file descriptor
-int
-createFdShareSocket(const std::string& path) {
+socket_type
+createSdShareSocket(const std::string& path) {
// TODO: Current master has socketsession code and better way
// of handling errors without potential leaks for this. It is
// not public there at this moment, but when this is merged
// we should make a ticket to move this functionality to the
// SocketSessionReceiver and use that.
- const int sock_pass_fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock_pass_fd == -1) {
+ const socket_type sock_pass_sd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock_pass_sd == invalid_socket) {
isc_throw(SocketRequestor::SocketError,
"Unable to open domain socket " << path <<
": " << strerror(errno));
@@ -184,7 +184,7 @@ createFdShareSocket(const std::string& path) {
struct sockaddr_un sock_pass_addr;
sock_pass_addr.sun_family = AF_UNIX;
if (path.size() >= sizeof(sock_pass_addr.sun_path)) {
- close(sock_pass_fd);
+ close(sock_pass_sd);
isc_throw(SocketRequestor::SocketError,
"Unable to open domain socket " << path <<
": path too long");
@@ -195,25 +195,25 @@ createFdShareSocket(const std::string& path) {
strcpy(sock_pass_addr.sun_path, path.c_str());
const socklen_t len = path.size() + offsetof(struct sockaddr_un, sun_path);
// Yes, C-style cast bad. See previous comment about SocketSessionReceiver.
- if (connect(sock_pass_fd, (const struct sockaddr*)&sock_pass_addr,
+ if (connect(sock_pass_sd, (const struct sockaddr*)&sock_pass_addr,
len) == -1) {
- close(sock_pass_fd);
+ close(sock_pass_sd);
isc_throw(SocketRequestor::SocketError,
"Unable to open domain socket " << path <<
": " << strerror(errno));
}
- return (sock_pass_fd);
+ return (sock_pass_sd);
}
-// Reads a socket fd over the given socket (using recv_fd()).
+// Reads a socket handle over the given socket (using recv_socket()).
//
// \exception SocketError if the socket cannot be read
-// \return the socket fd that has been read
-int
-getSocketFd(const std::string& token, int sock_pass_fd) {
+// \return the socket handle that has been read
+socket_type
+getSocketSd(const std::string& token, socket_type sock_pass_sd) {
// Tell the boss the socket token.
const std::string token_data = token + "\n";
- if (!isc::util::io::write_data(sock_pass_fd, token_data.c_str(),
+ if (!isc::util::io::write_data(sock_pass_sd, token_data.c_str(),
token_data.size())) {
isc_throw(SocketRequestor::SocketError, "Error writing socket token");
}
@@ -222,7 +222,7 @@ getSocketFd(const std::string& token, int sock_pass_fd) {
// from its cache succeeded
char status[3]; // We need a space for trailing \0, hence 3
memset(status, 0, 3);
- if (isc::util::io::read_data(sock_pass_fd, status, 2) < 2) {
+ if (isc::util::io::read_data(sock_pass_sd, status, 2) < 2) {
isc_throw(SocketRequestor::SocketError,
"Error reading status code while requesting socket");
}
@@ -232,34 +232,36 @@ getSocketFd(const std::string& token, int sock_pass_fd) {
"CREATOR_SOCKET_UNAVAILABLE returned");
} else if (CREATOR_SOCKET_OK() != status) {
isc_throw(SocketRequestor::SocketError,
- "Unknown status code returned before recv_fd '" << status <<
- "'");
+ "Unknown status code returned before recv_socket '" <<
+ status << "'");
}
- const int passed_sock_fd = isc::util::io::recv_fd(sock_pass_fd);
+ socket_type passed_sock_sd = invalid_socket;
+ const int result = isc::util::io::recv_socket(sock_pass_sd,
+ &passed_sock_sd);
- // check for error values of passed_sock_fd (see fd_share.h)
- if (passed_sock_fd < 0) {
- switch (passed_sock_fd) {
- case isc::util::io::FD_SYSTEM_ERROR:
+ // check for error values of result (see socket_share.h)
+ if (passed_sock_sd == invalid_socket) {
+ switch (result) {
+ case isc::util::io::SOCKET_SYSTEM_ERROR:
isc_throw(SocketRequestor::SocketError,
- "FD_SYSTEM_ERROR while requesting socket");
+ "SOCKET_SYSTEM_ERROR while requesting socket");
break;
- case isc::util::io::FD_OTHER_ERROR:
+ case isc::util::io::SOCKET_OTHER_ERROR:
isc_throw(SocketRequestor::SocketError,
- "FD_OTHER_ERROR while requesting socket");
+ "SOCKET_OTHER_ERROR while requesting socket");
break;
default:
isc_throw(SocketRequestor::SocketError,
"Unknown error while requesting socket");
}
}
- return (passed_sock_fd);
+ return (passed_sock_sd);
}
// This implementation class for SocketRequestor uses
// a CC session for communication with the boss process,
-// and fd_share to read out the socket(s).
+// and socket_share to read out the socket(s).
// Since we only use a reference to the session, it must never
// be closed during the lifetime of this class
class SocketRequestorCCSession : public SocketRequestor {
@@ -270,7 +272,7 @@ public:
app_name_(app_name)
{
// We need to filter SIGPIPE to prevent it from happening in
- // getSocketFd() while writing to the UNIX domain socket after the
+ // getSocketSd() while writing to the UNIX domain socket after the
// remote end closed it. See lib/util/io/socketsession for more
// background details.
// Note: we should eventually unify this level of details into a single
@@ -285,7 +287,7 @@ public:
}
~SocketRequestorCCSession() {
- closeFdShareSockets();
+ closeSdShareSockets();
LOG_DEBUG(logger, DBGLVL_TRACE_BASIC, SOCKETREQUESTOR_DESTROYED);
}
@@ -316,14 +318,14 @@ public:
readRequestSocketAnswer(recv_msg, token, path);
// get the domain socket over which we will receive the
// real socket
- const int sock_pass_fd = getFdShareSocket(path);
+ const socket_type sock_pass_sd = getSdShareSocket(path);
// and finally get the socket itself
- const int passed_sock_fd = getSocketFd(token, sock_pass_fd);
+ const socket_type passed_sock_sd = getSocketSd(token, sock_pass_sd);
LOG_DEBUG(logger, DBGLVL_TRACE_DETAIL, SOCKETREQUESTOR_GETSOCKET).
arg(protocolString(protocol)).arg(address).arg(port).
- arg(passed_sock_fd).arg(token).arg(path);
- return (SocketID(passed_sock_fd, token));
+ arg(passed_sock_sd).arg(token).arg(path);
+ return (SocketID(passed_sock_sd, token));
}
virtual void releaseSocket(const std::string& token) {
@@ -356,26 +358,27 @@ public:
private:
// Returns the domain socket file descriptor
// If we had not opened it yet, opens it now
- int
- getFdShareSocket(const std::string& path) {
- if (fd_share_sockets_.find(path) == fd_share_sockets_.end()) {
- const int new_fd = createFdShareSocket(path);
- // Technically, the (creation and) assignment of the new map entry
- // could thrown an exception and lead to FD leak. This should be
- // cleaned up later (see comment about SocketSessionReceiver above)
- fd_share_sockets_[path] = new_fd;
- return (new_fd);
+ socket_type
+ getSdShareSocket(const std::string& path) {
+ if (share_sockets_.find(path) == share_sockets_.end()) {
+ const socket_type new_sd = createSdShareSocket(path);
+ // Technically, the (creation and) assignment of the new
+ // map entry could thrown an exception and lead to socket
+ // leak. This should be cleaned up later (see comment
+ // about SocketSessionReceiver above)
+ share_sockets_[path] = new_sd;
+ return (new_sd);
} else {
- return (fd_share_sockets_[path]);
+ return (share_sockets_[path]);
}
}
- // Closes the sockets that has been used for fd_share
+ // Closes the sockets that has been used for socket_share
void
- closeFdShareSockets() {
+ closeSdShareSockets() {
for (std::map<std::string, int>::const_iterator it =
- fd_share_sockets_.begin();
- it != fd_share_sockets_.end();
+ share_sockets_.begin();
+ it != share_sockets_.end();
++it) {
close((*it).second);
}
@@ -383,7 +386,7 @@ private:
cc::AbstractSession& session_;
const std::string app_name_;
- std::map<std::string, int> fd_share_sockets_;
+ std::map<std::string, socket_type> share_sockets_;
};
}
diff --git a/src/lib/server_common/socket_request.h b/src/lib/server_common/socket_request.h
index aac95d1..58e117d 100644
--- a/src/lib/server_common/socket_request.h
+++ b/src/lib/server_common/socket_request.h
@@ -18,6 +18,7 @@
#include <exceptions/exceptions.h>
#include <boost/noncopyable.hpp>
+#include <asio.hpp>
#include <utility>
#include <string>
#include <stdint.h>
@@ -62,11 +63,11 @@ public:
/// \brief A representation of received socket
///
- /// The pair holds two parts. The OS-level file descriptor acting as the
+ /// The pair holds two parts. The OS-level descriptor acting as the
/// socket (you might want to use it directly with functions like recv,
/// or fill it into an asio socket). The other part is the token
/// representing the socket, which allows it to be given up again.
- typedef std::pair<int, std::string> SocketID;
+ typedef std::pair<asio::detail::socket_type, std::string> SocketID;
/// \brief The protocol of requested socket
///
diff --git a/src/lib/server_common/tests/socket_requestor_test.cc b/src/lib/server_common/tests/socket_requestor_test.cc
index 9878c63..daaec92 100644
--- a/src/lib/server_common/tests/socket_requestor_test.cc
+++ b/src/lib/server_common/tests/socket_requestor_test.cc
@@ -33,8 +33,8 @@
#include <boost/foreach.hpp>
#include <boost/scoped_ptr.hpp>
-#include <util/io/fd.h>
-#include <util/io/fd_share.h>
+#include <util/io/socket.h>
+#include <util/io/socket_share.h>
using namespace isc::data;
using namespace isc::config;
@@ -60,7 +60,7 @@ TEST(SocketRequestorAccess, initialized) {
virtual SocketID requestSocket(Protocol, const std::string&, uint16_t,
ShareMode, const std::string&)
{
- return (SocketID(0, "")); // Just to silence warnings
+ return (SocketID(invalid_socket, "")); // Just to silence warnings
}
};
DummyRequestor requestor;
@@ -325,7 +325,7 @@ TEST_F(SocketRequestorTest, testBadSocketReleaseAnswers) {
// send expected data.
// It returns true when the timeout is set successfully; otherwise false.
bool
-setRecvTimo(int s) {
+setRecvTimo(socket_type s) {
const struct timeval timeo = { 10, 0 }; // 10sec, arbitrary choice
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)) == 0) {
return (true);
@@ -344,7 +344,7 @@ setRecvTimo(int s) {
// connection, and then close the socket
class TestSocket {
public:
- TestSocket() : fd_(-1) {
+ TestSocket() : sd_(invalid_socket) {
path_ = strdup("test_socket.XXXXXX");
// Misuse mkstemp to generate a file name.
const int f = mkstemp(path_);
@@ -366,9 +366,9 @@ public:
free(path_);
path_ = NULL;
}
- if (fd_ != -1) {
- close(fd_);
- fd_ = -1;
+ if (sd_ != invalid_socket) {
+ close(sd_);
+ sd_ = invalid_socket;
}
}
@@ -383,15 +383,15 @@ public:
// performing tests that could result in a dead lock.
bool run(const std::vector<std::pair<std::string, int> >& data) {
create();
- const bool timo_ok = setRecvTimo(fd_);
+ const bool timo_ok = setRecvTimo(sd_);
const int child_pid = fork();
if (child_pid == 0) {
serve(data);
exit(0);
} else {
- // parent does not need fd anymore
- close(fd_);
- fd_ = -1;
+ // parent does not need sd_ anymore
+ close(sd_);
+ sd_ = invalid_socket;
}
return (timo_ok);
}
@@ -399,8 +399,8 @@ private:
// Actually create the socket and listen on it
void
create() {
- fd_ = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd_ == -1) {
+ sd_ = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sd_ == invalid_socket) {
isc_throw(Unexpected, "Unable to create socket");
}
struct sockaddr_un socket_address;
@@ -420,13 +420,13 @@ private:
// a domain socket connection. This contains a minor race condition
// but for the purposes of this test it should be small enough
unlink(path_);
- if (bind(fd_, (const struct sockaddr*)&socket_address, len) == -1) {
+ if (bind(sd_, (const struct sockaddr*)&socket_address, len) == -1) {
isc_throw(Unexpected,
"unable to bind to test domain socket " << path_ <<
": " << strerror(errno));
}
- if (listen(fd_, 1) == -1) {
+ if (listen(sd_, 1) == -1) {
isc_throw(Unexpected,
"unable to listen on test domain socket " << path_ <<
": " << strerror(errno));
@@ -436,7 +436,7 @@ private:
// Accept one connection, then for each value of the vector,
// read the socket token from the connection and match the string
// part of the vector element, and send the integer part of the element
- // using send_fd() (prepended by a status code 'ok'). For simplicity
+ // using send_socket() (prepended by a status code 'ok'). For simplicity
// we assume the tokens are 4 bytes long; if the test case uses a
// different size of token the test will fail.
//
@@ -445,17 +445,17 @@ private:
// CREATOR_SOCKET_UNAVAILABLE)
// when the value is -2, it will send a byte signaling CREATOR_SOCKET_OK
// first, and then one byte from some string (i.e. bad data, not using
- // send_fd())
+ // send_socket())
//
- // NOTE: client_fd could leak on exception. This should be cleaned up.
+ // NOTE: client_sd could leak on exception. This should be cleaned up.
// See the note about SocketSessionReceiver in socket_request.cc.
void
serve(const std::vector<std::pair<std::string, int> >& data) {
- const int client_fd = accept(fd_, NULL, NULL);
- if (client_fd == -1) {
+ const socket_type client_sd = accept(sd_, NULL, NULL);
+ if (client_sd == invalid_socket) {
isc_throw(Unexpected, "Error in accept(): " << strerror(errno));
}
- if (!setRecvTimo(client_fd)) {
+ if (!setRecvTimo(client_sd)) {
// In the loop below we do blocking read. To avoid deadlock
// when the parent is buggy we'll skip it unless we can
// set a read timeout on the socket.
@@ -465,7 +465,7 @@ private:
BOOST_FOREACH(DataPair cur_data, data) {
char buf[5];
memset(buf, 0, 5);
- if (isc::util::io::read_data(client_fd, buf, 4) != 4) {
+ if (isc::util::io::read_data(client_sd, buf, 4) != 4) {
isc_throw(Unexpected, "unable to receive socket token");
}
if (cur_data.first != buf) {
@@ -476,34 +476,34 @@ private:
bool result;
if (cur_data.second == -1) {
// send 'CREATOR_SOCKET_UNAVAILABLE'
- result = isc::util::io::write_data(client_fd, "0\n", 2);
+ result = isc::util::io::write_data(client_sd, "0\n", 2);
} else if (cur_data.second == -2) {
// send 'CREATOR_SOCKET_OK' first
- result = isc::util::io::write_data(client_fd, "1\n", 2);
+ result = isc::util::io::write_data(client_sd, "1\n", 2);
if (result) {
- if (send(client_fd, "a", 1, 0) != 1) {
+ if (send(client_sd, "a", 1, 0) != 1) {
result = false;
}
}
} else {
// send 'CREATOR_SOCKET_OK' first
- result = isc::util::io::write_data(client_fd, "1\n", 2);
+ result = isc::util::io::write_data(client_sd, "1\n", 2);
if (result) {
- if (isc::util::io::send_fd(client_fd,
- cur_data.second) != 0) {
+ if (isc::util::io::send_socket(client_sd,
+ cur_data.second) != 0) {
result = false;
}
}
}
if (!result) {
- isc_throw(Exception, "Error in send_fd(): " <<
+ isc_throw(Exception, "Error in send_socket(): " <<
strerror(errno));
}
}
- close(client_fd);
+ close(client_sd);
}
- int fd_;
+ socket_type sd_;
char* path_;
};
diff --git a/src/lib/testutils/mockups.h b/src/lib/testutils/mockups.h
index b5def4b..87cde2f 100644
--- a/src/lib/testutils/mockups.h
+++ b/src/lib/testutils/mockups.h
@@ -29,6 +29,8 @@
#include <utility>
#include <vector>
+using asio::detail::socket_type;
+
namespace isc {
namespace testutils {
@@ -108,19 +110,20 @@ private:
// to addServerXXX methods so the test code subsequently checks the parameters.
class MockDNSService : public isc::asiodns::DNSServiceBase {
public:
- // A helper tuple of parameters passed to addServerUDPFromFD().
- struct UDPFdParams {
- int fd;
+ // A helper tuple of parameters passed to addServerUDPFromSD().
+ struct UDPSocketParams {
+ socket_type sd;
int af;
ServerFlag options;
};
- virtual void addServerTCPFromFD(int fd, int af) {
- tcp_fd_params_.push_back(std::pair<int, int>(fd, af));
+ virtual void addServerTCPFromSD(socket_type sd, int af) {
+ tcp_params_.push_back(std::pair<socket_type, int>(sd, af));
}
- virtual void addServerUDPFromFD(int fd, int af, ServerFlag options) {
- UDPFdParams params = { fd, af, options };
- udp_fd_params_.push_back(params);
+ virtual void addServerUDPFromSD(socket_type sd, int af,
+ ServerFlag options) {
+ UDPSocketParams params = { sd, af, options };
+ udp_params_.push_back(params);
}
virtual void clearServers() {}
@@ -131,16 +134,17 @@ public:
// These two allow the tests to check how the servers have been created
// through this object.
- const std::vector<std::pair<int, int> >& getTCPFdParams() const {
- return (tcp_fd_params_);
+ const std::vector<std::pair<socket_type, int> >&
+ getTCPSocketParams() const {
+ return (tcp_params_);
}
- const std::vector<UDPFdParams>& getUDPFdParams() const {
- return (udp_fd_params_);
+ const std::vector<UDPSocketParams>& getUDPSocketParams() const {
+ return (udp_params_);
}
private:
- std::vector<std::pair<int, int> > tcp_fd_params_;
- std::vector<UDPFdParams> udp_fd_params_;
+ std::vector<std::pair<socket_type, int> > tcp_params_;
+ std::vector<UDPSocketParams> udp_params_;
};
// A nonoperative DNSServer object to be used in calls to processMessage().
@@ -179,7 +183,7 @@ public:
is_connected_ = false;
}
- virtual int sendXfroutRequestInfo(int, const void*, uint16_t) {
+ virtual int sendXfroutRequestInfo(socket_type, const void*, uint16_t) {
if (!send_ok_) {
isc_throw(isc::xfr::XfroutError,
"xfrout connection send is disabled for test");
diff --git a/src/lib/util/io/Makefile.am b/src/lib/util/io/Makefile.am
index 1249178..8216c6f 100644
--- a/src/lib/util/io/Makefile.am
+++ b/src/lib/util/io/Makefile.am
@@ -4,7 +4,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
lib_LTLIBRARIES = libb10-util-io.la
-libb10_util_io_la_SOURCES = fd.h fd.cc fd_share.h fd_share.cc
+libb10_util_io_la_SOURCES = socket.h socket.cc
+libb10_util_io_la_SOURCES += socket_share.h socket_share.cc
libb10_util_io_la_SOURCES += socketsession.h socketsession.cc sockaddr_util.h
libb10_util_io_la_SOURCES += pktinfo_utilities.h
libb10_util_io_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
@@ -15,7 +16,7 @@ pyexec_LTLIBRARIES = libutil_io_python.la
# Python prefers .so, while some OSes (specifically MacOS) use a different
# suffix for dynamic objects. -module is necessary to work this around.
libutil_io_python_la_LDFLAGS = -module -avoid-version
-libutil_io_python_la_SOURCES = fdshare_python.cc
+libutil_io_python_la_SOURCES = socketshare_python.cc
libutil_io_python_la_LIBADD = libb10-util-io.la
libutil_io_python_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
# Note: PYTHON_CXXFLAGS may have some -Wno... workaround, which must be
diff --git a/src/lib/util/io/fd.cc b/src/lib/util/io/fd.cc
deleted file mode 100644
index 49aac39..0000000
--- a/src/lib/util/io/fd.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include "fd.h"
-
-#include <unistd.h>
-#include <cerrno>
-
-namespace isc {
-namespace util {
-namespace io {
-
-bool
-write_data(const int fd, const void *buffer_v, const size_t length) {
- const unsigned char* buffer(static_cast<const unsigned char*>(buffer_v));
- size_t remaining = length; // Amount remaining to be written
-
- // Just keep writing until all is written
- while (remaining > 0) {
- const int written = write(fd, buffer, remaining);
- if (written == -1) {
- if (errno == EINTR) { // Just keep going
- continue;
- } else {
- return (false);
- }
-
- } else if (written > 0) {
- // Wrote "written" bytes from the buffer
- remaining -= written;
- buffer += written;
-
- } else {
- // Wrote zero bytes from the buffer. We should not get here as any
- // error that causes zero bytes to be written should have returned
- // -1. However, write(2) can return 0, and in this case we
- // interpret it as an error.
- return (false);
- }
- }
- return (true);
-}
-
-ssize_t
-read_data(const int fd, void *buffer_v, const size_t length) {
- unsigned char* buffer(static_cast<unsigned char*>(buffer_v));
- size_t remaining = length; // Amount remaining to be read
-
- while (remaining > 0) {
- const int amount = read(fd, buffer, remaining);
- if (amount == -1) {
- if (errno == EINTR) { // Continue on interrupted call
- continue;
- } else {
- return (-1);
- }
- } else if (amount > 0) {
- // Read "amount" bytes into the buffer
- remaining -= amount;
- buffer += amount;
- } else {
- // EOF - end the read
- break;
- }
- }
-
- // Return total number of bytes read
- return (static_cast<ssize_t>(length - remaining));
-}
-
-}
-}
-}
diff --git a/src/lib/util/io/fd.h b/src/lib/util/io/fd.h
deleted file mode 100644
index bdd2d41..0000000
--- a/src/lib/util/io/fd.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef __UTIL_IO_FD_H
-#define __UTIL_IO_FD_H 1
-
-#include <unistd.h>
-
-/**
- * @file fd.h
- * @short Wrappers around common unix fd manipulation functions.
- */
-
-namespace isc {
-namespace util {
-namespace io {
-
-/*
- * \short write() that writes everything.
- * Wrapper around write(). The difference is, it never writes less data
- * and looks successfull (eg. it blocks until all data are written).
- * Retries on signals.
- *
- * \return True if sucessfull, false otherwise. The errno variable is left
- * intact.
- * \param fd Where to write.
- * \param data The buffer to write.
- * \param length How much data is there to write.
- */
-bool
-write_data(const int fd, const void *data, const size_t length);
-
-/*
- * \short read() that reads everything.
- * Wrapper around read(). It does not do short reads, if it returns less,
- * it means there was EOF. It retries on signals.
- *
- * \return Number of bytes read or -1 on error.
- * \param fd Where to read data from.
- * \param data Where to put the data.
- * \param length How many of them.
- */
-ssize_t
-read_data(const int fd, void *buffer, const size_t length);
-
-}
-}
-}
-
-#endif // __UTIL_IO_FD_H
diff --git a/src/lib/util/io/fd_share.cc b/src/lib/util/io/fd_share.cc
deleted file mode 100644
index 7adbbbe..0000000
--- a/src/lib/util/io/fd_share.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <cstring>
-#include <cstdlib>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <errno.h>
-#include <stdlib.h> // for malloc and free
-#include <unistd.h>
-#include "fd_share.h"
-
-namespace isc {
-namespace util {
-namespace io {
-
-namespace {
-// Not all OSes support advanced CMSG macros: CMSG_LEN and CMSG_SPACE.
-// In order to ensure as much portability as possible, we provide wrapper
-// functions of these macros.
-// Note that cmsg_space() could run slow on OSes that do not have
-// CMSG_SPACE.
-inline socklen_t
-cmsg_len(const socklen_t len) {
-#ifdef CMSG_LEN
- return (CMSG_LEN(len));
-#else
- // Cast NULL so that any pointer arithmetic performed by CMSG_DATA
- // is correct.
- const uintptr_t hdrlen = (uintptr_t)CMSG_DATA(((struct cmsghdr*)NULL));
- return (hdrlen + len);
-#endif
-}
-
-inline socklen_t
-cmsg_space(const socklen_t len) {
-#ifdef CMSG_SPACE
- return (CMSG_SPACE(len));
-#else
- struct msghdr msg;
- struct cmsghdr* cmsgp;
- // XXX: The buffer length is an ad hoc value, but should be enough
- // in a practical sense.
- char dummybuf[sizeof(struct cmsghdr) + 1024];
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_control = dummybuf;
- msg.msg_controllen = sizeof(dummybuf);
-
- cmsgp = (struct cmsghdr*)dummybuf;
- cmsgp->cmsg_len = cmsg_len(len);
-
- cmsgp = CMSG_NXTHDR(&msg, cmsgp);
- if (cmsgp != NULL) {
- return ((char*)cmsgp - (char*)msg.msg_control);
- } else {
- return (0);
- }
-#endif // CMSG_SPACE
-}
-}
-
-int
-recv_fd(const int sock) {
- struct msghdr msghdr;
- struct iovec iov_dummy;
- unsigned char dummy_data;
-
- iov_dummy.iov_base = &dummy_data;
- iov_dummy.iov_len = sizeof(dummy_data);
- msghdr.msg_name = NULL;
- msghdr.msg_namelen = 0;
- msghdr.msg_iov = &iov_dummy;
- msghdr.msg_iovlen = 1;
- msghdr.msg_flags = 0;
- msghdr.msg_controllen = cmsg_space(sizeof(int));
- msghdr.msg_control = malloc(msghdr.msg_controllen);
- if (msghdr.msg_control == NULL) {
- return (FD_SYSTEM_ERROR);
- }
-
- const int cc = recvmsg(sock, &msghdr, 0);
- if (cc <= 0) {
- free(msghdr.msg_control);
- if (cc == 0) {
- errno = ECONNRESET;
- }
- return (FD_SYSTEM_ERROR);
- }
- const struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msghdr);
- int fd = FD_OTHER_ERROR;
- if (cmsg != NULL && cmsg->cmsg_len == cmsg_len(sizeof(int)) &&
- cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
- std::memcpy(&fd, CMSG_DATA(cmsg), sizeof(int));
- }
- free(msghdr.msg_control);
- // It is strange, but the call can return the same file descriptor as
- // one returned previously, even if that one is not closed yet. So,
- // we just re-number every one we get, so they are unique.
- int new_fd(dup(fd));
- int close_error(close(fd));
- if (close_error == -1 || new_fd == -1) {
- // We need to return an error, because something failed. But in case
- // it was the previous close, we at least try to close the duped FD.
- if (new_fd != -1) {
- close(new_fd); // If this fails, nothing but returning error can't
- // be done and we are doing that anyway.
- }
- return (FD_SYSTEM_ERROR);
- }
- return (new_fd);
-}
-
-int
-send_fd(const int sock, const int fd) {
- struct msghdr msghdr;
- struct iovec iov_dummy;
- unsigned char dummy_data = 0;
-
- iov_dummy.iov_base = &dummy_data;
- iov_dummy.iov_len = sizeof(dummy_data);
- msghdr.msg_name = NULL;
- msghdr.msg_namelen = 0;
- msghdr.msg_iov = &iov_dummy;
- msghdr.msg_iovlen = 1;
- msghdr.msg_flags = 0;
- msghdr.msg_controllen = cmsg_space(sizeof(int));
- msghdr.msg_control = malloc(msghdr.msg_controllen);
- if (msghdr.msg_control == NULL) {
- return (FD_OTHER_ERROR);
- }
-
- struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msghdr);
- cmsg->cmsg_len = cmsg_len(sizeof(int));
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- std::memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
-
- const int ret = sendmsg(sock, &msghdr, 0);
- free(msghdr.msg_control);
- return (ret >= 0 ? 0 : FD_SYSTEM_ERROR);
-}
-
-} // End for namespace io
-} // End for namespace util
-} // End for namespace isc
diff --git a/src/lib/util/io/fd_share.h b/src/lib/util/io/fd_share.h
deleted file mode 100644
index 2b30abd..0000000
--- a/src/lib/util/io/fd_share.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef FD_SHARE_H_
-#define FD_SHARE_H_
-
-/**
- * \file fd_share.h
- * \short Support to transfer file descriptors between processes.
- * \todo This interface is very C-ish. Should we have some kind of exceptions?
- */
-
-namespace isc {
-namespace util {
-namespace io {
-
-const int FD_SYSTEM_ERROR = -2;
-const int FD_OTHER_ERROR = -1;
-
-/**
- * \short Receives a file descriptor.
- * This receives a file descriptor sent over an unix domain socket. This
- * is the counterpart of send_fd().
- *
- * \return FD_SYSTEM_ERROR when there's an error at the operating system
- * level (such as a system call failure). The global 'errno' variable
- * indicates the specific error. FD_OTHER_ERROR when there's a different
- * error.
- *
- * \param sock The unix domain socket to read from. Tested and it does
- * not work with a pipe.
- */
-int recv_fd(const int sock);
-
-/**
- * \short Sends a file descriptor.
- * This sends a file descriptor over an unix domain socket. This is the
- * counterpart of recv_fd().
- *
- * \return FD_SYSTEM_ERROR when there's an error at the operating system
- * level (such as a system call failure). The global 'errno' variable
- * indicates the specific error.
- * \param sock The unix domain socket to send to. Tested and it does not
- * work with a pipe.
- * \param fd The file descriptor to send. It should work with any valid
- * file descriptor.
- */
-int send_fd(const int sock, const int fd);
-
-} // End for namespace io
-} // End for namespace util
-} // End for namespace isc
-
-#endif
-
-// Local Variables:
-// mode: c++
-// End:
diff --git a/src/lib/util/io/fdshare_python.cc b/src/lib/util/io/fdshare_python.cc
deleted file mode 100644
index 249f8b0..0000000
--- a/src/lib/util/io/fdshare_python.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-#include <structmember.h>
-
-#include <config.h>
-
-#include "fd_share.h"
-
-
-static PyObject*
-fdshare_recv_fd(PyObject*, PyObject* args) {
- int sock, fd;
- if (!PyArg_ParseTuple(args, "i", &sock)) {
- return (NULL);
- }
- fd = isc::util::io::recv_fd(sock);
- return (Py_BuildValue("i", fd));
-}
-
-static PyObject*
-fdshare_send_fd(PyObject*, PyObject* args) {
- int sock, fd, result;
- if (!PyArg_ParseTuple(args, "ii", &sock, &fd)) {
- return (NULL);
- }
- result = isc::util::io::send_fd(sock, fd);
- return (Py_BuildValue("i", result));
-}
-
-static PyMethodDef fdshare_Methods[] = {
- {"send_fd", fdshare_send_fd, METH_VARARGS, ""},
- {"recv_fd", fdshare_recv_fd, METH_VARARGS, ""},
- {NULL, NULL, 0, NULL} /* Sentinel */
-};
-
-
-static PyModuleDef bind10_fdshare_python = {
- { PyObject_HEAD_INIT(NULL) NULL, 0, NULL},
- "bind10_fdshare",
- "Python bindings for fdshare",
- -1,
- fdshare_Methods,
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-PyMODINIT_FUNC
-PyInit_libutil_io_python(void) {
- PyObject *mod = PyModule_Create(&bind10_fdshare_python);
- if (mod == NULL) {
- return (NULL);
- }
-
- PyObject* FD_SYSTEM_ERROR = Py_BuildValue("i",
- isc::util::io::FD_SYSTEM_ERROR);
- if (FD_SYSTEM_ERROR == NULL) {
- Py_XDECREF(mod);
- return (NULL);
- }
- int ret = PyModule_AddObject(mod, "FD_SYSTEM_ERROR", FD_SYSTEM_ERROR);
- if (ret == -1) {
- Py_XDECREF(FD_SYSTEM_ERROR);
- Py_XDECREF(mod);
- return (NULL);
- }
-
- PyObject* FD_OTHER_ERROR = Py_BuildValue("i",
- isc::util::io::FD_OTHER_ERROR);
- if (FD_OTHER_ERROR == NULL) {
- Py_XDECREF(mod);
- return (NULL);
- }
- ret = PyModule_AddObject(mod, "FD_OTHER_ERROR", FD_OTHER_ERROR);
- if (-1 == ret) {
- Py_XDECREF(FD_OTHER_ERROR);
- Py_XDECREF(mod);
- return (NULL);
- }
-
- return (mod);
-}
-
diff --git a/src/lib/util/io/socket.cc b/src/lib/util/io/socket.cc
new file mode 100644
index 0000000..77d5141
--- /dev/null
+++ b/src/lib/util/io/socket.cc
@@ -0,0 +1,84 @@
+// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include "socket.h"
+
+#include <unistd.h>
+#include <cerrno>
+
+namespace isc {
+namespace util {
+namespace io {
+
+bool
+write_data(const socket_type s, const void *buffer_v, const size_t length) {
+ const unsigned char* buffer(static_cast<const unsigned char*>(buffer_v));
+ size_t remaining = length; // Amount remaining to be written
+
+ // Just keep writing until all is written
+ while (remaining > 0) {
+ const int written = write(s, buffer, remaining);
+ if (written == -1) {
+ if (errno == EINTR) { // Just keep going
+ continue;
+ } else {
+ return (false);
+ }
+
+ } else if (written > 0) {
+ // Wrote "written" bytes from the buffer
+ remaining -= written;
+ buffer += written;
+
+ } else {
+ // Wrote zero bytes from the buffer. We should not get here as any
+ // error that causes zero bytes to be written should have returned
+ // -1. However, write(2) can return 0, and in this case we
+ // interpret it as an error.
+ return (false);
+ }
+ }
+ return (true);
+}
+
+ssize_t
+read_data(const socket_type s, void *buffer_v, const size_t length) {
+ unsigned char* buffer(static_cast<unsigned char*>(buffer_v));
+ size_t remaining = length; // Amount remaining to be read
+
+ while (remaining > 0) {
+ const int amount = read(s, buffer, remaining);
+ if (amount == -1) {
+ if (errno == EINTR) { // Continue on interrupted call
+ continue;
+ } else {
+ return (-1);
+ }
+ } else if (amount > 0) {
+ // Read "amount" bytes into the buffer
+ remaining -= amount;
+ buffer += amount;
+ } else {
+ // EOF - end the read
+ break;
+ }
+ }
+
+ // Return total number of bytes read
+ return (static_cast<ssize_t>(length - remaining));
+}
+
+}
+}
+}
diff --git a/src/lib/util/io/socket.h b/src/lib/util/io/socket.h
new file mode 100644
index 0000000..eec02ba
--- /dev/null
+++ b/src/lib/util/io/socket.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __UTIL_IO_SOCKET_H
+#define __UTIL_IO_SOCKET_H 1
+
+#include <asio.hpp>
+
+#include <unistd.h>
+
+/**
+ * @file socket.h
+ * @short Wrappers around common socket handle manipulation functions.
+ */
+
+using namespace asio::detail;
+
+namespace isc {
+namespace util {
+namespace io {
+
+/*
+ * \short write() that writes everything.
+ * Wrapper around write(). The difference is, it never writes less data
+ * and looks successfull (eg. it blocks until all data are written).
+ * Retries on signals.
+ *
+ * \return True if sucessfull, false otherwise. The errno variable is left
+ * intact.
+ * \param s Where to write.
+ * \param data The buffer to write.
+ * \param length How much data is there to write.
+ */
+bool
+write_data(const socket_type s, const void *data, const size_t length);
+
+/*
+ * \short read() that reads everything.
+ * Wrapper around read(). It does not do short reads, if it returns less,
+ * it means there was EOF. It retries on signals.
+ *
+ * \return Number of bytes read or -1 on error.
+ * \param s Where to read data from.
+ * \param data Where to put the data.
+ * \param length How many of them.
+ */
+ssize_t
+read_data(const socket_type s, void *buffer, const size_t length);
+
+}
+}
+}
+
+#endif // __UTIL_IO_SOCKET_H
diff --git a/src/lib/util/io/socket_share.cc b/src/lib/util/io/socket_share.cc
new file mode 100644
index 0000000..fccea6e
--- /dev/null
+++ b/src/lib/util/io/socket_share.cc
@@ -0,0 +1,161 @@
+// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <cstring>
+#include <cstdlib>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <stdlib.h> // for malloc and free
+#include <unistd.h>
+#include "socket_share.h"
+
+namespace isc {
+namespace util {
+namespace io {
+
+namespace {
+// Not all OSes support advanced CMSG macros: CMSG_LEN and CMSG_SPACE.
+// In order to ensure as much portability as possible, we provide wrapper
+// functions of these macros.
+// Note that cmsg_space() could run slow on OSes that do not have
+// CMSG_SPACE.
+inline socklen_t
+cmsg_len(const socklen_t len) {
+#ifdef CMSG_LEN
+ return (CMSG_LEN(len));
+#else
+ // Cast NULL so that any pointer arithmetic performed by CMSG_DATA
+ // is correct.
+ const uintptr_t hdrlen = (uintptr_t)CMSG_DATA(((struct cmsghdr*)NULL));
+ return (hdrlen + len);
+#endif
+}
+
+inline socklen_t
+cmsg_space(const socklen_t len) {
+#ifdef CMSG_SPACE
+ return (CMSG_SPACE(len));
+#else
+ struct msghdr msg;
+ struct cmsghdr* cmsgp;
+ // XXX: The buffer length is an ad hoc value, but should be enough
+ // in a practical sense.
+ char dummybuf[sizeof(struct cmsghdr) + 1024];
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_control = dummybuf;
+ msg.msg_controllen = sizeof(dummybuf);
+
+ cmsgp = (struct cmsghdr*)dummybuf;
+ cmsgp->cmsg_len = cmsg_len(len);
+
+ cmsgp = CMSG_NXTHDR(&msg, cmsgp);
+ if (cmsgp != NULL) {
+ return ((char*)cmsgp - (char*)msg.msg_control);
+ } else {
+ return (0);
+ }
+#endif // CMSG_SPACE
+}
+}
+
+int
+recv_socket(const socket_type sock, socket_type *val) {
+ struct msghdr msghdr;
+ struct iovec iov_dummy;
+ unsigned char dummy_data;
+
+ *val = invalid_socket;
+ iov_dummy.iov_base = &dummy_data;
+ iov_dummy.iov_len = sizeof(dummy_data);
+ msghdr.msg_name = NULL;
+ msghdr.msg_namelen = 0;
+ msghdr.msg_iov = &iov_dummy;
+ msghdr.msg_iovlen = 1;
+ msghdr.msg_flags = 0;
+ msghdr.msg_controllen = cmsg_space(sizeof(socket_type));
+ msghdr.msg_control = malloc(msghdr.msg_controllen);
+ if (msghdr.msg_control == NULL) {
+ return (SOCKET_SYSTEM_ERROR);
+ }
+
+ const int cc = recvmsg(sock, &msghdr, 0);
+ if (cc <= 0) {
+ free(msghdr.msg_control);
+ if (cc == 0) {
+ errno = ECONNRESET;
+ }
+ return (SOCKET_SYSTEM_ERROR);
+ }
+ const struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msghdr);
+ socket_type s = invalid_socket;
+ if (cmsg != NULL && cmsg->cmsg_len == cmsg_len(sizeof(socket_type)) &&
+ cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ std::memcpy(&s, CMSG_DATA(cmsg), sizeof(socket_type));
+ }
+ free(msghdr.msg_control);
+ // It is strange, but the call can return the same file descriptor as
+ // one returned previously, even if that one is not closed yet. So,
+ // we just re-number every one we get, so they are unique.
+ socket_type new_sd(dup(s));
+ int close_error(close(s));
+ if (close_error == socket_error_retval || new_sd == invalid_socket) {
+ // We need to return an error, because something failed. But in case
+ // it was the previous close, we at least try to close the duped SD.
+ if (new_sd != invalid_socket) {
+ close(new_sd); // If this fails, nothing but returning error can't
+ // be done and we are doing that anyway.
+ }
+ return (SOCKET_SYSTEM_ERROR);
+ }
+ *val = new_sd;
+ return (0);
+}
+
+int
+send_socket(const socket_type sock, const socket_type val) {
+ struct msghdr msghdr;
+ struct iovec iov_dummy;
+ unsigned char dummy_data = 0;
+
+ iov_dummy.iov_base = &dummy_data;
+ iov_dummy.iov_len = sizeof(dummy_data);
+ msghdr.msg_name = NULL;
+ msghdr.msg_namelen = 0;
+ msghdr.msg_iov = &iov_dummy;
+ msghdr.msg_iovlen = 1;
+ msghdr.msg_flags = 0;
+ msghdr.msg_controllen = cmsg_space(sizeof(socket_type));
+ msghdr.msg_control = malloc(msghdr.msg_controllen);
+ if (msghdr.msg_control == NULL) {
+ return (SOCKET_OTHER_ERROR);
+ }
+
+ struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msghdr);
+ cmsg->cmsg_len = cmsg_len(sizeof(socket_type));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ std::memcpy(CMSG_DATA(cmsg), &val, sizeof(socket_type));
+
+ const int ret = sendmsg(sock, &msghdr, 0);
+ free(msghdr.msg_control);
+ return (ret >= 0 ? 0 : SOCKET_SYSTEM_ERROR);
+}
+
+} // End for namespace io
+} // End for namespace util
+} // End for namespace isc
diff --git a/src/lib/util/io/socket_share.h b/src/lib/util/io/socket_share.h
new file mode 100644
index 0000000..444152f
--- /dev/null
+++ b/src/lib/util/io/socket_share.h
@@ -0,0 +1,73 @@
+// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef SOCKET_SHARE_H_
+#define SOCKET_SHARE_H_
+
+/**
+ * \file socket_share.h
+ * \short Support to transfer socket descriptors between processes.
+ * \todo This interface is very C-ish. Should we have some kind of exceptions?
+ */
+
+#include <asio.hpp>
+
+using namespace asio::detail;
+
+namespace isc {
+namespace util {
+namespace io {
+
+const int SOCKET_SYSTEM_ERROR = -2;
+const int SOCKET_OTHER_ERROR = -1;
+
+/**
+ * \short Receives a socket descriptor.
+ * This receives a socket descriptor sent over an unix domain socket. This
+ * is the counterpart of send_socket().
+ *
+ * \return SOCKET_SYSTEM_ERROR when there's an error at the operating system
+ * level (such as a system call failure). The global 'errno' variable
+ * indicates the specific error. SOCKET_OTHER_ERROR when there's a different
+ * error.
+ *
+ * \param sock The unix domain socket to read from. Tested and it does
+ * not work with a pipe.
+ */
+int recv_socket(const socket_type sock, socket_type *val);
+
+/**
+ * \short Sends a socket descriptor.
+ * This sends a socket descriptor over an unix domain socket. This is the
+ * counterpart of recv_socket().
+ *
+ * \return SOCKET_SYSTEM_ERROR when there's an error at the operating system
+ * level (such as a system call failure). The global 'errno' variable
+ * indicates the specific error.
+ * \param sock The unix domain socket to send to. Tested and it does not
+ * work with a pipe.
+ * \param val The socket descriptor to send. It should work with any valid
+ * socket descriptor.
+ */
+int send_socket(const socket_type sock, const socket_type val);
+
+} // End for namespace io
+} // End for namespace util
+} // End for namespace isc
+
+#endif
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/util/io/socketsession.cc b/src/lib/util/io/socketsession.cc
index 4c50949..ddcb90d 100644
--- a/src/lib/util/io/socketsession.cc
+++ b/src/lib/util/io/socketsession.cc
@@ -39,7 +39,7 @@
#include <util/buffer.h>
-#include "fd_share.h"
+#include "socket_share.h"
#include "socketsession.h"
#include "sockaddr_util.h"
@@ -58,7 +58,7 @@ using namespace internal;
const size_t DEFAULT_HEADER_BUFLEN = sizeof(uint16_t) + sizeof(uint32_t) * 6 +
sizeof(struct sockaddr_storage) * 2;
-// The allowable maximum size of data passed with the socket FD. For now
+// The allowable maximum size of data passed with the socket handle. For now
// we use a fixed value of 65535, the largest possible size of valid DNS
// messages. We may enlarge it or make it configurable as we see the need
// for more flexibility.
@@ -85,7 +85,7 @@ struct SocketSessionForwarder::ForwarderImpl {
ForwarderImpl() : buf_(DEFAULT_HEADER_BUFLEN) {}
struct sockaddr_un sock_un_;
socklen_t sock_un_len_;
- int fd_;
+ socket_type sd_;
OutputBuffer buf_;
};
@@ -116,14 +116,14 @@ SocketSessionForwarder::SocketSessionForwarder(const std::string& unix_file) :
#ifdef HAVE_SA_LEN
impl.sock_un_.sun_len = impl.sock_un_len_;
#endif
- impl.fd_ = -1;
+ impl.sd_ = invalid_socket;
impl_ = new ForwarderImpl;
*impl_ = impl;
}
SocketSessionForwarder::~SocketSessionForwarder() {
- if (impl_->fd_ != -1) {
+ if (impl_->sd_ != invalid_socket) {
close();
}
delete impl_;
@@ -131,21 +131,21 @@ SocketSessionForwarder::~SocketSessionForwarder() {
void
SocketSessionForwarder::connectToReceiver() {
- if (impl_->fd_ != -1) {
+ if (impl_->sd_ != invalid_socket) {
isc_throw(BadValue, "Duplicate connect to UNIX domain "
"endpoint " << impl_->sock_un_.sun_path);
}
- impl_->fd_ = socket(AF_UNIX, SOCK_STREAM, 0);
- if (impl_->fd_ == -1) {
+ impl_->sd_ = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (impl_->sd_ == invalid_socket) {
isc_throw(SocketSessionError, "Failed to create a UNIX domain socket: "
<< strerror(errno));
}
// Make the socket non blocking
- int fcntl_flags = fcntl(impl_->fd_, F_GETFL, 0);
+ int fcntl_flags = fcntl(impl_->sd_, F_GETFL, 0);
if (fcntl_flags != -1) {
fcntl_flags |= O_NONBLOCK;
- fcntl_flags = fcntl(impl_->fd_, F_SETFL, fcntl_flags);
+ fcntl_flags = fcntl(impl_->sd_, F_SETFL, fcntl_flags);
}
if (fcntl_flags == -1) {
close(); // note: this is the internal method, not ::close()
@@ -157,16 +157,16 @@ SocketSessionForwarder::connectToReceiver() {
// current size, simply set the sufficient size.
int sndbuf_size;
socklen_t sndbuf_size_len = sizeof(sndbuf_size);
- if (getsockopt(impl_->fd_, SOL_SOCKET, SO_SNDBUF, &sndbuf_size,
+ if (getsockopt(impl_->sd_, SOL_SOCKET, SO_SNDBUF, &sndbuf_size,
&sndbuf_size_len) == -1 ||
sndbuf_size < SOCKSESSION_BUFSIZE) {
- if (setsockopt(impl_->fd_, SOL_SOCKET, SO_SNDBUF, &SOCKSESSION_BUFSIZE,
+ if (setsockopt(impl_->sd_, SOL_SOCKET, SO_SNDBUF, &SOCKSESSION_BUFSIZE,
sizeof(SOCKSESSION_BUFSIZE)) == -1) {
close();
isc_throw(SocketSessionError, "Failed to set send buffer size");
}
}
- if (connect(impl_->fd_, convertSockAddr(&impl_->sock_un_),
+ if (connect(impl_->sd_, convertSockAddr(&impl_->sock_un_),
impl_->sock_un_len_) == -1) {
close();
isc_throw(SocketSessionError, "Failed to connect to UNIX domain "
@@ -177,20 +177,21 @@ SocketSessionForwarder::connectToReceiver() {
void
SocketSessionForwarder::close() {
- if (impl_->fd_ == -1) {
+ if (impl_->sd_ == invalid_socket) {
isc_throw(BadValue, "Attempt of close before connect");
}
- ::close(impl_->fd_);
- impl_->fd_ = -1;
+ ::close(impl_->sd_);
+ impl_->sd_ = invalid_socket;
}
void
-SocketSessionForwarder::push(int sock, int family, int type, int protocol,
+SocketSessionForwarder::push(socket_type sock,
+ int family, int type, int protocol,
const struct sockaddr& local_end,
const struct sockaddr& remote_end,
const void* data, size_t data_len)
{
- if (impl_->fd_ == -1) {
+ if (impl_->sd_ == invalid_socket) {
isc_throw(BadValue, "Attempt of push before connect");
}
if ((local_end.sa_family != AF_INET && local_end.sa_family != AF_INET6) ||
@@ -215,8 +216,8 @@ SocketSessionForwarder::push(int sock, int family, int type, int protocol,
data_len << ", must not exceed " << MAX_DATASIZE);
}
- if (send_fd(impl_->fd_, sock) != 0) {
- isc_throw(SocketSessionError, "FD passing failed: " <<
+ if (send_socket(impl_->sd_, sock) != 0) {
+ isc_throw(SocketSessionError, "socket passing failed: " <<
strerror(errno));
}
@@ -244,7 +245,7 @@ SocketSessionForwarder::push(int sock, int family, int type, int protocol,
{ const_cast<void*>(impl_->buf_.getData()), impl_->buf_.getLength() },
{ const_cast<void*>(data), data_len }
};
- const int cc = writev(impl_->fd_, iov, 2);
+ const int cc = writev(impl_->sd_, iov, 2);
if (cc != impl_->buf_.getLength() + data_len) {
if (cc < 0) {
isc_throw(SocketSessionError,
@@ -257,7 +258,8 @@ SocketSessionForwarder::push(int sock, int family, int type, int protocol,
}
}
-SocketSession::SocketSession(int sock, int family, int type, int protocol,
+SocketSession::SocketSession(socket_type sock,
+ int family, int type, int protocol,
const sockaddr* local_end,
const sockaddr* remote_end,
const void* data, size_t data_len) :
@@ -277,20 +279,20 @@ SocketSession::SocketSession(int sock, int family, int type, int protocol,
}
struct SocketSessionReceiver::ReceiverImpl {
- ReceiverImpl(int fd) : fd_(fd),
- sa_local_(convertSockAddr(&ss_local_)),
- sa_remote_(convertSockAddr(&ss_remote_)),
- header_buf_(DEFAULT_HEADER_BUFLEN),
- data_buf_(INITIAL_BUFSIZE)
+ ReceiverImpl(socket_type sd) : sd_(sd),
+ sa_local_(convertSockAddr(&ss_local_)),
+ sa_remote_(convertSockAddr(&ss_remote_)),
+ header_buf_(DEFAULT_HEADER_BUFLEN),
+ data_buf_(INITIAL_BUFSIZE)
{
- if (setsockopt(fd_, SOL_SOCKET, SO_RCVBUF, &SOCKSESSION_BUFSIZE,
+ if (setsockopt(sd_, SOL_SOCKET, SO_RCVBUF, &SOCKSESSION_BUFSIZE,
sizeof(SOCKSESSION_BUFSIZE)) == -1) {
isc_throw(SocketSessionError,
"Failed to set receive buffer size");
}
}
- const int fd_;
+ const socket_type sd_;
struct sockaddr_storage ss_local_; // placeholder for local endpoint
struct sockaddr* const sa_local_;
struct sockaddr_storage ss_remote_; // placeholder for remote endpoint
@@ -301,8 +303,8 @@ struct SocketSessionReceiver::ReceiverImpl {
vector<uint8_t> data_buf_;
};
-SocketSessionReceiver::SocketSessionReceiver(int fd) :
- impl_(new ReceiverImpl(fd))
+SocketSessionReceiver::SocketSessionReceiver(socket_type sd) :
+ impl_(new ReceiverImpl(sd))
{
}
@@ -327,33 +329,33 @@ readFail(int actual_len, int expected_len) {
// SocketSessionReceiver::pop that ensures the socket is closed unless it
// can be safely passed to the caller via release().
struct ScopedSocket : boost::noncopyable {
- ScopedSocket(int fd) : fd_(fd) {}
+ ScopedSocket(socket_type sd) : sd_(sd) {}
~ScopedSocket() {
- if (fd_ >= 0) {
- close(fd_);
+ if (sd_ != invalid_socket) {
+ close(sd_);
}
}
int release() {
- const int fd = fd_;
- fd_ = -1;
- return (fd);
+ const socket_type sd = sd_;
+ sd_ = invalid_socket;
+ return (sd);
}
- int fd_;
+ socket_type sd_;
};
}
SocketSession
SocketSessionReceiver::pop() {
- ScopedSocket passed_sock(recv_fd(impl_->fd_));
- if (passed_sock.fd_ == FD_SYSTEM_ERROR) {
- isc_throw(SocketSessionError, "Receiving a forwarded FD failed: " <<
- strerror(errno));
- } else if (passed_sock.fd_ < 0) {
- isc_throw(SocketSessionError, "No FD forwarded");
+ ScopedSocket passed_sock(invalid_socket);
+ if (recv_socket(impl_->sd_, &passed_sock.sd_) == SOCKET_SYSTEM_ERROR) {
+ isc_throw(SocketSessionError,
+ "Receiving a forwarded socket failed: " << strerror(errno));
+ } else if (passed_sock.sd_ == invalid_socket) {
+ isc_throw(SocketSessionError, "No socket forwarded");
}
uint16_t header_len;
- const int cc_hlen = recv(impl_->fd_, &header_len, sizeof(header_len),
+ const int cc_hlen = recv(impl_->sd_, &header_len, sizeof(header_len),
MSG_WAITALL);
if (cc_hlen < sizeof(header_len)) {
readFail(cc_hlen, sizeof(header_len));
@@ -365,7 +367,7 @@ SocketSessionReceiver::pop() {
}
impl_->header_buf_.clear();
impl_->header_buf_.resize(header_len);
- const int cc_hdr = recv(impl_->fd_, &impl_->header_buf_[0], header_len,
+ const int cc_hdr = recv(impl_->sd_, &impl_->header_buf_[0], header_len,
MSG_WAITALL);
if (cc_hdr < header_len) {
readFail(cc_hdr, header_len);
@@ -412,7 +414,7 @@ SocketSessionReceiver::pop() {
impl_->data_buf_.clear();
impl_->data_buf_.resize(data_len);
- const int cc_data = recv(impl_->fd_, &impl_->data_buf_[0], data_len,
+ const int cc_data = recv(impl_->sd_, &impl_->data_buf_[0], data_len,
MSG_WAITALL);
if (cc_data < data_len) {
readFail(cc_data, data_len);
diff --git a/src/lib/util/io/socketsession.h b/src/lib/util/io/socketsession.h
index 48b7f19..9bfb50a 100644
--- a/src/lib/util/io/socketsession.h
+++ b/src/lib/util/io/socketsession.h
@@ -17,11 +17,13 @@
#include <boost/noncopyable.hpp>
+#include <asio.hpp>
+
#include <exceptions/exceptions.h>
#include <string>
-#include <sys/socket.h>
+using asio::detail::socket_type;
namespace isc {
namespace util {
@@ -50,13 +52,13 @@ namespace io {
/// provided separately from the socket.
///
/// In the actual implementation we represent a socket as a tuple of
-/// socket's file descriptor, address family (e.g. \c AF_INET6),
+/// socket's descriptor, address family (e.g. \c AF_INET6),
/// socket type (e.g. \c SOCK_STREAM), and protocol (e.g. \c IPPROTO_TCP).
/// The latter three are included in the representation of a socket in order
/// to provide complete information of how the socket would be created
/// by the \c socket(2) system call. More specifically in practice, these
/// parameters could be used to construct a Python socket object from the
-/// file descriptor.
+/// socket descriptor.
///
/// We use the standard \c sockaddr structure to represent endpoints.
///
@@ -64,7 +66,7 @@ namespace io {
/// (possibly with some reasonable upper limit).
///
/// To forward a socket session between processes, we use connected UNIX
-/// domain sockets established between the processes. The file descriptor
+/// domain sockets established between the processes. The socket descriptor
/// will be forwarded through the sockets as an ancillary data item of
/// type \c SCM_RIGHTS. Other elements of the session will be transferred
/// as normal data over the connection.
@@ -78,9 +80,9 @@ namespace io {
/// \c SocketSessionForwarder and \c SocketSessionReceiver objects use a
/// straightforward protocol to pass elements of socket sessions.
/// Once the connection is established, the forwarder object first forwards
-/// the file descriptor with 1-byte dummy data. It then forwards a
+/// the socket descriptor with 1-byte dummy data. It then forwards a
/// "(socket) session header", which contains all other elements of the session
-/// except the file descriptor (already forwarded) and session data.
+/// except the socket descriptor (already forwarded) and session data.
/// The wire format of the header is as follows:
/// - The length of the header (16-bit unsigned integer)
/// - Address family
@@ -181,7 +183,7 @@ public:
virtual ~BaseSocketSessionForwarder() {}
virtual void connectToReceiver() = 0;
virtual void close() = 0;
- virtual void push(int sock, int family, int type, int protocol,
+ virtual void push(socket_type sock, int family, int type, int protocol,
const struct sockaddr& local_end,
const struct sockaddr& remote_end,
const void* data, size_t data_len) = 0;
@@ -297,7 +299,7 @@ public:
/// \exception SocketSessionError A system error in socket operation,
/// including the case where the write operation would block.
///
- /// \param sock The socket file descriptor
+ /// \param sock The socket socket descriptor
/// \param family The address family (such as AF_INET6) of the socket
/// \param type The socket type (such as SOCK_DGRAM) of the socket
/// \param protocol The transport protocol (such as IPPROTO_UDP) of the
@@ -309,7 +311,7 @@ public:
/// \param data A pointer to the beginning of the memory region for the
/// session data
/// \param data_len The size of the session data in bytes.
- virtual void push(int sock, int family, int type, int protocol,
+ virtual void push(socket_type sock, int family, int type, int protocol,
const struct sockaddr& local_end,
const struct sockaddr& remote_end,
const void* data, size_t data_len);
@@ -346,7 +348,7 @@ public:
/// \exception BadValue Given parameters don't meet the requirement
/// (see the parameter descriptions).
///
- /// \param sock The socket file descriptor
+ /// \param sock The socket descriptor
/// \param family The address family (such as AF_INET6) of the socket
/// \param type The socket type (such as SOCK_DGRAM) of the socket
/// \param protocol The transport protocol (such as IPPROTO_UDP) of the
@@ -359,12 +361,12 @@ public:
/// session data. Must not be NULL, and the subsequent \c data_len bytes
/// must be valid.
/// \param data_len The size of the session data in bytes. Must not be 0.
- SocketSession(int sock, int family, int type, int protocol,
+ SocketSession(socket_type sock, int family, int type, int protocol,
const sockaddr* local_end, const sockaddr* remote_end,
const void* data, size_t data_len);
- /// Return the socket file descriptor.
- int getSocket() const { return (sock_); }
+ /// Return the socket descriptor.
+ socket_type getSocket() const { return (sock_); }
/// Return the address family (such as AF_INET6) of the socket.
int getFamily() const { return (family_); }
@@ -394,7 +396,7 @@ public:
size_t getDataLength() const { return (data_len_); }
private:
- const int sock_;
+ const socket_type sock_;
const int family_;
const int type_;
const int protocol_;
@@ -433,7 +435,7 @@ public:
///
/// \param fd A UNIX domain socket for an established connection with
/// a forwarder.
- explicit SocketSessionReceiver(int fd);
+ explicit SocketSessionReceiver(socket_type sd);
/// The destructor.
///
@@ -455,7 +457,7 @@ public:
/// destructed.
///
/// The caller is responsible for closing the received socket (whose
- /// file descriptor is accessible via \c SocketSession::getSocket()).
+ /// socket descriptor is accessible via \c SocketSession::getSocket()).
/// If the caller copies the returned \c SocketSession object, it's also
/// responsible for making sure the descriptor is closed at most once.
/// On the other hand, the caller is not responsible for freeing the
diff --git a/src/lib/util/io/socketshare_python.cc b/src/lib/util/io/socketshare_python.cc
new file mode 100644
index 0000000..81eb307
--- /dev/null
+++ b/src/lib/util/io/socketshare_python.cc
@@ -0,0 +1,105 @@
+// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+#include <structmember.h>
+
+#include <config.h>
+
+#include "socket_share.h"
+
+
+static PyObject*
+socketshare_recv_socket(PyObject*, PyObject* args) {
+ int result;
+ socket_type sock, sd;
+ if (!PyArg_ParseTuple(args, "i", &sock)) {
+ return (NULL);
+ }
+ result = isc::util::io::recv_socket(sock, &sd);
+ if (result != 0) {
+ return (Py_BuildValue("i", result));
+ } else {
+ return (Py_BuildValue("i", sd));
+ }
+}
+
+static PyObject*
+socketshare_send_socket(PyObject*, PyObject* args) {
+ int result;
+ socket_type sock, sd;
+ if (!PyArg_ParseTuple(args, "ii", &sock, &sd)) {
+ return (NULL);
+ }
+ result = isc::util::io::send_socket(sock, sd);
+ return (Py_BuildValue("i", result));
+}
+
+static PyMethodDef socketshare_Methods[] = {
+ {"send_socket", socketshare_send_socket, METH_VARARGS, ""},
+ {"recv_socket", socketshare_recv_socket, METH_VARARGS, ""},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+
+static PyModuleDef bind10_socketshare_python = {
+ { PyObject_HEAD_INIT(NULL) NULL, 0, NULL},
+ "bind10_socketshare",
+ "Python bindings for socketshare",
+ -1,
+ socketshare_Methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PyMODINIT_FUNC
+PyInit_libutil_io_python(void) {
+ PyObject *mod = PyModule_Create(&bind10_socketshare_python);
+ if (mod == NULL) {
+ return (NULL);
+ }
+
+ PyObject* SOCKET_SYSTEM_ERROR =
+ Py_BuildValue("i", isc::util::io::SOCKET_SYSTEM_ERROR);
+ if (SOCKET_SYSTEM_ERROR == NULL) {
+ Py_XDECREF(mod);
+ return (NULL);
+ }
+ int ret;
+ ret = PyModule_AddObject(mod, "SOCKET_SYSTEM_ERROR", SOCKET_SYSTEM_ERROR);
+ if (ret == -1) {
+ Py_XDECREF(SOCKET_SYSTEM_ERROR);
+ Py_XDECREF(mod);
+ return (NULL);
+ }
+
+ PyObject* SOCKET_OTHER_ERROR =
+ Py_BuildValue("i", isc::util::io::SOCKET_OTHER_ERROR);
+ if (SOCKET_OTHER_ERROR == NULL) {
+ Py_XDECREF(mod);
+ return (NULL);
+ }
+ ret = PyModule_AddObject(mod, "SOCKET_OTHER_ERROR", SOCKET_OTHER_ERROR);
+ if (ret == -1) {
+ Py_XDECREF(SOCKET_OTHER_ERROR);
+ Py_XDECREF(mod);
+ return (NULL);
+ }
+
+ return (mod);
+}
+
diff --git a/src/lib/util/tests/Makefile.am b/src/lib/util/tests/Makefile.am
index 105322f..5b7d262 100644
--- a/src/lib/util/tests/Makefile.am
+++ b/src/lib/util/tests/Makefile.am
@@ -25,8 +25,8 @@ run_unittests_SOURCES = run_unittests.cc
run_unittests_SOURCES += base32hex_unittest.cc
run_unittests_SOURCES += base64_unittest.cc
run_unittests_SOURCES += buffer_unittest.cc
-run_unittests_SOURCES += fd_share_tests.cc
-run_unittests_SOURCES += fd_tests.cc
+run_unittests_SOURCES += socket_share_tests.cc
+run_unittests_SOURCES += socket_tests.cc
run_unittests_SOURCES += filename_unittest.cc
run_unittests_SOURCES += hex_unittest.cc
run_unittests_SOURCES += io_utilities_unittest.cc
diff --git a/src/lib/util/tests/fd_share_tests.cc b/src/lib/util/tests/fd_share_tests.cc
deleted file mode 100644
index cc92e47..0000000
--- a/src/lib/util/tests/fd_share_tests.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <util/io/fd.h>
-#include <util/io/fd_share.h>
-
-#include <util/unittests/fork.h>
-
-#include <gtest/gtest.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <cstdio>
-
-using namespace isc::util::io;
-using namespace isc::util::unittests;
-
-namespace {
-
-// We test that we can transfer a pipe over other pipe
-TEST(FDShare, transfer) {
- // Get a pipe and fork
- int pipes[2];
- ASSERT_NE(-1, socketpair(AF_UNIX, SOCK_STREAM, 0, pipes));
- pid_t sender(fork());
- ASSERT_NE(-1, sender);
- if(sender) { // We are in parent
- // Close the other side of pipe, we want only writible one
- EXPECT_NE(-1, close(pipes[0]));
- // Get a process to check data
- int fd(0);
- pid_t checker(check_output(&fd, "data", 4));
- ASSERT_NE(-1, checker);
- // Now, send the file descriptor, close it and close the pipe
- EXPECT_NE(-1, send_fd(pipes[1], fd));
- EXPECT_NE(-1, close(pipes[1]));
- EXPECT_NE(-1, close(fd));
- // Check both subprocesses ended well
- EXPECT_TRUE(process_ok(sender));
- EXPECT_TRUE(process_ok(checker));
- } else { // We are in child. We do not use ASSERT here
- // Close the write end, we only read
- if(close(pipes[1])) {
- exit(1);
- }
- // Get the file descriptor
- int fd(recv_fd(pipes[0]));
- if(fd == -1) {
- exit(1);
- }
- // This pipe is not needed
- if(close(pipes[0])) {
- exit(1);
- }
- // Send "data" trough the received fd, close it and be done
- if(!write_data(fd, "data", 4) || close(fd) == -1) {
- exit(1);
- }
- exit(0);
- }
-}
-
-}
diff --git a/src/lib/util/tests/fd_tests.cc b/src/lib/util/tests/fd_tests.cc
deleted file mode 100644
index 6ba2766..0000000
--- a/src/lib/util/tests/fd_tests.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <util/io/fd.h>
-
-#include <util/unittests/fork.h>
-
-#include <gtest/gtest.h>
-
-using namespace isc::util::io;
-using namespace isc::util::unittests;
-
-namespace {
-
-// Make sure the test is large enough and does not fit into one
-// read or write request
-const size_t TEST_DATA_SIZE = 8 * 1024 * 1024;
-
-class FDTest : public ::testing::Test {
- public:
- unsigned char *data, *buffer;
- FDTest() :
- // We do not care what is inside, we just need it to be the same
- data(new unsigned char[TEST_DATA_SIZE]),
- buffer(NULL)
- { }
- ~ FDTest() {
- delete[] data;
- delete[] buffer;
- }
-};
-
-// Test we read what was sent
-TEST_F(FDTest, read) {
- int read_pipe(0);
- buffer = new unsigned char[TEST_DATA_SIZE];
- pid_t feeder(provide_input(&read_pipe, data, TEST_DATA_SIZE));
- ASSERT_GE(feeder, 0);
- ssize_t received(read_data(read_pipe, buffer, TEST_DATA_SIZE));
- EXPECT_TRUE(process_ok(feeder));
- EXPECT_EQ(TEST_DATA_SIZE, received);
- EXPECT_EQ(0, memcmp(data, buffer, received));
-}
-
-// Test we write the correct thing
-TEST_F(FDTest, write) {
- int write_pipe(0);
- pid_t checker(check_output(&write_pipe, data, TEST_DATA_SIZE));
- ASSERT_GE(checker, 0);
- EXPECT_TRUE(write_data(write_pipe, data, TEST_DATA_SIZE));
- EXPECT_EQ(0, close(write_pipe));
- EXPECT_TRUE(process_ok(checker));
-}
-
-}
diff --git a/src/lib/util/tests/socket_share_tests.cc b/src/lib/util/tests/socket_share_tests.cc
new file mode 100644
index 0000000..2652afe
--- /dev/null
+++ b/src/lib/util/tests/socket_share_tests.cc
@@ -0,0 +1,74 @@
+// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <util/io/socket.h>
+#include <util/io/socket_share.h>
+
+#include <util/unittests/fork.h>
+
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <cstdio>
+
+using namespace isc::util::io;
+using namespace isc::util::unittests;
+
+namespace {
+
+// We test that we can transfer a pipe over other pipe
+TEST(SDShare, transfer) {
+ // Get a pipe and fork
+ int pipes[2];
+ ASSERT_NE(-1, socketpair(AF_UNIX, SOCK_STREAM, 0, pipes));
+ pid_t sender(fork());
+ ASSERT_NE(-1, sender);
+ if(sender) { // We are in parent
+ // Close the other side of pipe, we want only writible one
+ EXPECT_NE(-1, close(pipes[0]));
+ // Get a process to check data
+ socket_type sd(invalid_socket);
+ pid_t checker(check_output(&sd, "data", 4));
+ ASSERT_NE(-1, checker);
+ // Now, send the socket descriptor, close it and close the pipe
+ EXPECT_NE(-1, send_socket(pipes[1], sd));
+ EXPECT_NE(-1, close(pipes[1]));
+ EXPECT_NE(-1, close(sd));
+ // Check both subprocesses ended well
+ EXPECT_TRUE(process_ok(sender));
+ EXPECT_TRUE(process_ok(checker));
+ } else { // We are in child. We do not use ASSERT here
+ // Close the write end, we only read
+ if(close(pipes[1])) {
+ exit(1);
+ }
+ // Get the socket descriptor
+ socket_type sd(invalid_socket);
+ if (recv_socket(pipes[0], &sd) == -1) {
+ exit(1);
+ }
+ // This pipe is not needed
+ if(close(pipes[0])) {
+ exit(1);
+ }
+ // Send "data" trough the received socket, close it and be done
+ if(!write_data(sd, "data", 4) || close(sd) == -1) {
+ exit(1);
+ }
+ exit(0);
+ }
+}
+
+}
diff --git a/src/lib/util/tests/socket_tests.cc b/src/lib/util/tests/socket_tests.cc
new file mode 100644
index 0000000..cbbba00
--- /dev/null
+++ b/src/lib/util/tests/socket_tests.cc
@@ -0,0 +1,66 @@
+// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <util/io/socket.h>
+
+#include <util/unittests/fork.h>
+
+#include <gtest/gtest.h>
+
+using namespace isc::util::io;
+using namespace isc::util::unittests;
+
+namespace {
+
+// Make sure the test is large enough and does not fit into one
+// read or write request
+const size_t TEST_DATA_SIZE = 8 * 1024 * 1024;
+
+class SDTest : public ::testing::Test {
+ public:
+ unsigned char *data, *buffer;
+ SDTest() :
+ // We do not care what is inside, we just need it to be the same
+ data(new unsigned char[TEST_DATA_SIZE]),
+ buffer(NULL)
+ { }
+ ~ SDTest() {
+ delete[] data;
+ delete[] buffer;
+ }
+};
+
+// Test we receive what was sent
+TEST_F(SDTest, receive) {
+ socket_type read_pipe(invalid_socket);
+ buffer = new unsigned char[TEST_DATA_SIZE];
+ pid_t feeder(provide_input(&read_pipe, data, TEST_DATA_SIZE));
+ ASSERT_GE(feeder, 0);
+ ssize_t received(read_data(read_pipe, buffer, TEST_DATA_SIZE));
+ EXPECT_TRUE(process_ok(feeder));
+ EXPECT_EQ(TEST_DATA_SIZE, received);
+ EXPECT_EQ(0, memcmp(data, buffer, received));
+}
+
+// Test we send the correct thing
+TEST_F(SDTest, send) {
+ socket_type write_pipe(invalid_socket);
+ pid_t checker(check_output(&write_pipe, data, TEST_DATA_SIZE));
+ ASSERT_GE(checker, 0);
+ EXPECT_TRUE(write_data(write_pipe, data, TEST_DATA_SIZE));
+ EXPECT_EQ(0, close(write_pipe));
+ EXPECT_TRUE(process_ok(checker));
+}
+
+}
diff --git a/src/lib/util/tests/socketsession_unittest.cc b/src/lib/util/tests/socketsession_unittest.cc
index e83c140..fb33762 100644
--- a/src/lib/util/tests/socketsession_unittest.cc
+++ b/src/lib/util/tests/socketsession_unittest.cc
@@ -34,17 +34,20 @@
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
+#include <asio.hpp>
+
#include <gtest/gtest.h>
#include <exceptions/exceptions.h>
#include <util/buffer.h>
-#include <util/io/fd_share.h>
+#include <util/io/socket_share.h>
#include <util/io/socketsession.h>
#include <util/io/sockaddr_util.h>
using namespace std;
using namespace isc;
+using namespace asio::detail;
using boost::scoped_ptr;
using namespace isc::util::io;
using namespace isc::util::io::internal;
@@ -59,20 +62,20 @@ const char TEST_DATA[] = "BIND10 test";
// A simple helper structure to automatically close test sockets on return
// or exception in a RAII manner. non copyable to prevent duplicate close.
struct ScopedSocket : boost::noncopyable {
- ScopedSocket() : fd(-1) {}
- ScopedSocket(int sock) : fd(sock) {}
+ ScopedSocket() : sd(invalid_socket) {}
+ ScopedSocket(socket_type sock) : sd(sock) {}
~ScopedSocket() {
closeSocket();
}
- void reset(int sock) {
+ void reset(socket_type sock) {
closeSocket();
- fd = sock;
+ sd = sock;
}
- int fd;
+ socket_type sd;
private:
void closeSocket() {
- if (fd >= 0) {
- close(fd);
+ if (sd != invalid_socket) {
+ close(sd);
}
}
};
@@ -80,7 +83,7 @@ private:
// A helper function that makes a test socket non block so that a certain
// kind of test failure (such as missing send) won't cause hangup.
void
-setNonBlock(int s, bool on) {
+setNonBlock(socket_type s, bool on) {
int fcntl_flags = fcntl(s, F_GETFL, 0);
if (on) {
fcntl_flags |= O_NONBLOCK;
@@ -97,7 +100,7 @@ setNonBlock(int s, bool on) {
// if possible. It returns an option flag to be set for the system call
// (when necessary).
int
-setRecvDelay(int s) {
+setRecvDelay(socket_type s) {
const struct timeval timeo = { 10, 0 };
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)) == -1) {
if (errno == ENOPROTOOPT) {
@@ -155,7 +158,7 @@ private:
class ForwardTest : public ::testing::Test {
protected:
- ForwardTest() : listen_fd_(-1), forwarder_(TEST_UNIX_FILE),
+ ForwardTest() : listen_sd_(invalid_socket), forwarder_(TEST_UNIX_FILE),
large_text_(65535, 'a'),
test_un_len_(2 + strlen(TEST_UNIX_FILE))
{
@@ -168,36 +171,36 @@ protected:
}
~ForwardTest() {
- if (listen_fd_ != -1) {
- close(listen_fd_);
+ if (listen_sd_ != invalid_socket) {
+ close(listen_sd_);
}
unlink(TEST_UNIX_FILE);
}
// Start an internal "socket session server".
void startListen() {
- if (listen_fd_ != -1) {
+ if (listen_sd_ != invalid_socket) {
isc_throw(isc::Unexpected, "duplicate call to startListen()");
}
- listen_fd_ = socket(AF_UNIX, SOCK_STREAM, 0);
- if (listen_fd_ == -1) {
+ listen_sd_ = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (listen_sd_ == invalid_socket) {
isc_throw(isc::Unexpected, "failed to create UNIX domain socket" <<
strerror(errno));
}
- if (bind(listen_fd_, convertSockAddr(&test_un_), test_un_len_) == -1) {
+ if (bind(listen_sd_, convertSockAddr(&test_un_), test_un_len_) == -1) {
isc_throw(isc::Unexpected, "failed to bind UNIX domain socket" <<
strerror(errno));
}
// 10 is an arbitrary choice, should be sufficient for a single test
- if (listen(listen_fd_, 10) == -1) {
+ if (listen(listen_sd_, 10) == -1) {
isc_throw(isc::Unexpected, "failed to listen on UNIX domain socket"
<< strerror(errno));
}
}
- int dummyConnect() const {
- const int s = socket(AF_UNIX, SOCK_STREAM, 0);
- if (s == -1) {
+ socket_type dummyConnect() const {
+ const socket_type s = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (s == invalid_socket) {
isc_throw(isc::Unexpected,
"failed to create a test UNIX domain socket");
}
@@ -210,14 +213,16 @@ protected:
}
// Accept a new connection from a SocketSessionForwarder and return
- // the socket FD of the new connection. This assumes startListen()
+ // the socket handle of the new connection. This assumes startListen()
// has been called.
- int acceptForwarder() {
- setNonBlock(listen_fd_, true); // prevent the test from hanging up
+ socket_type acceptForwarder() {
+ setNonBlock(listen_sd_, true); // prevent the test from hanging up
struct sockaddr_un from;
socklen_t from_len = sizeof(from);
- const int s = accept(listen_fd_, convertSockAddr(&from), &from_len);
- if (s == -1) {
+ const socket_type s = accept(listen_sd_,
+ convertSockAddr(&from),
+ &from_len);
+ if (s == invalid_socket) {
isc_throw(isc::Unexpected, "accept failed: " << strerror(errno));
}
// Make sure the socket is *blocking*. We may pass large data, through
@@ -237,11 +242,11 @@ protected:
// to the specified address and port in sainfo. If do_listen is true
// and it's a TCP socket, it will also start listening to new connection
// requests.
- int createSocket(int family, int type, int protocol,
- const SockAddrInfo& sainfo, bool do_listen)
+ socket_type createSocket(int family, int type, int protocol,
+ const SockAddrInfo& sainfo, bool do_listen)
{
- int s = socket(family, type, protocol);
- if (s < 0) {
+ socket_type s = socket(family, type, protocol);
+ if (s == invalid_socket) {
isc_throw(isc::Unexpected, "socket(2) failed: " <<
strerror(errno));
}
@@ -278,30 +283,30 @@ protected:
// \param hdrlen_len: The length of the actually pushed data as "header
// length". Normally it should be 2 (the default), but
// could be a bogus value for testing.
- // \param push_fd: Whether to forward the FD. Normally it should be true,
- // but can be false for testing.
+ // \param push_sd: Whether to forward the socket. Normally it
+ // should be true, but can be false for testing.
void pushSessionHeader(uint16_t hdrlen,
size_t hdrlen_len = sizeof(uint16_t),
- bool push_fd = true,
- int fd = 0)
+ bool push_sd = true,
+ socket_type sd = 0)
{
isc::util::OutputBuffer obuffer(0);
obuffer.clear();
dummy_forwarder_.reset(dummyConnect());
- if (push_fd && send_fd(dummy_forwarder_.fd, fd) != 0) {
- isc_throw(isc::Unexpected, "Failed to pass FD");
+ if (push_sd && send_socket(dummy_forwarder_.sd, sd) != 0) {
+ isc_throw(isc::Unexpected, "Failed to pass socket");
}
obuffer.writeUint16(hdrlen);
if (hdrlen_len > 0) {
- if (send(dummy_forwarder_.fd, obuffer.getData(), hdrlen_len, 0) !=
+ if (send(dummy_forwarder_.sd, obuffer.getData(), hdrlen_len, 0) !=
hdrlen_len) {
isc_throw(isc::Unexpected,
"Failed to pass session header len");
}
}
accept_sock_.reset(acceptForwarder());
- receiver_.reset(new SocketSessionReceiver(accept_sock_.fd));
+ receiver_.reset(new SocketSessionReceiver(accept_sock_.sd));
}
// A helper method to push some (normally bogus) socket session via a
@@ -327,11 +332,11 @@ protected:
obuffer.writeData(&remote, min(remote_len, getSALength(remote)));
obuffer.writeUint32(static_cast<uint32_t>(data_len));
pushSessionHeader(obuffer.getLength());
- if (send(dummy_forwarder_.fd, obuffer.getData(), obuffer.getLength(),
+ if (send(dummy_forwarder_.sd, obuffer.getData(), obuffer.getLength(),
0) != obuffer.getLength()) {
isc_throw(isc::Unexpected, "Failed to pass session header");
}
- if (send(dummy_forwarder_.fd, TEST_DATA, sizeof(TEST_DATA), 0) !=
+ if (send(dummy_forwarder_.sd, TEST_DATA, sizeof(TEST_DATA), 0) !=
sizeof(TEST_DATA)) {
isc_throw(isc::Unexpected, "Failed to pass session data");
}
@@ -344,7 +349,7 @@ protected:
size_t data_len, bool new_connection);
protected:
- int listen_fd_;
+ socket_type listen_sd_;
SocketSessionForwarder forwarder_;
ScopedSocket dummy_forwarder_; // forwarder "like" socket to pass bad data
scoped_ptr<SocketSessionReceiver> receiver_;
@@ -425,9 +430,9 @@ checkSockAddrs(const sockaddr& expected, const sockaddr& actual) {
// This is a commonly used test case that confirms normal behavior of
// session passing. It first creates a "local" socket (which is supposed
// to act as a "server") bound to the 'local' parameter. It then forwards
-// the descriptor of the FD of the local socket along with given data.
-// Next, it creates an Receiver object to receive the forwarded FD itself,
-// receives the FD, and sends test data from the received FD. The
+// the descriptor of the handle of the local socket along with given data.
+// Next, it creates an Receiver object to receive the forwarded handle itself,
+// receives the handle, and sends test data from the received handle. The
// test finally checks if it can receive the test data from the local socket
// at the Forwarder side. In the case of TCP it's a bit complicated because
// it first needs to establish a new connection, but essentially the test
@@ -454,26 +459,26 @@ ForwardTest::checkPushAndPop(int family, int type, int protocol,
{
// Create an original socket to be passed
const ScopedSocket sock(createSocket(family, type, protocol, local, true));
- int fwd_fd = sock.fd; // default FD to be forwarded
- ScopedSocket client_sock; // for TCP test we need a separate "client"..
- ScopedSocket server_sock; // ..and a separate socket for the connection
+ socket_type fwd_sd = sock.sd; // default handle to be forwarded
+ ScopedSocket client_sock; // for TCP test we need a separate "client"..
+ ScopedSocket server_sock; // ..and a separate socket for the connection
if (protocol == IPPROTO_TCP) {
// Use unspecified port for the "client" to avoid bind(2) failure
const SockAddrInfo client_addr = getSockAddr(family == AF_INET6 ?
"::1" : "127.0.0.1", "0");
client_sock.reset(createSocket(family, type, protocol, client_addr,
false));
- setNonBlock(client_sock.fd, true);
+ setNonBlock(client_sock.sd, true);
// This connect would "fail" due to EINPROGRESS. Ignore it for now.
- connect(client_sock.fd, local.first, local.second);
+ connect(client_sock.sd, local.first, local.second);
sockaddr_storage ss;
socklen_t salen = sizeof(ss);
- server_sock.reset(accept(sock.fd, convertSockAddr(&ss), &salen));
- if (server_sock.fd == -1) {
+ server_sock.reset(accept(sock.sd, convertSockAddr(&ss), &salen));
+ if (server_sock.sd == invalid_socket) {
isc_throw(isc::Unexpected, "internal accept failed: " <<
strerror(errno));
}
- fwd_fd = server_sock.fd;
+ fwd_sd = server_sock.sd;
}
// If a new connection is required, start the "server", have the
@@ -485,21 +490,21 @@ ForwardTest::checkPushAndPop(int family, int type, int protocol,
}
// Then push one socket session via the forwarder.
- forwarder_.push(fwd_fd, family, type, protocol, *local.first,
+ forwarder_.push(fwd_sd, family, type, protocol, *local.first,
*remote.first, data, data_len);
// Pop the socket session we just pushed from a local receiver, and
// check the content. Since we do blocking read on the receiver's socket,
// we set up an alarm to prevent hangup in case there's a bug that really
// makes the blocking happen.
- SocketSessionReceiver receiver(accept_sock_.fd);
+ SocketSessionReceiver receiver(accept_sock_.sd);
alarm(1); // set up 1-sec timer, an arbitrary choice.
const SocketSession sock_session = receiver.pop();
alarm(0); // then cancel it.
const ScopedSocket passed_sock(sock_session.getSocket());
- EXPECT_LE(0, passed_sock.fd);
- // The passed FD should be different from the original FD
- EXPECT_NE(fwd_fd, passed_sock.fd);
+ EXPECT_NE(passed_sock.sd, invalid_socket);
+ // The passed handle should be different from the original handle
+ EXPECT_NE(fwd_sd, passed_sock.sd);
EXPECT_EQ(family, sock_session.getFamily());
EXPECT_EQ(type, sock_session.getType());
EXPECT_EQ(protocol, sock_session.getProtocol());
@@ -508,16 +513,16 @@ ForwardTest::checkPushAndPop(int family, int type, int protocol,
ASSERT_EQ(data_len, sock_session.getDataLength());
EXPECT_EQ(0, memcmp(data, sock_session.getData(), data_len));
- // Check if the passed FD is usable by sending some data from it.
- setNonBlock(passed_sock.fd, false);
+ // Check if the passed handle is usable by sending some data from it.
+ setNonBlock(passed_sock.sd, false);
if (protocol == IPPROTO_UDP) {
EXPECT_EQ(sizeof(TEST_DATA),
- sendto(passed_sock.fd, TEST_DATA, sizeof(TEST_DATA), 0,
+ sendto(passed_sock.sd, TEST_DATA, sizeof(TEST_DATA), 0,
convertSockAddr(local.first), local.second));
} else {
- server_sock.reset(-1);
+ server_sock.reset(invalid_socket);
EXPECT_EQ(sizeof(TEST_DATA),
- send(passed_sock.fd, TEST_DATA, sizeof(TEST_DATA), 0));
+ send(passed_sock.sd, TEST_DATA, sizeof(TEST_DATA), 0));
}
// We don't use non blocking read below as it doesn't seem to be always
// reliable. Instead we impose some reasonably large upper time limit of
@@ -528,23 +533,23 @@ ForwardTest::checkPushAndPop(int family, int type, int protocol,
socklen_t sa_len = sizeof(ss);
if (protocol == IPPROTO_UDP) {
EXPECT_EQ(sizeof(recvbuf),
- recvfrom(fwd_fd, recvbuf, sizeof(recvbuf),
- setRecvDelay(fwd_fd), convertSockAddr(&ss),
+ recvfrom(fwd_sd, recvbuf, sizeof(recvbuf),
+ setRecvDelay(fwd_sd), convertSockAddr(&ss),
&sa_len));
} else {
- setNonBlock(client_sock.fd, false);
+ setNonBlock(client_sock.sd, false);
EXPECT_EQ(sizeof(recvbuf),
- recv(client_sock.fd, recvbuf, sizeof(recvbuf),
- setRecvDelay(client_sock.fd)));
+ recv(client_sock.sd, recvbuf, sizeof(recvbuf),
+ setRecvDelay(client_sock.sd)));
}
EXPECT_EQ(string(TEST_DATA), string(recvbuf));
}
TEST_F(ForwardTest, pushAndPop) {
- // Pass a UDP/IPv6 session. We use different ports for different UDP
- // tests because Solaris 11 seems to prohibit reusing the same port for
- // some short period once the socket FD is forwarded, even if the sockets
- // are closed. See Trac #2028.
+ // Pass a UDP/IPv6 session. We use different ports for different
+ // UDP tests because Solaris 11 seems to prohibit reusing the same
+ // port for some short period once the socket handle is forwarded,
+ // even if the sockets are closed. See Trac #2028.
const SockAddrInfo sai_local6(getSockAddr("::1", TEST_PORT));
const SockAddrInfo sai_local6_alt(getSockAddr("::1", TEST_PORT2));
const SockAddrInfo sai_remote6(getSockAddr("2001:db8::1", "5300"));
@@ -664,8 +669,8 @@ TEST_F(ForwardTest, badPush) {
// Close the receiver before push. It will result in SIGPIPE (should be
// ignored) and EPIPE, which will be converted to SocketSessionError.
- const int receiver_fd = acceptForwarder();
- close(receiver_fd);
+ const int receiver_sd = acceptForwarder();
+ close(receiver_sd);
EXPECT_THROW(forwarder_.push(1, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
*getSockAddr("192.0.2.1", "53").first,
*getSockAddr("192.0.2.2", "53").first,
@@ -709,34 +714,34 @@ TEST_F(ForwardTest, badPop) {
// Close the forwarder socket before pop() without sending anything.
pushSessionHeader(0, 0, false);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
- // Pretending to be a forwarder but don't actually pass FD.
+ // Pretending to be a forwarder but don't actually pass handle.
pushSessionHeader(0, 1, false);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
- // Pass a valid FD (stdin), but provide short data for the hdrlen
+ // Pass a valid handle (stdin), but provide short data for the hdrlen
pushSessionHeader(0, 1);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
- // Pass a valid FD, but provides too large hdrlen
+ // Pass a valid handle, but provides too large hdrlen
pushSessionHeader(0xffff);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Don't provide full header
pushSessionHeader(sizeof(uint32_t));
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Pushed header is too short
const uint8_t dummy_data = 0;
pushSessionHeader(1);
- send(dummy_forwarder_.fd, &dummy_data, 1, 0);
- dummy_forwarder_.reset(-1);
+ send(dummy_forwarder_.sd, &dummy_data, 1, 0);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// socket addresses commonly used below (the values don't matter).
@@ -747,79 +752,79 @@ TEST_F(ForwardTest, badPop) {
// Pass invalid address family (AF_UNSPEC)
pushSession(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, sai_local.second,
*sai_local.first, sai_remote.second, *sai_remote.first);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Pass inconsistent address family for local
pushSession(AF_INET, SOCK_DGRAM, IPPROTO_UDP, sai6.second,
*sai6.first, sai_remote.second, *sai_remote.first);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Same for remote
pushSession(AF_INET, SOCK_DGRAM, IPPROTO_UDP, sai_local.second,
*sai_local.first, sai6.second, *sai6.first);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Pass too big sa length for local
pushSession(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
sizeof(struct sockaddr_storage) + 1, *sai_local.first,
sai_remote.second, *sai_remote.first);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Same for remote
pushSession(AF_INET, SOCK_DGRAM, IPPROTO_UDP, sai_local.second,
*sai_local.first, sizeof(struct sockaddr_storage) + 1,
*sai_remote.first);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Pass too small sa length for local
pushSession(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
sizeof(struct sockaddr_in) - 1, *sai_local.first,
sai_remote.second, *sai_remote.first);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Same for remote
pushSession(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
sai6.second, *sai6.first, sizeof(struct sockaddr_in6) - 1,
*sai6.first);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Data length is too large
pushSession(AF_INET, SOCK_DGRAM, IPPROTO_UDP, sai_local.second,
*sai_local.first, sai_remote.second,
*sai_remote.first, 65536);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Empty data
pushSession(AF_INET, SOCK_DGRAM, IPPROTO_UDP, sai_local.second,
*sai_local.first, sai_remote.second,
*sai_remote.first, 0);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Not full data are passed
pushSession(AF_INET, SOCK_DGRAM, IPPROTO_UDP, sai_local.second,
*sai_local.first, sai_remote.second,
*sai_remote.first, sizeof(TEST_DATA) + 1);
- dummy_forwarder_.reset(-1);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
- // Check the forwarded FD is closed on failure
+ // Check the forwarded socket is closed on failure
ScopedSocket sock(createSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
getSockAddr("127.0.0.1", TEST_PORT),
false));
- pushSessionHeader(0, 1, true, sock.fd);
- dummy_forwarder_.reset(-1);
+ pushSessionHeader(0, 1, true, sock.sd);
+ dummy_forwarder_.reset(invalid_socket);
EXPECT_THROW(receiver_->pop(), SocketSessionError);
// Close the original socket
- sock.reset(-1);
+ sock.reset(invalid_socket);
// The passed one should have been closed, too, so we should be able
// to bind a new socket to the same port.
sock.reset(createSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
diff --git a/src/lib/util/unittests/fork.cc b/src/lib/util/unittests/fork.cc
index 3414a3c..c66587a 100644
--- a/src/lib/util/unittests/fork.cc
+++ b/src/lib/util/unittests/fork.cc
@@ -14,7 +14,7 @@
#include "fork.h"
-#include <util/io/fd.h>
+#include <util/io/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <stdio.h>
+using namespace asio::detail;
using namespace isc::util::io;
namespace {
@@ -70,9 +71,9 @@ process_ok(pid_t process) {
* Used to provide the input in non-blocking/asynchronous way.
*/
pid_t
-provide_input(int *read_pipe, const void *input, const size_t length)
+provide_input(socket_type *read_pipe, const void *input, const size_t length)
{
- int pipes[2];
+ socket_type pipes[2];
if (pipe(pipes)) {
return -1;
}
@@ -96,9 +97,9 @@ provide_input(int *read_pipe, const void *input, const size_t length)
* with given data. Used to check output of run in asynchronous way.
*/
pid_t
-check_output(int *write_pipe, const void *output, const size_t length)
+check_output(socket_type *write_pipe, const void *output, const size_t length)
{
- int pipes[2];
+ socket_type pipes[2];
if (pipe(pipes)) {
return -1;
}
diff --git a/src/lib/util/unittests/fork.h b/src/lib/util/unittests/fork.h
index 2d27a11..c641946 100644
--- a/src/lib/util/unittests/fork.h
+++ b/src/lib/util/unittests/fork.h
@@ -17,6 +17,8 @@
#include <unistd.h>
+#include <asio.hpp>
+
/**
* \file fork.h
* \brief Help functions to fork the test case process.
@@ -40,10 +42,12 @@ bool
process_ok(pid_t process);
pid_t
-provide_input(int *read_pipe, const void *input, const size_t length);
+provide_input(asio::detail::socket_type *read_pipe,
+ const void *input, const size_t length);
pid_t
-check_output(int *write_pipe, const void *output, const size_t length);
+check_output(asio::detail::socket_type *write_pipe,
+ const void *output, const size_t length);
} // End of the namespace
}
diff --git a/src/lib/util/unittests/mock_socketsession.h b/src/lib/util/unittests/mock_socketsession.h
index 8078265..773d954 100644
--- a/src/lib/util/unittests/mock_socketsession.h
+++ b/src/lib/util/unittests/mock_socketsession.h
@@ -24,9 +24,12 @@
#include <cstring>
#include <vector>
-#include <sys/socket.h>
#include <stdint.h>
+#include <asio.hpp>
+
+using namespace asio::detail;
+
namespace isc {
namespace util {
namespace unittests {
@@ -66,7 +69,7 @@ public:
// so that the test code can check the values later via the getter
// methods. Complete deep copy will be created, so the caller doesn't
// have to keep the parameters valid after the call to this method.
- virtual void push(int sock, int family, int type, int protocol,
+ virtual void push(socket_type sock, int family, int type, int protocol,
const struct sockaddr& local_end,
const struct sockaddr& remote_end,
const void* data, size_t data_len)
@@ -116,7 +119,7 @@ public:
// sense; it was originally filled with the binary image of another
// sockaddr structure, and we are going to return the image opaquely
// as a sockaddr structure without touching the data.
- int getPushedSock() const { return (pushed_sock_); }
+ socket_type getPushedSock() const { return (pushed_sock_); }
int getPushedFamily() const { return (pushed_family_); }
int getPushedType() const { return (pushed_type_); }
int getPushedProtocol() const { return (pushed_protocol_); }
@@ -135,7 +138,7 @@ private:
bool connect_ok_;
bool push_ok_;
bool close_ok_;
- int pushed_sock_;
+ socket_type pushed_sock_;
int pushed_family_;
int pushed_type_;
int pushed_protocol_;
diff --git a/src/lib/xfr/xfrout_client.cc b/src/lib/xfr/xfrout_client.cc
index af0c1b5..77b8fd4 100644
--- a/src/lib/xfr/xfrout_client.cc
+++ b/src/lib/xfr/xfrout_client.cc
@@ -20,7 +20,7 @@
#include <unistd.h>
#include <asio.hpp>
-#include <util/io/fd_share.h>
+#include <util/io/socket_share.h>
#include <xfr/xfrout_client.h>
using namespace std;
@@ -70,11 +70,11 @@ XfroutClient::disconnect() {
}
int
-XfroutClient::sendXfroutRequestInfo(const int tcp_sock,
+XfroutClient::sendXfroutRequestInfo(const socket_type tcp_sock,
const void* const msg_data,
const uint16_t msg_len)
{
- if (send_fd(impl_->socket_.native(), tcp_sock) < 0) {
+ if (send_socket(impl_->socket_.native(), tcp_sock) < 0) {
isc_throw(XfroutError,
"Failed to send the socket file descriptor "
"to xfrout module");
diff --git a/src/lib/xfr/xfrout_client.h b/src/lib/xfr/xfrout_client.h
index bad963c..2852ff3 100644
--- a/src/lib/xfr/xfrout_client.h
+++ b/src/lib/xfr/xfrout_client.h
@@ -19,6 +19,8 @@
#include <string>
+#include <asio.hpp>
+
#include <exceptions/exceptions.h>
namespace isc {
@@ -60,7 +62,8 @@ public:
//@}
virtual void connect() = 0;
virtual void disconnect() = 0;
- virtual int sendXfroutRequestInfo(int tcp_sock, const void* msg_data,
+ virtual int sendXfroutRequestInfo(asio::detail::socket_type tcp_sock,
+ const void* msg_data,
uint16_t msg_len) = 0;
};
@@ -75,7 +78,8 @@ private:
public:
virtual void connect();
virtual void disconnect();
- virtual int sendXfroutRequestInfo(int tcp_sock, const void* msg_data,
+ virtual int sendXfroutRequestInfo(asio::detail::socket_type tcp_sock,
+ const void* msg_data,
uint16_t msg_len);
private:
XfroutClientImpl* impl_;
More information about the bind10-changes
mailing list