return (str);
}
+// A helper converter from numeric protocol ID to the corresponding string.
+// used both for generating a message for the boss process and for logging.
+inline const char*
+protocolString(SocketRequestor::Protocol protocol) {
+ switch (protocol) {
+ case SocketRequestor::TCP:
+ return ("TCP");
+ case SocketRequestor::UDP:
+ return ("UDP");
+ default:
+ return ("unknown protocol");
+ }
+}
+
// Creates the cc session message to request a socket.
// The actual command format is hardcoded, and should match
// the format as read in bind10_src.py.in
const isc::data::ElementPtr request = isc::data::Element::createMap();
request->set("address", isc::data::Element::create(address));
request->set("port", isc::data::Element::create(port));
- switch (protocol) {
- case SocketRequestor::UDP:
- request->set("protocol", isc::data::Element::create("UDP"));
- break;
- case SocketRequestor::TCP:
- request->set("protocol", isc::data::Element::create("TCP"));
- break;
+ if (protocol != SocketRequestor::TCP && protocol != SocketRequestor::UDP) {
+ isc_throw(InvalidParameter, "invalid protocol: " << protocol);
}
+ request->set("protocol",
+ isc::data::Element::create(protocolString(protocol)));
switch (share_mode) {
case SocketRequestor::DONT_SHARE:
request->set("share_mode", isc::data::Element::create("NO"));
case SocketRequestor::SHARE_ANY:
request->set("share_mode", isc::data::Element::create("ANY"));
break;
+ default:
+ isc_throw(InvalidParameter, "invalid share mode: " << share_mode);
}
request->set("share_name", isc::data::Element::create(share_name));
return (passed_sock_fd);
}
-namespace {
-inline const char*
-protocolString(SocketRequestor::Protocol protocol) {
- switch (protocol) {
- case SocketRequestor::TCP:
- return ("TCP");
- case SocketRequestor::UDP:
- return ("UDP");
- default:
- return ("unknown protocol");
- }
-}
-}
-
// This implementation class for SocketRequestor uses
// a ModuleCCSession for communication with the boss process,
// and fd_share to read out the socket(s).
/// Asks the socket creator to give us a socket. The socket will be bound
/// to the given address and port.
///
- /// \param protocol specifies the protocol of the socket.
+ /// \param protocol specifies the protocol of the socket. This must be
+ /// either UDP or TCP.
/// \param address to which the socket should be bound.
/// \param port the port to which the socket should be bound (native endian,
/// not network byte order).
/// \param share_mode how the socket can be shared with other requests.
+ /// This must be one of the defined values of ShareMode.
/// \param share_name the name of sharing group, relevant for SHARE_SAME
/// (specified by us or someone else).
/// \return the socket, as a file descriptor and token representing it on
/// the socket creator side.
+ ///
+ /// \throw InvalidParameter protocol or share_mode is invalid
/// \throw CCSessionError when we have a problem talking over the CC
/// session.
/// \throw SocketError in case the other side doesn't want to give us
ASSERT_EQ(*expected_request, *(session.getMsgQueue()->get(0)));
}
+TEST_F(SocketRequestorTest, invalidParameterForSocketRequest) {
+ // Bad protocol
+ EXPECT_THROW(socketRequestor().
+ requestSocket(static_cast<SocketRequestor::Protocol>(2),
+ "192.0.2.1", 12345,
+ SocketRequestor::DONT_SHARE,
+ "test"),
+ InvalidParameter);
+
+ // Bad share mode
+ EXPECT_THROW(socketRequestor().
+ requestSocket(SocketRequestor::UDP,
+ "192.0.2.1", 12345,
+ static_cast<SocketRequestor::ShareMode>(3),
+ "test"),
+ InvalidParameter);
+}
+
TEST_F(SocketRequestorTest, testBadRequestAnswers) {
// Test various scenarios where the requestor gets back bad answers