From: Michal 'vorner' Vaner Date: Wed, 21 Dec 2011 15:37:41 +0000 (+0100) Subject: [805] Basic support to install sockcreator sockets X-Git-Tag: trac2351_base~304^2~16^2~34 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cec38f4ec016d0b510fb884def95898080fa66f3;p=thirdparty%2Fkea.git [805] Basic support to install sockcreator sockets * They are requested and installed, instead of binding them locally * Documentation needs update * It'll fail in practice, since the requestor isn't initialized from auth and resolver. * It needs to set the correct IPv6 flag --- diff --git a/src/lib/server_common/portconfig.cc b/src/lib/server_common/portconfig.cc index 379a0a17c4..3f2a3169ce 100644 --- a/src/lib/server_common/portconfig.cc +++ b/src/lib/server_common/portconfig.cc @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -30,6 +31,11 @@ namespace isc { namespace server_common { namespace portconfig { +// This flags disables pushing the sockets to the DNSService. It prevents +// the clearServers() method to close the file descriptors we made up. +// It is not presented in any header, but we use it from the tests anyway. +bool test_mode(false); + AddressList parseAddresses(isc::data::ConstElementPtr addresses, const std::string& elemName) @@ -76,11 +82,35 @@ parseAddresses(isc::data::ConstElementPtr addresses, namespace { +vector current_sockets; + void setAddresses(DNSService& service, const AddressList& addresses) { service.clearServers(); + BOOST_FOREACH(const string& token, current_sockets) { + socketRequestor().releaseSocket(token); + } + current_sockets.clear(); BOOST_FOREACH(const AddressPair &address, addresses) { - service.addServer(address.second, address.first); + // TODO: Support sharing somehow in future. + const SocketRequestor::SocketID + tcp(socketRequestor().requestSocket(SocketRequestor::TCP, + address.first, address.second, + SocketRequestor::DONT_SHARE, + "dummy_app")); + current_sockets.push_back(tcp.second); + if (!test_mode) { + service.addServerTCP(tcp.first, true); // FIXME: Correct the flag + } + const SocketRequestor::SocketID + udp(socketRequestor().requestSocket(SocketRequestor::UDP, + address.first, address.second, + SocketRequestor::DONT_SHARE, + "dummy_app")); + current_sockets.push_back(udp.second); + if (!test_mode) { + service.addServerUDP(udp.first, true); // FIXME: Correct the flag + } } } diff --git a/src/lib/server_common/tests/portconfig_unittest.cc b/src/lib/server_common/tests/portconfig_unittest.cc index 65963eb31c..46a16bd636 100644 --- a/src/lib/server_common/tests/portconfig_unittest.cc +++ b/src/lib/server_common/tests/portconfig_unittest.cc @@ -13,6 +13,7 @@ // PERFORMANCE OF THIS SOFTWARE. #include +#include #include #include @@ -21,13 +22,25 @@ #include #include +#include using namespace isc::server_common::portconfig; +using namespace isc::server_common; using namespace isc::data; using namespace isc; using namespace std; using namespace isc::asiolink; using namespace isc::asiodns; +using boost::lexical_cast; + +// Access the private hidden flag +namespace isc { +namespace server_common { +namespace portconfig { +extern bool test_mode; +} +} +} namespace { @@ -127,12 +140,15 @@ TEST_F(ParseAddresses, invalid) { } // Test fixture for installListenAddresses -struct InstallListenAddresses : public ::testing::Test { +struct InstallListenAddresses : public ::testing::Test, + public SocketRequestor { InstallListenAddresses() : - dnss_(ios_, NULL, NULL, NULL) + dnss_(ios_, NULL, NULL, NULL), + last_token_(0) { valid_.push_back(AddressPair("127.0.0.1", 5288)); valid_.push_back(AddressPair("::1", 5288)); + invalid_.push_back(AddressPair("127.0.0.1", 5288)); invalid_.push_back(AddressPair("192.0.2.2", 1)); } IOService ios_; @@ -142,6 +158,11 @@ struct InstallListenAddresses : public ::testing::Test { AddressList valid_; // But this shouldn't work AddressList invalid_; + // Store the tokens as they go in and out + vector released_tokens_; + vector given_tokens_; + // Last token number and fd given out + size_t last_token_; // Check that the store_ addresses are the same as expected void checkAddresses(const AddressList& expected, const string& name) { SCOPED_TRACE(name); @@ -155,20 +176,91 @@ struct InstallListenAddresses : public ::testing::Test { EXPECT_EQ(ei->second, si->second); } } + void releaseSocket(const string& token) { + released_tokens_.push_back(token); + } + SocketID requestSocket(Protocol protocol, const string& address, + uint16_t port, ShareMode mode, const string& name) + { + if (address == "192.0.2.2") { + isc_throw(SocketError, "This address is not allowed"); + } + const string proto(protocol == TCP ? "TCP" : "UDP"); + size_t number = ++ last_token_; + EXPECT_EQ(5288, port); + EXPECT_EQ(DONT_SHARE, mode); + EXPECT_EQ("dummy_app", name); + const string token(proto + ":" + address + ":" + + lexical_cast(port) + ":" + + lexical_cast(number)); + given_tokens_.push_back(token); + return (SocketID(number, token)); + } + void SetUp() { + // Prepare the requestor (us) for the test + SocketRequestor::initTest(this); + // Don't manipulate the real sockets + test_mode = true; + } + void TearDown() { + // Make sure no sockets are left inside + AddressList list; + installListenAddresses(list, store_, dnss_); + // Don't leave invalid pointers here + SocketRequestor::initTest(NULL); + // And return the mode + test_mode = false; + } + // This checks the set of tokens is the same + void checkTokens(const char** expected, const vector& real, + const char* scope) + { + SCOPED_TRACE(scope); + size_t position(0); + while (expected[position]) { + ASSERT_LT(position, real.size()); + EXPECT_EQ(expected[position], real[position]) << position; + position ++; + } + EXPECT_EQ(position, real.size()); + } }; // Try switching valid addresses +// Check the sockets are correctly requested and returned TEST_F(InstallListenAddresses, valid) { // First, bind to the valid addresses EXPECT_NO_THROW(installListenAddresses(valid_, store_, dnss_)); checkAddresses(valid_, "Valid addresses"); + const char* tokens1[] = { + "TCP:127.0.0.1:5288:1", + "UDP:127.0.0.1:5288:2", + "TCP:::1:5288:3", + "UDP:::1:5288:4", + NULL + }; + const char* no_tokens[] = { NULL }; + checkTokens(tokens1, given_tokens_, "Valid given tokens 1"); + checkTokens(no_tokens, released_tokens_, "Valid no released tokens 1"); // TODO Maybe some test to actually connect to them // Try setting it back to nothing + given_tokens_.clear(); EXPECT_NO_THROW(installListenAddresses(AddressList(), store_, dnss_)); checkAddresses(AddressList(), "No addresses"); + checkTokens(no_tokens, given_tokens_, "Valid no given tokens"); + checkTokens(tokens1, released_tokens_, "Valid released tokens"); // Try switching back again EXPECT_NO_THROW(installListenAddresses(valid_, store_, dnss_)); checkAddresses(valid_, "Valid addresses"); + const char* tokens2[] = { + "TCP:127.0.0.1:5288:5", + "UDP:127.0.0.1:5288:6", + "TCP:::1:5288:7", + "UDP:::1:5288:8", + NULL + }; + checkTokens(tokens2, given_tokens_, "Valid given tokens 2"); + checkTokens(tokens1, released_tokens_, "Valid released tokens"); } // Try if rollback works @@ -176,9 +268,44 @@ TEST_F(InstallListenAddresses, rollback) { // Set some addresses EXPECT_NO_THROW(installListenAddresses(valid_, store_, dnss_)); checkAddresses(valid_, "Before rollback"); + const char* tokens1[] = { + "TCP:127.0.0.1:5288:1", + "UDP:127.0.0.1:5288:2", + "TCP:::1:5288:3", + "UDP:::1:5288:4", + NULL + }; + const char* no_tokens[] = { NULL }; + checkTokens(tokens1, given_tokens_, "Given before rollback"); + checkTokens(no_tokens, released_tokens_, "Released before rollback"); + given_tokens_.clear(); // This should not bind them, but should leave the original addresses EXPECT_THROW(installListenAddresses(invalid_, store_, dnss_), exception); checkAddresses(valid_, "After rollback"); + // Now, it should have requested first pair of sockets from the invalids + // and, as the second failed, it should have returned them right away. + const char* released1[] = { + "TCP:127.0.0.1:5288:1", + "UDP:127.0.0.1:5288:2", + "TCP:::1:5288:3", + "UDP:::1:5288:4", + "TCP:127.0.0.1:5288:5", + "UDP:127.0.0.1:5288:6", + NULL + }; + // It should request the first pair of sockets, and then request the + // complete set of valid addresses to rollback + const char* tokens2[] = { + "TCP:127.0.0.1:5288:5", + "UDP:127.0.0.1:5288:6", + "TCP:127.0.0.1:5288:7", + "UDP:127.0.0.1:5288:8", + "TCP:::1:5288:9", + "UDP:::1:5288:10", + NULL + }; + checkTokens(tokens2, given_tokens_, "Given after rollback"); + checkTokens(released1, released_tokens_, "Released after rollback"); } }