BIND 10 master, updated. c21653aa339f403136a96c06a127b1796c203d78 [master] Compilation fix after 3315 merge.
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Feb 4 17:34:26 UTC 2014
The branch, master has been updated
via c21653aa339f403136a96c06a127b1796c203d78 (commit)
via 7686ac9a3e309f9cbd179a897cae845f16cc3478 (commit)
via fba33a4f336010b0af70ba5c194d8850adf82485 (commit)
via 8d6bd774155061530c7c6cd0029332b0d35fe1ce (commit)
via d17da3a2be2c2649652b4dd0ae5d3d11ba9cc21b (commit)
via 22d124644f6fc0480295c4d02104687965afd24b (commit)
via 3b47e007ac82dcc63c6f99b344211ca4661a8471 (commit)
from 5ff46cb07dfa9f6b373ea9466d7675efa320d926 (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 c21653aa339f403136a96c06a127b1796c203d78
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Tue Feb 4 18:33:54 2014 +0100
[master] Compilation fix after 3315 merge.
commit 7686ac9a3e309f9cbd179a897cae845f16cc3478
Merge: 5ff46cb fba33a4
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Tue Feb 4 15:17:17 2014 +0100
Merge branch 'trac3315'
-----------------------------------------------------------------------
Summary of changes:
src/bin/dhcp4/ctrl_dhcp4_srv.cc | 9 +-
src/bin/dhcp6/ctrl_dhcp6_srv.cc | 11 +-
src/lib/dhcp/iface_mgr.cc | 118 +++++++----
src/lib/dhcp/iface_mgr.h | 43 ++--
src/lib/dhcp/iface_mgr_bsd.cc | 2 +-
src/lib/dhcp/iface_mgr_linux.cc | 2 +-
src/lib/dhcp/iface_mgr_sun.cc | 2 +-
src/lib/dhcp/tests/iface_mgr_unittest.cc | 313 +++++++++++++++++++++++++++++-
8 files changed, 427 insertions(+), 73 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
index 43c08c9..72e0b21 100644
--- a/src/bin/dhcp4/ctrl_dhcp4_srv.cc
+++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
@@ -226,7 +226,7 @@ void ControlledDhcpv4Srv::establishSession() {
int ctrl_socket = cc_session_->getSocketDesc();
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_CCSESSION_STARTED)
.arg(ctrl_socket);
- IfaceMgr::instance().set_session_socket(ctrl_socket, sessionReader);
+ IfaceMgr::instance().addExternalSocket(ctrl_socket, sessionReader);
}
void ControlledDhcpv4Srv::disconnectSession() {
@@ -235,13 +235,14 @@ void ControlledDhcpv4Srv::disconnectSession() {
config_session_ = NULL;
}
if (cc_session_) {
+
+ int ctrl_socket = cc_session_->getSocketDesc();
cc_session_->disconnect();
+
+ IfaceMgr::instance().deleteExternalSocket(ctrl_socket);
delete cc_session_;
cc_session_ = NULL;
}
-
- // deregister session socket
- IfaceMgr::instance().set_session_socket(IfaceMgr::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 e42c83b..43497cd 100644
--- a/src/bin/dhcp6/ctrl_dhcp6_srv.cc
+++ b/src/bin/dhcp6/ctrl_dhcp6_srv.cc
@@ -227,7 +227,7 @@ void ControlledDhcpv6Srv::establishSession() {
int ctrl_socket = cc_session_->getSocketDesc();
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_CCSESSION_STARTED)
.arg(ctrl_socket);
- IfaceMgr::instance().set_session_socket(ctrl_socket, sessionReader);
+ IfaceMgr::instance().addExternalSocket(ctrl_socket, sessionReader);
}
void ControlledDhcpv6Srv::disconnectSession() {
@@ -236,13 +236,16 @@ void ControlledDhcpv6Srv::disconnectSession() {
config_session_ = NULL;
}
if (cc_session_) {
+
+ int ctrl_socket = cc_session_->getSocketDesc();
cc_session_->disconnect();
+
+ // deregister session socket
+ IfaceMgr::instance().deleteExternalSocket(ctrl_socket);
+
delete cc_session_;
cc_session_ = NULL;
}
-
- // deregister session socket
- IfaceMgr::instance().set_session_socket(IfaceMgr::INVALID_SOCKET, NULL);
}
ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t port)
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index 9338006..6a59124 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -170,7 +170,6 @@ bool Iface::delSocket(const 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),
packet_filter_(new PktFilterInet()),
packet_filter6_(new PktFilterInet6())
{
@@ -228,6 +227,37 @@ IfaceMgr::isDirectResponseSupported() const {
}
void
+IfaceMgr::addExternalSocket(int socketfd, SocketCallback callback) {
+ for (SocketCallbackInfoContainer::iterator s = callbacks_.begin();
+ s != callbacks_.end(); ++s) {
+
+ // There's such a socket description there already.
+ // Update the callback and we're done
+ if (s->socket_ == socketfd) {
+ s->callback_ = callback;
+ return;
+ }
+ }
+
+ // Add a new entry to the callbacks vector
+ SocketCallbackInfo x;
+ x.socket_ = socketfd;
+ x.callback_ = callback;
+ callbacks_.push_back(x);
+}
+
+void
+IfaceMgr::deleteExternalSocket(int socketfd) {
+ for (SocketCallbackInfoContainer::iterator s = callbacks_.begin();
+ s != callbacks_.end(); ++s) {
+ if (s->socket_ == socketfd) {
+ callbacks_.erase(s);
+ return;
+ }
+ }
+}
+
+void
IfaceMgr::setPacketFilter(const PktFilterPtr& packet_filter) {
// Do not allow NULL pointer.
if (!packet_filter) {
@@ -789,7 +819,6 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
IfaceCollection::const_iterator iface;
fd_set sockets;
int maxfd = 0;
- stringstream names;
FD_ZERO(&sockets);
@@ -804,7 +833,6 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
// Only deal with IPv4 addresses.
if (s->addr_.isV4()) {
- names << s->sockfd_ << "(" << iface->getName() << ") ";
// Add this socket to listening set
FD_SET(s->sockfd_, &sockets);
@@ -815,13 +843,15 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
}
}
- // if there is session socket registered...
- if (session_socket_ != INVALID_SOCKET) {
- // at it to the set as well
- FD_SET(session_socket_, &sockets);
- if (maxfd < session_socket_)
- maxfd = session_socket_;
- names << session_socket_ << "(session)";
+ // if there are any callbacks for external sockets registered...
+ if (!callbacks_.empty()) {
+ for (SocketCallbackInfoContainer::const_iterator s = callbacks_.begin();
+ s != callbacks_.end(); ++s) {
+ FD_SET(s->socket_, &sockets);
+ if (maxfd < s->socket_) {
+ maxfd = s->socket_;
+ }
+ }
}
struct timeval select_timeout;
@@ -838,18 +868,22 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
}
// Let's find out which socket has the data
- if ((session_socket_ != INVALID_SOCKET) && (FD_ISSET(session_socket_, &sockets))) {
- // something received over session socket
- if (session_callback_) {
- // in theory we could call io_service.run_one() here, instead of
- // implementing callback mechanism, but that would introduce
- // asiolink dependency to libdhcp++ and that is something we want
- // to avoid (see CPE market and out long term plans for minimalistic
- // implementations.
- session_callback_();
+ for (SocketCallbackInfoContainer::iterator s = callbacks_.begin();
+ s != callbacks_.end(); ++s) {
+ if (!FD_ISSET(s->socket_, &sockets)) {
+ continue;
}
- return (Pkt4Ptr()); // NULL
+ // something received over external socket
+
+ // Calling the external socket's callback provides its service
+ // layer access without integrating any specific features
+ // in IfaceMgr
+ if (s->callback_) {
+ s->callback_();
+ }
+
+ return (Pkt4Ptr());
}
// Let's find out which interface/socket has the data
@@ -886,7 +920,6 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
const SocketInfo* candidate = 0;
fd_set sockets;
int maxfd = 0;
- stringstream names;
FD_ZERO(&sockets);
@@ -901,7 +934,6 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
// Only deal with IPv6 addresses.
if (s->addr_.isV6()) {
- names << s->sockfd_ << "(" << iface->getName() << ") ";
// Add this socket to listening set
FD_SET(s->sockfd_, &sockets);
@@ -912,13 +944,17 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
}
}
- // if there is session socket registered...
- if (session_socket_ != INVALID_SOCKET) {
- // at it to the set as well
- FD_SET(session_socket_, &sockets);
- if (maxfd < session_socket_)
- maxfd = session_socket_;
- names << session_socket_ << "(session)";
+ // if there are any callbacks for external sockets registered...
+ if (!callbacks_.empty()) {
+ for (SocketCallbackInfoContainer::const_iterator s = callbacks_.begin();
+ s != callbacks_.end(); ++s) {
+
+ // Add it to the set as well
+ FD_SET(s->socket_, &sockets);
+ if (maxfd < s->socket_) {
+ maxfd = s->socket_;
+ }
+ }
}
struct timeval select_timeout;
@@ -935,18 +971,22 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
}
// Let's find out which socket has the data
- if ((session_socket_ != INVALID_SOCKET) && (FD_ISSET(session_socket_, &sockets))) {
- // something received over session socket
- if (session_callback_) {
- // in theory we could call io_service.run_one() here, instead of
- // implementing callback mechanism, but that would introduce
- // asiolink dependency to libdhcp++ and that is something we want
- // to avoid (see CPE market and out long term plans for minimalistic
- // implementations.
- session_callback_();
+ for (SocketCallbackInfoContainer::iterator s = callbacks_.begin();
+ s != callbacks_.end(); ++s) {
+ if (!FD_ISSET(s->socket_, &sockets)) {
+ continue;
}
- return (Pkt6Ptr()); // NULL
+ // something received over external socket
+
+ // Calling the external socket's callback provides its service
+ // layer access without integrating any specific features
+ // in IfaceMgr
+ if (s->callback_) {
+ s->callback_();
+ }
+
+ return (Pkt6Ptr());
}
// Let's find out which interface/socket has the data
diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h
index 5a26c5d..12212c7 100644
--- a/src/lib/dhcp/iface_mgr.h
+++ b/src/lib/dhcp/iface_mgr.h
@@ -394,8 +394,20 @@ boost::function<void(const std::string& errmsg)> IfaceMgrErrorMsgCallback;
///
class IfaceMgr : public boost::noncopyable {
public:
- /// Defines callback used when commands are received over control session.
- typedef void (*SessionCallback) (void);
+ /// Defines callback used when data is received over external sockets.
+ typedef boost::function<void ()> SocketCallback;
+
+ /// Keeps callback information for external sockets.
+ struct SocketCallbackInfo {
+ /// Socket descriptor of the external socket.
+ int socket_;
+
+ /// A callback that will be called when data arrives over socket_.
+ SocketCallback callback_;
+ };
+
+ /// Defines storage container for callbacks for external sockets
+ typedef std::list<SocketCallbackInfo> SocketCallbackInfoContainer;
/// @brief Packet reception buffer size
///
@@ -785,17 +797,18 @@ public:
/// @return number of detected interfaces
uint16_t countIfaces() { return ifaces_.size(); }
- /// @brief Sets session socket and a callback
+ /// @brief Adds external socket and a callback
///
- /// Specifies session socket and a callback that will be called
+ /// Specifies external socket and a callback that will be called
/// when data will be received over that socket.
///
/// @param socketfd socket descriptor
/// @param callback callback function
- void set_session_socket(int socketfd, SessionCallback callback) {
- session_socket_ = socketfd;
- session_callback_ = callback;
- }
+ void addExternalSocket(int socketfd, SocketCallback callback);
+
+ /// @brief Deletes external socket
+
+ void deleteExternalSocket(int socketfd);
/// @brief Set packet filter object to handle sending and receiving DHCPv4
/// messages.
@@ -881,9 +894,6 @@ public:
/// @return true if there is a socket bound to the specified address.
bool hasOpenSocket(const isc::asiolink::IOAddress& addr) const;
- /// 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:
@@ -977,13 +987,7 @@ protected:
/// @return true if successful, false otherwise
bool os_receive4(struct msghdr& m, Pkt4Ptr& pkt);
- /// Socket descriptor of the session socket.
- int session_socket_;
-
- /// A callback that will be called when data arrives over session_socket_.
- SessionCallback session_callback_;
private:
-
/// @brief Identifies local network address to be used to
/// connect to remote address.
///
@@ -1022,7 +1026,7 @@ private:
/// error occurs during opening a socket, or NULL if exception should
/// be thrown upon error.
bool openMulticastSocket(Iface& iface,
- const isc::asiolink::IOAddress addr,
+ const isc::asiolink::IOAddress& addr,
const uint16_t port,
IfaceMgrErrorMsgCallback error_handler = NULL);
@@ -1041,6 +1045,9 @@ private:
/// messages. It is possible to supply a custom object using
/// setPacketFilter method.
PktFilter6Ptr packet_filter6_;
+
+ /// @brief Contains list of callbacks for external sockets
+ SocketCallbackInfoContainer callbacks_;
};
}; // namespace isc::dhcp
diff --git a/src/lib/dhcp/iface_mgr_bsd.cc b/src/lib/dhcp/iface_mgr_bsd.cc
index cf6c3e2..7a01228 100644
--- a/src/lib/dhcp/iface_mgr_bsd.cc
+++ b/src/lib/dhcp/iface_mgr_bsd.cc
@@ -152,7 +152,7 @@ IfaceMgr::setMatchingPacketFilter(const bool /* direct_response_desired */) {
bool
IfaceMgr::openMulticastSocket(Iface& iface,
- const isc::asiolink::IOAddress addr,
+ const isc::asiolink::IOAddress& addr,
const uint16_t port,
IfaceMgrErrorMsgCallback error_handler) {
try {
diff --git a/src/lib/dhcp/iface_mgr_linux.cc b/src/lib/dhcp/iface_mgr_linux.cc
index eaa625e..f4b0613 100644
--- a/src/lib/dhcp/iface_mgr_linux.cc
+++ b/src/lib/dhcp/iface_mgr_linux.cc
@@ -536,7 +536,7 @@ bool IfaceMgr::os_receive4(struct msghdr&, Pkt4Ptr&) {
bool
IfaceMgr::openMulticastSocket(Iface& iface,
- const isc::asiolink::IOAddress addr,
+ const isc::asiolink::IOAddress& addr,
const uint16_t port,
IfaceMgrErrorMsgCallback error_handler) {
// This variable will hold a descriptor of the socket bound to
diff --git a/src/lib/dhcp/iface_mgr_sun.cc b/src/lib/dhcp/iface_mgr_sun.cc
index 0a9f9b4..a78de8f 100644
--- a/src/lib/dhcp/iface_mgr_sun.cc
+++ b/src/lib/dhcp/iface_mgr_sun.cc
@@ -156,7 +156,7 @@ IfaceMgr::setMatchingPacketFilter(const bool /* direct_response_desired */) {
bool
IfaceMgr::openMulticastSocket(Iface& iface,
- const isc::asiolink::IOAddress addr,
+ const isc::asiolink::IOAddress& addr,
const uint16_t port,
IfaceMgrErrorMsgCallback error_handler) {
try {
diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc
index dc5d85b..b95b4de 100644
--- a/src/lib/dhcp/tests/iface_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc
@@ -2590,15 +2590,19 @@ TEST_F(IfaceMgrTest, detectIfaces) {
}
volatile bool callback_ok;
+volatile bool callback2_ok;
void my_callback(void) {
- cout << "Callback triggered." << endl;
callback_ok = true;
}
-TEST_F(IfaceMgrTest, controlSession) {
- // Tests if extra control socket and its callback can be passed and
- // it is supported properly by receive4() method.
+void my_callback2(void) {
+ callback2_ok = true;
+}
+
+// Tests if a single external socket and its callback can be passed and
+// it is supported properly by receive4() method.
+TEST_F(IfaceMgrTest, SingleExternalSocket4) {
callback_ok = false;
@@ -2607,7 +2611,7 @@ TEST_F(IfaceMgrTest, controlSession) {
// Create pipe and register it as extra socket
int pipefd[2];
EXPECT_TRUE(pipe(pipefd) == 0);
- EXPECT_NO_THROW(ifacemgr->set_session_socket(pipefd[0], my_callback));
+ EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
Pkt4Ptr pkt4;
ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
@@ -2635,6 +2639,305 @@ TEST_F(IfaceMgrTest, controlSession) {
close(pipefd[0]);
}
+// Tests if multiple external sockets and their callbacks can be passed and
+// it is supported properly by receive4() method.
+TEST_F(IfaceMgrTest, MiltipleExternalSockets4) {
+
+ callback_ok = false;
+ callback2_ok = false;
+
+ scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
+
+ // Create first pipe and register it as extra socket
+ int pipefd[2];
+ EXPECT_TRUE(pipe(pipefd) == 0);
+ EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
+
+ // Let's create a second pipe and register it as well
+ int secondpipe[2];
+ EXPECT_TRUE(pipe(secondpipe) == 0);
+ EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));
+
+ Pkt4Ptr pkt4;
+ ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
+
+ // Our callbacks should not be called this time (there was no data)
+ EXPECT_FALSE(callback_ok);
+ EXPECT_FALSE(callback2_ok);
+
+ // IfaceMgr should not process control socket data as incoming packets
+ EXPECT_FALSE(pkt4);
+
+ // Now, send some data over the first pipe (38 bytes)
+ EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
+
+ // ... and repeat
+ ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
+
+ // IfaceMgr should not process control socket data as incoming packets
+ EXPECT_FALSE(pkt4);
+
+ // There was some data, so this time callback should be called
+ EXPECT_TRUE(callback_ok);
+ EXPECT_FALSE(callback2_ok);
+
+ // Read the data sent, because our test callbacks are too dumb to actually
+ // do it. We don't care about the content read, because we're testing
+ // the callbacks, not pipes.
+ char buf[80];
+ EXPECT_EQ(38, read(pipefd[0], buf, 80));
+
+ // Clear the status...
+ callback_ok = false;
+ callback2_ok = false;
+
+ // And try again, using the second pipe
+ EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));
+
+ // ... and repeat
+ ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
+
+ // IfaceMgr should not process control socket data as incoming packets
+ EXPECT_FALSE(pkt4);
+
+ // There was some data, so this time callback should be called
+ EXPECT_FALSE(callback_ok);
+ EXPECT_TRUE(callback2_ok);
+
+ // close both pipe ends
+ close(pipefd[1]);
+ close(pipefd[0]);
+
+ close(secondpipe[1]);
+ close(secondpipe[0]);
+}
+
+// Tests if existing external socket can be deleted and that such deletion does
+// not affect any other existing sockets. Tests uses receive4()
+TEST_F(IfaceMgrTest, DeleteExternalSockets4) {
+
+ callback_ok = false;
+ callback2_ok = false;
+
+ scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
+
+ // Create first pipe and register it as extra socket
+ int pipefd[2];
+ EXPECT_TRUE(pipe(pipefd) == 0);
+ EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
+
+ // Let's create a second pipe and register it as well
+ int secondpipe[2];
+ EXPECT_TRUE(pipe(secondpipe) == 0);
+ EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));
+
+ // Now delete the first session socket
+ EXPECT_NO_THROW(ifacemgr->deleteExternalSocket(pipefd[0]));
+
+ // Now check whether the second callback is still functional
+ EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));
+
+ // ... and repeat
+ Pkt4Ptr pkt4;
+ ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
+
+ // IfaceMgr should not process control socket data as incoming packets
+ EXPECT_FALSE(pkt4);
+
+ // There was some data, so this time callback should be called
+ EXPECT_FALSE(callback_ok);
+ EXPECT_TRUE(callback2_ok);
+
+ // Let's reset the status
+ callback_ok = false;
+ callback2_ok = false;
+
+ // Now let's send something over the first callback that was unregistered.
+ // We should NOT receive any callback.
+ EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
+
+ // Now check that the first callback is NOT called.
+ ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
+ EXPECT_FALSE(callback_ok);
+
+ // close both pipe ends
+ close(pipefd[1]);
+ close(pipefd[0]);
+
+ close(secondpipe[1]);
+ close(secondpipe[0]);
+}
+
+
+// Tests if a single external socket and its callback can be passed and
+// it is supported properly by receive6() method.
+TEST_F(IfaceMgrTest, SingleExternalSocket6) {
+
+ callback_ok = false;
+
+ scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
+
+ // Create pipe and register it as extra socket
+ int pipefd[2];
+ EXPECT_TRUE(pipe(pipefd) == 0);
+ EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
+
+ Pkt6Ptr pkt6;
+ ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
+
+ // Our callback should not be called this time (there was no data)
+ EXPECT_FALSE(callback_ok);
+
+ // IfaceMgr should not process control socket data as incoming packets
+ EXPECT_FALSE(pkt6);
+
+ // Now, send some data over pipe (38 bytes)
+ EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
+
+ // ... and repeat
+ ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
+
+ // IfaceMgr should not process control socket data as incoming packets
+ EXPECT_FALSE(pkt6);
+
+ // There was some data, so this time callback should be called
+ EXPECT_TRUE(callback_ok);
+
+ // close both pipe ends
+ close(pipefd[1]);
+ close(pipefd[0]);
+}
+
+// Tests if multiple external sockets and their callbacks can be passed and
+// it is supported properly by receive6() method.
+TEST_F(IfaceMgrTest, MiltipleExternalSockets6) {
+
+ callback_ok = false;
+ callback2_ok = false;
+
+ scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
+
+ // Create first pipe and register it as extra socket
+ int pipefd[2];
+ EXPECT_TRUE(pipe(pipefd) == 0);
+ EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
+
+ // Let's create a second pipe and register it as well
+ int secondpipe[2];
+ EXPECT_TRUE(pipe(secondpipe) == 0);
+ EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));
+
+ Pkt6Ptr pkt6;
+ ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
+
+ // Our callbacks should not be called this time (there was no data)
+ EXPECT_FALSE(callback_ok);
+ EXPECT_FALSE(callback2_ok);
+
+ // IfaceMgr should not process control socket data as incoming packets
+ EXPECT_FALSE(pkt6);
+
+ // Now, send some data over the first pipe (38 bytes)
+ EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
+
+ // ... and repeat
+ ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
+
+ // IfaceMgr should not process control socket data as incoming packets
+ EXPECT_FALSE(pkt6);
+
+ // There was some data, so this time callback should be called
+ EXPECT_TRUE(callback_ok);
+ EXPECT_FALSE(callback2_ok);
+
+ // Read the data sent, because our test callbacks are too dumb to actually
+ // do it. We don't care about the content read, because we're testing
+ // the callbacks, not pipes.
+ char buf[80];
+ EXPECT_EQ(38, read(pipefd[0], buf, 80));
+
+ // Clear the status...
+ callback_ok = false;
+ callback2_ok = false;
+
+ // And try again, using the second pipe
+ EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));
+
+ // ... and repeat
+ ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
+
+ // IfaceMgr should not process control socket data as incoming packets
+ EXPECT_FALSE(pkt6);
+
+ // There was some data, so this time callback should be called
+ EXPECT_FALSE(callback_ok);
+ EXPECT_TRUE(callback2_ok);
+
+ // close both pipe ends
+ close(pipefd[1]);
+ close(pipefd[0]);
+
+ close(secondpipe[1]);
+ close(secondpipe[0]);
+}
+
+// Tests if existing external socket can be deleted and that such deletion does
+// not affect any other existing sockets. Tests uses receive6()
+TEST_F(IfaceMgrTest, DeleteExternalSockets6) {
+
+ callback_ok = false;
+ callback2_ok = false;
+
+ scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
+
+ // Create first pipe and register it as extra socket
+ int pipefd[2];
+ EXPECT_TRUE(pipe(pipefd) == 0);
+ EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
+
+ // Let's create a second pipe and register it as well
+ int secondpipe[2];
+ EXPECT_TRUE(pipe(secondpipe) == 0);
+ EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));
+
+ // Now delete the first session socket
+ EXPECT_NO_THROW(ifacemgr->deleteExternalSocket(pipefd[0]));
+
+ // Now check whether the second callback is still functional
+ EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));
+
+ // ... and repeat
+ Pkt6Ptr pkt6;
+ ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
+
+ // IfaceMgr should not process control socket data as incoming packets
+ EXPECT_FALSE(pkt6);
+
+ // There was some data, so this time callback should be called
+ EXPECT_FALSE(callback_ok);
+ EXPECT_TRUE(callback2_ok);
+
+ // Let's reset the status
+ callback_ok = false;
+ callback2_ok = false;
+
+ // Now let's send something over the first callback that was unregistered.
+ // We should NOT receive any callback.
+ EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
+
+ // Now check that the first callback is NOT called.
+ ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
+ EXPECT_FALSE(callback_ok);
+
+ // close both pipe ends
+ close(pipefd[1]);
+ close(pipefd[0]);
+
+ close(secondpipe[1]);
+ close(secondpipe[0]);
+}
+
+
// Test checks if the unicast sockets can be opened.
// This test is now disabled, because there is no reliable way to test it. We
// can't even use loopback, beacuse openSockets() skips loopback interface
More information about the bind10-changes
mailing list