summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomek Mrugalski <tomek@isc.org>2024-04-18 13:39:36 +0200
committerTomek Mrugalski <tomek@isc.org>2024-04-23 17:42:20 +0200
commit4577c80bd1ff243032a6542353468d30c08a9f0b (patch)
tree18c5d635d1c075c6e88e2f2b85cdd64bd5abe251
parent[#3347] Updated ChangeLog (diff)
downloadkea-4577c80bd1ff243032a6542353468d30c08a9f0b.tar.xz
kea-4577c80bd1ff243032a6542353468d30c08a9f0b.zip
[#3321] legacy code removed
-rw-r--r--doc/devel/mainpage.dox1
-rw-r--r--src/lib/util/Makefile.am5
-rw-r--r--src/lib/util/io/Makefile.am4
-rw-r--r--src/lib/util/io/fd_share.cc166
-rw-r--r--src/lib/util/io/fd_share.h57
-rw-r--r--src/lib/util/io/socketsession.cc439
-rw-r--r--src/lib/util/io/socketsession.h491
-rw-r--r--src/lib/util/tests/Makefile.am1
-rw-r--r--src/lib/util/tests/fd_share_tests.cc72
-rw-r--r--src/lib/util/unittests/Makefile.am3
-rw-r--r--src/lib/util/unittests/mock_socketsession.h148
11 files changed, 3 insertions, 1384 deletions
diff --git a/doc/devel/mainpage.dox b/doc/devel/mainpage.dox
index 5151e15980..e15b8a590a 100644
--- a/doc/devel/mainpage.dox
+++ b/doc/devel/mainpage.dox
@@ -151,7 +151,6 @@
* - @subpage logDeveloperUse
* - @subpage logNotes
* - @subpage LoggingApi
- * - @subpage SocketSessionUtility
* - @subpage crossCompile
* - @subpage debug
* - @subpage docs
diff --git a/src/lib/util/Makefile.am b/src/lib/util/Makefile.am
index de3104ae86..526cac331e 100644
--- a/src/lib/util/Makefile.am
+++ b/src/lib/util/Makefile.am
@@ -92,8 +92,5 @@ libkea_util_encode_include_HEADERS = \
libkea_util_io_includedir = $(pkgincludedir)/util/io
libkea_util_io_include_HEADERS = \
- io/fd.h \
- io/fd_share.h \
io/pktinfo_utilities.h \
- io/sockaddr_util.h \
- io/socketsession.h
+ io/sockaddr_util.h
diff --git a/src/lib/util/io/Makefile.am b/src/lib/util/io/Makefile.am
index b5659b9218..9756d9d60e 100644
--- a/src/lib/util/io/Makefile.am
+++ b/src/lib/util/io/Makefile.am
@@ -5,8 +5,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
lib_LTLIBRARIES = libkea-util-io.la
-libkea_util_io_la_SOURCES = fd.h fd.cc fd_share.h fd_share.cc
-libkea_util_io_la_SOURCES += socketsession.h socketsession.cc sockaddr_util.h
+libkea_util_io_la_SOURCES = fd.h fd.cc
+libkea_util_io_la_SOURCES += sockaddr_util.h
libkea_util_io_la_SOURCES += pktinfo_utilities.h
libkea_util_io_la_LIBADD = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
libkea_util_io_la_LDFLAGS = -no-undefined -version-info 0:1:0
diff --git a/src/lib/util/io/fd_share.cc b/src/lib/util/io/fd_share.cc
deleted file mode 100644
index 7ab265953a..0000000000
--- a/src/lib/util/io/fd_share.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright (C) 2010-2019 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <config.h>
-
-#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 <util/io/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) {
-// Some systems (e.g. recent NetBSD) converted all CMSG access macros
-// to static_cast when used in C++ code. As cmsg is declared const
-// this makes the CMSG_DATA macro to not compile. But fortunately
-// these systems provide a const alternative named CCMSG_DATA.
-#ifdef CCMSG_DATA
- std::memcpy(&fd, CCMSG_DATA(cmsg), sizeof(int));
-#else
- std::memcpy(&fd, CMSG_DATA(cmsg), sizeof(int));
-#endif
- }
- free(msghdr.msg_control);
- int new_fd = -1;
- int close_error = -1;
- if (fd >= 0) {
- // 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.
- new_fd = dup(fd);
- 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);
- }
- std::memset(msghdr.msg_control, 0, msghdr.msg_controllen);
-
- 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);
-}
-
-} // namespace io
-} // namespace util
-} // 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 600606f820..0000000000
--- a/src/lib/util/io/fd_share.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#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);
-
-} // namespace io
-} // namespace util
-} // namespace isc
-
-#endif // FD_SHARE_H
diff --git a/src/lib/util/io/socketsession.cc b/src/lib/util/io/socketsession.cc
deleted file mode 100644
index db93820a4f..0000000000
--- a/src/lib/util/io/socketsession.cc
+++ /dev/null
@@ -1,439 +0,0 @@
-// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <config.h>
-
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/un.h>
-
-#include <netinet/in.h>
-
-#include <fcntl.h>
-#include <stdint.h>
-
-#include <cerrno>
-#include <csignal>
-#include <cstddef>
-#include <cstring>
-
-#include <string>
-#include <vector>
-
-#include <boost/noncopyable.hpp>
-
-#include <exceptions/exceptions.h>
-#include <exceptions/isc_assert.h>
-
-#include <util/buffer.h>
-
-#include <util/io/fd_share.h>
-#include <util/io/socketsession.h>
-#include <util/io/sockaddr_util.h>
-
-using namespace std;
-
-namespace isc {
-namespace util {
-namespace io {
-
-using namespace internal;
-
-// The expected max size of the session header: 2-byte header length,
-// 6 32-bit fields, and 2 sockaddr structure. (see the SocketSessionUtility
-// overview description in the header file). sizeof sockaddr_storage
-// should be the possible max of any sockaddr structure
-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
-// 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.
-const int MAX_DATASIZE = 65535;
-
-// The initial buffer size for receiving socket session data in the receiver.
-// This value is the maximum message size of DNS messages carried over UDP
-// (without EDNS). In our expected usage (at the moment) this should be
-// sufficiently large (the expected data is AXFR/IXFR query or an UPDATE
-// requests. The former should be generally quite small. While the latter
-// could be large, it would often be small enough for a single UDP message).
-// If it turns out that there are many exceptions, we may want to extend
-// the class so that this value can be customized. Note that the buffer
-// will be automatically extended for longer data and this is only about
-// efficiency.
-const size_t INITIAL_BUFSIZE = 512;
-
-// The (default) socket buffer size for the forwarder and receiver. This is
-// chosen to be sufficiently large to store two full-size DNS messages. We
-// may want to customize this value in future.
-const int SOCKSESSION_BUFSIZE = (DEFAULT_HEADER_BUFLEN + MAX_DATASIZE) * 2;
-
-struct SocketSessionForwarder::ForwarderImpl {
- ForwarderImpl() : sock_un_len_(0), fd_(-1), buf_(DEFAULT_HEADER_BUFLEN) {
- memset(&sock_un_, 0, sizeof(sock_un_));
- }
-
- struct sockaddr_un sock_un_;
- socklen_t sock_un_len_;
- int fd_;
- OutputBuffer buf_;
-};
-
-SocketSessionForwarder::SocketSessionForwarder(const std::string& unix_file) :
- impl_(NULL)
-{
- // We need to filter SIGPIPE for subsequent push(). See the class
- // description.
- if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
- isc_throw(Unexpected, "Failed to filter SIGPIPE: " << strerror(errno));
- }
-
- ForwarderImpl impl;
- if (sizeof(impl.sock_un_.sun_path) - 1 < unix_file.length()) {
- isc_throw(SocketSessionError,
- "File name for a UNIX domain socket is too long: " <<
- unix_file);
- }
- impl.sock_un_.sun_family = AF_UNIX;
- // the copy should be safe due to the above check, but we'd be rather
- // paranoid about making it 100% sure even if the check has a bug (with
- // triggering the assertion in the worse case)
- memset(&impl.sock_un_.sun_path, 0, sizeof(impl.sock_un_.sun_path));
- strncpy(impl.sock_un_.sun_path, unix_file.c_str(),
- sizeof(impl.sock_un_.sun_path) - 1);
- isc_throw_assert(impl.sock_un_.sun_path[sizeof(impl.sock_un_.sun_path) - 1] == '\0');
- impl.sock_un_len_ = offsetof(struct sockaddr_un, sun_path) +
- unix_file.length();
-#ifdef HAVE_SA_LEN
- impl.sock_un_.sun_len = impl.sock_un_len_;
-#endif
- impl.fd_ = -1;
-
- impl_ = new ForwarderImpl;
- *impl_ = impl;
-}
-
-SocketSessionForwarder::~SocketSessionForwarder() {
- if (impl_->fd_ != -1) {
- close();
- }
- delete impl_;
-}
-
-void
-SocketSessionForwarder::connectToReceiver() {
- if (impl_->fd_ != -1) {
- 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) {
- 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);
- if (fcntl_flags != -1) {
- fcntl_flags |= O_NONBLOCK;
- fcntl_flags = fcntl(impl_->fd_, F_SETFL, fcntl_flags);
- }
- if (fcntl_flags == -1) {
- close(); // note: this is the internal method, not ::close()
- isc_throw(SocketSessionError,
- "Failed to make UNIX domain socket non blocking: " <<
- strerror(errno));
- }
- // Ensure the socket send buffer is large enough. If we can't get the
- // 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,
- &sndbuf_size_len) == -1 ||
- sndbuf_size < SOCKSESSION_BUFSIZE) {
- if (setsockopt(impl_->fd_, SOL_SOCKET, SO_SNDBUF, &SOCKSESSION_BUFSIZE,
- sizeof(SOCKSESSION_BUFSIZE)) == -1) {
- close();
- isc_throw(SocketSessionError,
- "Failed to set send buffer size to " <<
- SOCKSESSION_BUFSIZE);
- }
- }
- if (connect(impl_->fd_, convertSockAddr(&impl_->sock_un_),
- impl_->sock_un_len_) == -1) {
- close();
- isc_throw(SocketSessionError, "Failed to connect to UNIX domain "
- "endpoint " << impl_->sock_un_.sun_path << ": " <<
- strerror(errno));
- }
-}
-
-void
-SocketSessionForwarder::close() {
- if (impl_->fd_ == -1) {
- isc_throw(BadValue, "Attempt of close before connect");
- }
- ::close(impl_->fd_);
- impl_->fd_ = -1;
-}
-
-void
-SocketSessionForwarder::push(int 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) {
- isc_throw(BadValue, "Attempt of push before connect");
- }
- if ((local_end.sa_family != AF_INET && local_end.sa_family != AF_INET6) ||
- (remote_end.sa_family != AF_INET && remote_end.sa_family != AF_INET6))
- {
- isc_throw(BadValue, "Invalid address family: must be "
- "AF_INET or AF_INET6; " <<
- static_cast<int>(local_end.sa_family) << ", " <<
- static_cast<int>(remote_end.sa_family) << " given");
- }
- if (family != local_end.sa_family || family != remote_end.sa_family) {
- isc_throw(BadValue, "Inconsistent address family: must be "
- << static_cast<int>(family) << "; "
- << static_cast<int>(local_end.sa_family) << ", "
- << static_cast<int>(remote_end.sa_family) << " given");
- }
- if (data_len == 0 || data == NULL) {
- isc_throw(BadValue, "Data for a socket session must not be empty");
- }
- if (data_len > MAX_DATASIZE) {
- isc_throw(BadValue, "Invalid socket session data size: " <<
- data_len << ", must not exceed " << MAX_DATASIZE);
- }
-
- if (send_fd(impl_->fd_, sock) != 0) {
- isc_throw(SocketSessionError, "FD passing failed: " <<
- strerror(errno));
- }
-
- impl_->buf_.clear();
- // Leave the space for the header length
- impl_->buf_.skip(sizeof(uint16_t));
- // Socket properties: family, type, protocol
- impl_->buf_.writeUint32(static_cast<uint32_t>(family));
- impl_->buf_.writeUint32(static_cast<uint32_t>(type));
- impl_->buf_.writeUint32(static_cast<uint32_t>(protocol));
- // Local endpoint
- impl_->buf_.writeUint32(static_cast<uint32_t>(getSALength(local_end)));
- impl_->buf_.writeData(&local_end, getSALength(local_end));
- // Remote endpoint
- impl_->buf_.writeUint32(static_cast<uint32_t>(getSALength(remote_end)));
- impl_->buf_.writeData(&remote_end, getSALength(remote_end));
- // Data length. Must be fit uint32 due to the range check above.
- const uint32_t data_len32 = static_cast<uint32_t>(data_len);
- isc_throw_assert(data_len == data_len32); // shouldn't cause overflow.
- impl_->buf_.writeUint32(data_len32);
- // Write the resulting header length at the beginning of the buffer
- impl_->buf_.writeUint16At(impl_->buf_.getLength() - sizeof(uint16_t), 0);
-
- const struct iovec iov[2] = {
- { const_cast<void*>(impl_->buf_.getDataAsVoidPtr()),
- impl_->buf_.getLength() },
- { const_cast<void*>(data), data_len }
- };
- const int cc = writev(impl_->fd_, iov, 2);
- if (cc != impl_->buf_.getLength() + data_len) {
- if (cc < 0) {
- isc_throw(SocketSessionError,
- "Write failed in forwarding a socket session: " <<
- strerror(errno));
- }
- isc_throw(SocketSessionError,
- "Incomplete write in forwarding a socket session: " << cc <<
- "/" << (impl_->buf_.getLength() + data_len));
- }
-}
-
-SocketSession::SocketSession(int sock, int family, int type, int protocol,
- const sockaddr* local_end,
- const sockaddr* remote_end,
- const void* data, size_t data_len) :
- sock_(sock), family_(family), type_(type), protocol_(protocol),
- local_end_(local_end), remote_end_(remote_end),
- data_(data), data_len_(data_len)
-{
- if (local_end == NULL || remote_end == NULL) {
- isc_throw(BadValue, "sockaddr must be non NULL for SocketSession");
- }
- if (data_len == 0) {
- isc_throw(BadValue, "data_len must be non 0 for SocketSession");
- }
- if (data == NULL) {
- isc_throw(BadValue, "data must be non NULL for SocketSession");
- }
-}
-
-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)
- {
- memset(&ss_local_, 0, sizeof(ss_local_));
- memset(&ss_remote_, 0, sizeof(ss_remote_));
-
- if (setsockopt(fd_, SOL_SOCKET, SO_RCVBUF, &SOCKSESSION_BUFSIZE,
- sizeof(SOCKSESSION_BUFSIZE)) == -1) {
- isc_throw(SocketSessionError,
- "Failed to set receive buffer size to " <<
- SOCKSESSION_BUFSIZE);
- }
- }
-
- const int fd_;
- struct sockaddr_storage ss_local_; // placeholder for local endpoint
- struct sockaddr* const sa_local_;
- struct sockaddr_storage ss_remote_; // placeholder for remote endpoint
- struct sockaddr* const sa_remote_;
-
- // placeholder for session header and data
- vector<uint8_t> header_buf_;
- vector<uint8_t> data_buf_;
-};
-
-SocketSessionReceiver::SocketSessionReceiver(int fd) :
- impl_(new ReceiverImpl(fd))
-{
-}
-
-SocketSessionReceiver::~SocketSessionReceiver() {
- delete impl_;
-}
-
-namespace {
-// A shortcut to throw common exception on failure of recv(2)
-void
-readFail(int actual_len, int expected_len) {
- if (expected_len < 0) {
- isc_throw(SocketSessionError, "Failed to receive data from "
- "SocketSessionForwarder: " << strerror(errno));
- }
- isc_throw(SocketSessionError, "Incomplete data from "
- "SocketSessionForwarder: " << actual_len << "/" <<
- expected_len);
-}
-
-// A helper container for a (socket) file descriptor used in
-// 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() {
- if (fd_ >= 0) {
- close(fd_);
- }
- }
- int release() {
- const int fd = fd_;
- fd_ = -1;
- return (fd);
- }
- int fd_;
-};
-}
-
-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");
- }
-
- uint16_t header_len;
- const int cc_hlen = recv(impl_->fd_, &header_len, sizeof(header_len),
- MSG_WAITALL);
- if (cc_hlen < sizeof(header_len)) {
- readFail(cc_hlen, sizeof(header_len));
- }
- header_len = InputBuffer(&header_len, sizeof(header_len)).readUint16();
- if (header_len > DEFAULT_HEADER_BUFLEN) {
- isc_throw(SocketSessionError, "Too large header length: " <<
- header_len);
- }
- impl_->header_buf_.clear();
- impl_->header_buf_.resize(header_len);
- const int cc_hdr = recv(impl_->fd_, &impl_->header_buf_[0], header_len,
- MSG_WAITALL);
- if (cc_hdr < header_len) {
- readFail(cc_hdr, header_len);
- }
-
- InputBuffer ibuffer(&impl_->header_buf_[0], header_len);
- try {
- const int family = static_cast<int>(ibuffer.readUint32());
- if (family != AF_INET && family != AF_INET6) {
- isc_throw(SocketSessionError,
- "Unsupported address family is passed: " << family);
- }
- const int type = static_cast<int>(ibuffer.readUint32());
- const int protocol = static_cast<int>(ibuffer.readUint32());
- const socklen_t local_end_len = ibuffer.readUint32();
- const socklen_t endpoint_minlen = (family == AF_INET) ?
- sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
- if (local_end_len < endpoint_minlen ||
- local_end_len > sizeof(impl_->ss_local_)) {
- isc_throw(SocketSessionError, "Invalid local SA length: " <<
- local_end_len);
- }
- ibuffer.readData(&impl_->ss_local_, local_end_len);
- const socklen_t remote_end_len = ibuffer.readUint32();
- if (remote_end_len < endpoint_minlen ||
- remote_end_len > sizeof(impl_->ss_remote_)) {
- isc_throw(SocketSessionError, "Invalid remote SA length: " <<
- remote_end_len);
- }
- ibuffer.readData(&impl_->ss_remote_, remote_end_len);
- if (family != impl_->sa_local_->sa_family ||
- family != impl_->sa_remote_->sa_family) {
- isc_throw(SocketSessionError, "SA family inconsistent: " <<
- static_cast<int>(impl_->sa_local_->sa_family) << ", " <<
- static_cast<int>(impl_->sa_remote_->sa_family) <<
- " given, must be " << family);
- }
- const size_t data_len = ibuffer.readUint32();
- if (data_len == 0 || data_len > MAX_DATASIZE) {
- isc_throw(SocketSessionError,
- "Invalid socket session data size: " << data_len <<
- ", must be > 0 and <= " << MAX_DATASIZE);
- }
-
- impl_->data_buf_.clear();
- impl_->data_buf_.resize(data_len);
- const int cc_data = recv(impl_->fd_, &impl_->data_buf_[0], data_len,
- MSG_WAITALL);
- if (cc_data < data_len) {
- readFail(cc_data, data_len);
- }
-
- return (SocketSession(passed_sock.release(), family, type, protocol,
- impl_->sa_local_, impl_->sa_remote_,
- &impl_->data_buf_[0], data_len));
- } catch (const OutOfRange& ex) {
- // We catch the case where the given header is too short and convert
- // the exception to SocketSessionError.
- isc_throw(SocketSessionError, "bogus socket session header: " <<
- ex.what());
- }
-}
-
-}
-}
-}
diff --git a/src/lib/util/io/socketsession.h b/src/lib/util/io/socketsession.h
deleted file mode 100644
index 6c0fac74bd..0000000000
--- a/src/lib/util/io/socketsession.h
+++ /dev/null
@@ -1,491 +0,0 @@
-// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef SOCKETSESSION_H
-#define SOCKETSESSION_H 1
-
-#include <boost/noncopyable.hpp>
-
-#include <exceptions/exceptions.h>
-
-#include <string>
-
-#include <sys/socket.h>
-
-namespace isc {
-namespace util {
-namespace io {
-
-/// \page SocketSessionUtility Socket session utility
-///
-/// \note This class is currently unused. Once we get to the implementation
-/// of the remote parts of the management API, we will evaluate whether
-/// this code is useful or not and either start using it or remove it.
-///
-/// This utility defines a set of classes that support forwarding a
-/// "socket session" from one process to another. A socket session is a
-/// conceptual tuple of the following elements:
-/// - A network socket
-/// - The local and remote endpoints of a (IP) communication taking place on
-/// the socket. In practice an endpoint is a pair of an IP address and
-/// TCP or UDP port number.
-/// - Some amount of data sent from the remote endpoint and received on the
-/// socket. We call it (socket) session data in this documentation.
-///
-/// Note that this is a conceptual definition. Depending on the underlying
-/// implementation and/or the network protocol, some of the elements could be
-/// part of others; for example, if it's an established TCP connection,
-/// the local and remote endpoints would be able to be retrieved from the
-/// socket using the standard \c getsockname() and \c getpeername() system
-/// calls. But in this definition we separate these to be more generic.
-/// Also, as a matter of fact our intended usage includes non-connected UDP
-/// communications, in which case at least the remote endpoint should be
-/// 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 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.
-///
-/// We use the standard \c sockaddr structure to represent endpoints.
-///
-/// Socket session data is an opaque memory region of an arbitrary length
-/// (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
-/// 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.
-///
-/// We provide three classes to help applications forward socket sessions:
-/// \c SocketSessionForwarder is the sender of the UNIX domain connection,
-/// while \c SocketSessionReceiver is the receiver (this interface assumes
-/// one direction of forwarding); \c SocketSession represents a single
-/// socket session.
-///
-/// \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
-/// "(socket) session header", which contains all other elements of the session
-/// except the file 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
-/// - Socket type
-/// - Protocol
-/// - Size of the local endpoint in bytes
-/// - Local endpoint (a copy of the memory image of the corresponding
-/// \c sockaddr)
-/// - Size of the remote endpoint in bytes
-/// - Remote endpoint (same as local endpoint)
-/// - Size of session data in bytes
-///
-/// The type of the fields is 32-bit unsigned integer unless explicitly
-/// noted, and all fields are formatted in the network byte order.
-///
-/// The socket session data immediately follows the session header.
-///
-/// Note that the fields do not necessarily be in the network byte order
-/// because they are expected to be exchanged on the same machine. Likewise,
-/// integer elements such as address family do not necessarily be represented
-/// as an fixed-size value (i.e., 32-bit). But fixed size fields are used
-/// in order to ensure maximum portability in such a (rare) case where the
-/// forwarder and the receiver are built with different compilers that have
-/// different definitions of \c int. Also, since \c sockaddr fields are
-/// generally formatted in the network byte order, other fields are defined
-/// so to be consistent.
-///
-/// One basic assumption in the API of this utility is socket sessions should
-/// be forwarded without blocking, thus eliminating the need for incremental
-/// read/write or blocking other important services such as responding to
-/// requests from the application's clients. This assumption should be held
-/// as long as both the forwarder and receiver have sufficient resources
-/// to handle the forwarding process since the communication is local.
-/// But a forward attempt could still block if the receiver is busy (or even
-/// hang up) and cannot keep up with the volume of incoming sessions.
-///
-/// So, in this implementation, the forwarder uses non blocking writes to
-/// forward sessions. If a write attempt could block, it immediately gives
-/// up the operation with an exception. The corresponding application is
-/// expected to catch it, close the connection, and perform any necessary
-/// recovery for that application (that would normally be re-establish the
-/// connection with a new receiver, possibly after confirming the receiving
-/// side is still alive). On the other hand, the receiver implementation
-/// assumes it's possible that it only receive incomplete elements of a
-/// session (such as in the case where the forwarder writes part of the
-/// entire session and gives up the connection). The receiver implementation
-/// throws an exception when it encounters an incomplete session. Like the
-/// case of the forwarder application, the receiver application is expected
-/// to catch it, close the connection, and perform any necessary recovery
-/// steps.
-///
-/// Note that the receiver implementation uses blocking read. So it's
-/// application's responsibility to ensure that there's at least some data
-/// in the connection when the receiver object is requested to receive a
-/// session (unless this operation can be blocking, e.g., by the use of
-/// a separate thread). Also, if the forwarder implementation or application
-/// is malicious or extremely buggy and intentionally sends partial session
-/// and keeps the connection, the receiver could block in receiving a session.
-/// In general, we assume the forwarder doesn't do intentional blocking
-/// as it's a local node and is generally a module of the same (Kea)
-/// system. The minimum requirement for the forwarder implementation (and
-/// application) is to make sure the connection is closed once it detects
-/// an error on it. Even a naive implementation that simply dies due to
-/// the exception will meet this requirement.
-
-/// An exception indicating general errors that takes place in the
-/// socket session related class objects.
-///
-/// In general the errors are unusual but possible failures such as unexpected
-/// connection reset, and suggest the application to close the connection and
-/// (if necessary) reestablish it.
-class SocketSessionError: public Exception {
-public:
- SocketSessionError(const char *file, size_t line, const char *what):
- isc::Exception(file, line, what) {}
-};
-
-/// The "base" class of \c SocketSessionForwarder
-///
-/// This class defines abstract interfaces of the \c SocketSessionForwarder
-/// class. Although \c SocketSessionForwarder is not intended to be used in
-/// a polymorphic way, it's not easy to use in tests because it will require
-/// various low level network operations. So it would be useful if we
-/// provide a framework for defining a fake or mock version of it.
-/// An application that needs to use \c SocketSessionForwarder would actually
-/// refer to this base class, and tests for the application would define
-/// and use a fake version of the forwarder class.
-///
-/// Normal applications are not expected to define and use their own derived
-/// version of this base class, while it's not prohibited at the API level.
-///
-/// See description of \c SocketSessionForwarder for the expected interface.
-class BaseSocketSessionForwarder {
-protected:
- BaseSocketSessionForwarder() {}
-
-public:
- virtual ~BaseSocketSessionForwarder() {}
- virtual void connectToReceiver() = 0;
- virtual void close() = 0;
- virtual void push(int 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;
-};
-
-/// The forwarder of socket sessions
-///
-/// An object of this class maintains a UNIX domain socket (normally expected
-/// to be connected to a \c SocketSessionReceiver object) and forwards
-/// socket sessions to the receiver.
-///
-/// See the description of \ref SocketSessionUtility for other details of how
-/// the session forwarding works.
-class SocketSessionForwarder : boost::noncopyable,
- public BaseSocketSessionForwarder
-{
-public:
- /// The constructor.
- ///
- /// It's constructed with path information of the intended receiver,
- /// but does not immediately establish a connection to the receiver;
- /// \c connectToReceiver() must be called to establish it. These are
- /// separated so that an object of class can be initialized (possibly
- /// as an attribute of a higher level application class object) without
- /// knowing the receiver is ready for accepting new forwarders. The
- /// separate connect interface allows the object to be reused when it
- /// detects connection failure and tries to re-establish it after closing
- /// the failed one.
- ///
- /// On construction, it also installs a signal filter for SIGPIPE to
- /// ignore it. Since this class uses a stream-type connected UNIX domain
- /// socket, if the receiver (abruptly) closes the connection a subsequent
- /// write operation on the socket would trigger a SIGPIPE signal, which
- /// kills the caller process by default. This behavior would be
- /// undesirable in many cases, so this implementation always disables
- /// the signal.
- ///
- /// This approach has some drawbacks, however; first, since signal handling
- /// is process (or thread) wide, ignoring it may not what the application
- /// wants. On the other hand, if the application changes how the signal is
- /// handled after instantiating this class, the new behavior affects the
- /// class operation. Secondly, even if ignoring the signal is the desired
- /// operation, it's a waste to set the filter every time this class object
- /// is constructed. It's sufficient to do it once. We still adopt this
- /// behavior based on the observation that in most cases applications would
- /// like to ignore SIGPIPE (or simply doesn't care about it) and that this
- /// class is not instantiated so often (so the wasteful setting overhead
- /// should be marginal). On the other hand, doing it every time is
- /// beneficial if the application is threaded and different threads
- /// create different forwarder objects (and if signals work per thread).
- ///
- /// \exception SocketSessionError \c unix_file is invalid as a path name
- /// of a UNIX domain socket.
- /// \exception Unexpected Error in setting a filter for SIGPIPE (see above)
- /// \exception std::bad_alloc resource allocation failure
- ///
- /// \param unix_file Path name of the receiver.
- explicit SocketSessionForwarder(const std::string& unix_file);
-
- /// The destructor.
- ///
- /// If a connection has been established, it's automatically closed in
- /// the destructor.
- virtual ~SocketSessionForwarder();
-
- /// Establish a connection to the receiver.
- ///
- /// This method establishes a connection to the receiver at the path
- /// given on construction. It makes the underlying UNIX domain socket
- /// non blocking, so this method (or subsequent \c push() calls) does not
- /// block.
- ///
- /// \exception BadValue The method is called while an already
- /// established connection is still active.
- /// \exception SocketSessionError A system error in socket operation.
- virtual void connectToReceiver();
-
- /// Close the connection to the receiver.
- ///
- /// The connection must have been established by \c connectToReceiver().
- /// As long as it's met this method is exception free.
- ///
- /// \exception BadValue The connection hasn't been established.
- virtual void close();
-
- /// Forward a socket session to the receiver.
- ///
- /// This method takes a set of parameters that represent a single socket
- /// session, renders them in the "wire" format according to the internal
- /// protocol (see \ref SocketSessionUtility) and forwards them to
- /// the receiver through the UNIX domain connection.
- ///
- /// The connection must have been established by \c connectToReceiver().
- ///
- /// For simplicity and for the convenience of detecting application
- /// errors, this method imposes some restrictions on the parameters:
- /// - Socket family must be either \c AF_INET or \c AF_INET6
- /// - The address family (\c sa_family) member of the local and remote
- /// end points must be equal to the \c family parameter
- /// - Socket session data must not be empty (\c data_len must not be 0
- /// and \c data must not be NULL)
- /// - Data length must not exceed 65535
- /// These are not architectural limitation, and might be loosened in
- /// future versions as we see the need for flexibility.
- ///
- /// Since the underlying UNIX domain socket is non blocking
- /// (see the description for the constructor), a call to this method
- /// should either return immediately or result in exception (in case of
- /// "would block").
- ///
- /// \exception BadValue The method is called before establishing a
- /// connection or given parameters are invalid.
- /// \exception SocketSessionError A system error in socket operation,
- /// including the case where the write operation would block.
- ///
- /// \param sock The socket file 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
- /// socket
- /// \param local_end The local end point of the session in the form of
- /// \c sockaddr.
- /// \param remote_end The remote end point of the session in the form of
- /// \c sockaddr.
- /// \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,
- const struct sockaddr& local_end,
- const struct sockaddr& remote_end,
- const void* data, size_t data_len);
-
-private:
- struct ForwarderImpl;
- ForwarderImpl* impl_;
-};
-
-/// Socket session object.
-///
-/// The \c SocketSession class provides a convenient encapsulation
-/// for the notion of a socket session. It's instantiated with straightforward
-/// parameters corresponding to a socket session, and provides read only
-/// accessors to the parameters to ensure data integrity.
-///
-/// In the initial design and implementation it's only used as a return type
-/// of \c SocketSessionReceiver::pop(), but it could also be used by
-/// the \c SocketSessionForwarder class or for other purposes.
-///
-/// It is assumed that the original owner of a \c SocketSession object
-/// (e.g. a class or a function that constructs it) is responsible for validity
-/// of the data passed to the object. See the description of
-/// \c SocketSessionReceiver::pop() for the specific case of that usage.
-class SocketSession {
-public:
- /// The constructor.
- ///
- /// This is a trivial constructor, taking a straightforward representation
- /// of session parameters and storing them internally to ensure integrity.
- ///
- /// As long as the given parameters are valid it never throws an exception.
- ///
- /// \exception BadValue Given parameters don't meet the requirement
- /// (see the parameter descriptions).
- ///
- /// \param sock The socket file 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
- /// socket.
- /// \param local_end The local end point of the session in the form of
- /// \c sockaddr. Must not be NULL.
- /// \param remote_end The remote end point of the session in the form of
- /// \c sockaddr. Must not be NULL.
- /// \param data A pointer to the beginning of the memory region for the
- /// 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,
- 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 address family (such as AF_INET6) of the socket.
- int getFamily() const { return (family_); }
-
- /// Return the socket type (such as SOCK_DGRAM) of the socket.
- int getType() const { return (type_); }
-
- /// Return the transport protocol (such as IPPROTO_UDP) of the socket.
- int getProtocol() const { return (protocol_); }
-
- /// Return the local end point of the session in the form of \c sockaddr.
- const sockaddr& getLocalEndpoint() const { return (*local_end_); }
-
- /// Return the remote end point of the session in the form of \c sockaddr.
- const sockaddr& getRemoteEndpoint() const { return (*remote_end_); }
-
- /// Return a pointer to the beginning of the memory region for the session
- /// data.
- ///
- /// In the current implementation it should never be NULL, and the region
- /// of the size returned by \c getDataLength() is expected to be valid.
- const void* getData() const { return (data_); }
-
- /// Return the size of the session data in bytes.
- ///
- /// In the current implementation it should be always larger than 0.
- size_t getDataLength() const { return (data_len_); }
-
-private:
- const int sock_;
- const int family_;
- const int type_;
- const int protocol_;
- const sockaddr* local_end_;
- const sockaddr* remote_end_;
- const void* const data_;
- const size_t data_len_;
-};
-
-/// The receiver of socket sessions
-///
-/// An object of this class holds a UNIX domain socket for an
-/// <em>established connection</em>, receives socket sessions from
-/// the remote forwarder, and provides the session to the application
-/// in the form of a \c SocketSession object.
-///
-/// Note that this class is instantiated with an already connected socket;
-/// it's not a listening socket that is accepting connection requests from
-/// forwarders. It's application's responsibility to create the listening
-/// socket, listen on it and accept connections. Once the connection is
-/// established, the application would construct a \c SocketSessionReceiver
-/// object with the socket for the newly established connection.
-/// This behavior is based on the design decision that the application should
-/// decide when it performs (possibly) blocking operations (see \ref
-/// SocketSessionUtility for more details).
-///
-/// See the description of \ref SocketSessionUtility for other details of how
-/// the session forwarding works.
-class SocketSessionReceiver : boost::noncopyable {
-public:
- /// The constructor.
- ///
- /// \exception SocketSessionError Any error on an operation that is
- /// performed on the given socket as part of initialization.
- /// \exception std::bad_alloc Resource allocation failure
- ///
- /// \param fd A UNIX domain socket for an established connection with
- /// a forwarder.
- explicit SocketSessionReceiver(int fd);
-
- /// The destructor.
- ///
- /// The destructor does \c not close the socket given on construction.
- /// It's up to the application what to do with it (note that the
- /// application would have to maintain the socket itself for detecting
- /// the existence of a new socket session asynchronously).
- ~SocketSessionReceiver();
-
- /// Receive a socket session from the forwarder.
- ///
- /// This method receives wire-format data (see \ref SocketSessionUtility)
- /// for a socket session on the UNIX domain socket, performs some
- /// validation on the data, and returns the session information in the
- /// form of a \c SocketSession object.
- ///
- /// The returned SocketSession object is valid only until the next time
- /// this method is called or until the \c SocketSessionReceiver object is
- /// destroyed.
- ///
- /// The caller is responsible for closing the received socket (whose
- /// file 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
- /// socket session data (accessible via \c SocketSession::getData());
- /// the \c SocketSessionReceiver object will clean it up automatically.
- ///
- /// It ensures the following:
- /// - The address family is either \c AF_INET or \c AF_INET6
- /// - The address family (\c sa_family) member of the local and remote
- /// end points must be equal to the \c family parameter
- /// - The socket session data is not empty and does not exceed 65535
- /// bytes.
- /// If the validation fails or an unexpected system error happens
- /// (including a connection close in the meddle of reception), it throws
- /// an SocketSessionError exception. When this happens, it's very
- /// unlikely that a subsequent call to this method succeeds, so in reality
- /// the application is expected to destruct it and close the socket in
- /// such a case.
- ///
- /// \exception SocketSessionError Invalid data is received or a system
- /// error on socket operation happens.
- /// \exception std::bad_alloc Resource allocation failure
- ///
- /// \return A \c SocketSession object corresponding to the extracted
- /// socket session.
- SocketSession pop();
-
-private:
- struct ReceiverImpl;
- ReceiverImpl* impl_;
-};
-
-}
-}
-}
-
-#endif // SOCKETSESSION_H
diff --git a/src/lib/util/tests/Makefile.am b/src/lib/util/tests/Makefile.am
index 430c53db91..6dfe681ba5 100644
--- a/src/lib/util/tests/Makefile.am
+++ b/src/lib/util/tests/Makefile.am
@@ -29,7 +29,6 @@ run_unittests_SOURCES += csv_file_unittest.cc
run_unittests_SOURCES += dhcp_space_unittest.cc
run_unittests_SOURCES += doubles_unittest.cc
run_unittests_SOURCES += encode_unittest.cc
-run_unittests_SOURCES += fd_share_tests.cc
run_unittests_SOURCES += fd_tests.cc
run_unittests_SOURCES += filesystem_unittests.cc
run_unittests_SOURCES += hash_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 f870ec2329..0000000000
--- a/src/lib/util/tests/fd_share_tests.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <config.h>
-
-#include <util/io/fd.h>
-#include <util/io/fd_share.h>
-
-#include <util/unittests/check_valgrind.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) {
-
- if (!isc::util::unittests::runningOnValgrind()) {
- // Get a pipe and fork
- int pipes[2];
- ASSERT_NE(-1, socketpair(AF_UNIX, SOCK_STREAM, 0, pipes));
- const pid_t sender(fork());
- ASSERT_NE(-1, sender);
- if (sender) { // We are in parent
- // Close the other side of pipe, we want only writable one
- EXPECT_NE(-1, close(pipes[0]));
- // Get a process to check data
- int fd(0);
- const 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
- const int fd(recv_fd(pipes[0]));
- if (fd == -1) {
- exit(1);
- }
- // This pipe is not needed
- if (close(pipes[0])) {
- exit(1);
- }
- // Send "data" through 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/unittests/Makefile.am b/src/lib/util/unittests/Makefile.am
index bd02a5139e..494ceae3ef 100644
--- a/src/lib/util/unittests/Makefile.am
+++ b/src/lib/util/unittests/Makefile.am
@@ -22,7 +22,4 @@ libutil_unittests_la_LIBADD += $(top_builddir)/src/lib/exceptions/libkea-excepti
libutil_unittests_la_LIBADD += $(GTEST_LDADD)
endif
-# For now, this isn't needed for libutil_unittests
-EXTRA_DIST = mock_socketsession.h
-
CLEANFILES = *.gcno *.gcda
diff --git a/src/lib/util/unittests/mock_socketsession.h b/src/lib/util/unittests/mock_socketsession.h
deleted file mode 100644
index 2fc2bb2d3b..0000000000
--- a/src/lib/util/unittests/mock_socketsession.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef UTIL_UNITTESTS_MOCKSOCKETSESSION_H
-#define UTIL_UNITTESTS_MOCKSOCKETSESSION_H 1
-
-#include <exceptions/exceptions.h>
-
-#include <util/io/socketsession.h>
-#include <util/io/sockaddr_util.h>
-
-#include <cassert>
-#include <cstring>
-#include <vector>
-
-#include <sys/socket.h>
-#include <stdint.h>
-
-namespace isc {
-namespace util {
-namespace unittests {
-
-/// \brief Mock socket session forwarder.
-///
-/// It emulates the behavior of SocketSessionForwarder without involving
-/// network communication, and allowing the tester to customize the behavior
-/// and to examine forwarded data afterwards.
-class MockSocketSessionForwarder :
- public isc::util::io::BaseSocketSessionForwarder
-{
-public:
- MockSocketSessionForwarder() :
- is_connected_(false), connect_ok_(true), push_ok_(true),
- close_ok_(true),
- // These are not used until set, but we set them anyway here,
- // partly to silence cppcheck, and partly to be cleaner. Put some
- // invalid values in.
- pushed_sock_(-1), pushed_family_(-1), pushed_type_(-1),
- pushed_protocol_(-1)
- {}
-
- virtual void connectToReceiver() {
- if (!connect_ok_) {
- isc_throw(isc::util::io::SocketSessionError, "socket session "
- "forwarding connection disabled for test");
- }
- if (is_connected_) {
- isc_throw(isc::util::io::SocketSessionError, "duplicate connect");
- }
- is_connected_ = true;
- }
- virtual void close() {
- if (!is_connected_) {
- isc_throw(isc::util::io::SocketSessionError, "duplicate close");
- }
- is_connected_ = false;
- }
-
- // Pushing a socket session. It copies the given session data
- // 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,
- const struct sockaddr& local_end,
- const struct sockaddr& remote_end,
- const void* data, size_t data_len)
- {
- if (!push_ok_) {
- isc_throw(isc::util::io::SocketSessionError,
- "socket session forwarding is disabled for test");
- }
- if (!is_connected_) {
- isc_throw(isc::util::io::SocketSessionError,
- "socket session is being pushed before connected");
- }
-
- // Copy parameters for later checks
- pushed_sock_ = sock;
- pushed_family_ = family;
- pushed_type_ = type;
- pushed_protocol_ = protocol;
- assert(io::internal::getSALength(local_end) <=
- sizeof(pushed_local_end_ss_));
- std::memcpy(&pushed_local_end_ss_, &local_end,
- io::internal::getSALength(local_end));
- assert(io::internal::getSALength(remote_end) <=
- sizeof(pushed_remote_end_ss_));
- std::memcpy(&pushed_remote_end_ss_, &remote_end,
- io::internal::getSALength(remote_end));
- pushed_data_.resize(data_len);
- std::memcpy(&pushed_data_[0], data, data_len);
- }
-
- // Allow the test code to check if the connection is established.
- bool isConnected() const { return (is_connected_); }
-
- // Allow the test code to customize the forwarder behavior wrt whether
- // a specific operation should succeed or fail.
- void disableConnect() { connect_ok_ = false; }
- void enableConnect() { connect_ok_ = true; }
- void disableClose() { close_ok_ = false; }
- void disablePush() { push_ok_ = false; }
- void enablePush() { push_ok_ = true; }
-
- // Read-only accessors to recorded parameters to the previous successful
- // call to push(). Return values are undefined if there has been no
- // successful call to push().
- // Note that we use convertSockAddr() to convert sockaddr_storage to
- // sockaddr. It should be safe since we use the storage in its literal
- // 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_); }
- int getPushedFamily() const { return (pushed_family_); }
- int getPushedType() const { return (pushed_type_); }
- int getPushedProtocol() const { return (pushed_protocol_); }
- const struct sockaddr& getPushedLocalend() const {
- return (*io::internal::convertSockAddr(&pushed_local_end_ss_));
- }
- const struct sockaddr& getPushedRemoteend() const {
- return (*io::internal::convertSockAddr(&pushed_remote_end_ss_));
- }
- const std::vector<uint8_t>& getPushedData() const {
- return (pushed_data_);
- }
-
-private:
- bool is_connected_;
- bool connect_ok_;
- bool push_ok_;
- bool close_ok_;
- int pushed_sock_;
- int pushed_family_;
- int pushed_type_;
- int pushed_protocol_;
- struct sockaddr_storage pushed_local_end_ss_;
- struct sockaddr_storage pushed_remote_end_ss_;
- std::vector<uint8_t> pushed_data_;
-};
-
-} // end of unittests
-} // end of util
-} // end of isc
-#endif // UTIL_UNITTESTS_MOCKSOCKETSESSION_H
-