mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 05:27:55 +00:00
[5317] Only a single control command connection is now allowed.
This commit is contained in:
parent
2688a2a886
commit
c4fb6001e7
@ -1066,4 +1066,50 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configReloadValid) {
|
||||
::remove("test8.json");
|
||||
}
|
||||
|
||||
// Verify that server returns an error if more than one connection is established.
|
||||
TEST_F(CtrlChannelDhcpv4SrvTest, concurrentConnections) {
|
||||
createUnixChannelServer();
|
||||
|
||||
boost::scoped_ptr<UnixControlClient> client1(new UnixControlClient());
|
||||
ASSERT_TRUE(client1);
|
||||
|
||||
boost::scoped_ptr<UnixControlClient> client2(new UnixControlClient());
|
||||
ASSERT_TRUE(client1);
|
||||
|
||||
// Client 1 connects.
|
||||
ASSERT_TRUE(client1->connectToServer(socket_path_));
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
// Client 2 connects.
|
||||
ASSERT_TRUE(client2->connectToServer(socket_path_));
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
// Send the command while another client is connected.
|
||||
ASSERT_TRUE(client2->sendCommand("{ \"command\": \"list-commands\" }"));
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
// The server should not allow for concurrent connections and should send
|
||||
// out an error message.
|
||||
std::string response;
|
||||
ASSERT_TRUE(client2->getResponse(response));
|
||||
EXPECT_EQ("{ \"result\": 1, \"text\": \"exceeded maximum number of concurrent"
|
||||
" connections\" }", response);
|
||||
|
||||
// Now disconnect the first server and retry.
|
||||
client1->disconnectFromServer();
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
ASSERT_TRUE(client2->connectToServer(socket_path_));
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
ASSERT_TRUE(client2->sendCommand("{ \"command\": \"list-commands\" }"));
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
// The server should now respond ok.
|
||||
ASSERT_TRUE(client2->getResponse(response));
|
||||
EXPECT_TRUE(response.find("\"result\": 0") != std::string::npos);
|
||||
|
||||
client2->disconnectFromServer();
|
||||
}
|
||||
|
||||
} // End of anonymous namespace
|
||||
|
@ -1088,4 +1088,51 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configReloadValid) {
|
||||
::remove("test8.json");
|
||||
}
|
||||
|
||||
// Verify that server returns an error if more than one connection is established.
|
||||
TEST_F(CtrlChannelDhcpv6SrvTest, concurrentConnections) {
|
||||
createUnixChannelServer();
|
||||
|
||||
boost::scoped_ptr<UnixControlClient> client1(new UnixControlClient());
|
||||
ASSERT_TRUE(client1);
|
||||
|
||||
boost::scoped_ptr<UnixControlClient> client2(new UnixControlClient());
|
||||
ASSERT_TRUE(client1);
|
||||
|
||||
// Client 1 connects.
|
||||
ASSERT_TRUE(client1->connectToServer(socket_path_));
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
// Client 2 connects.
|
||||
ASSERT_TRUE(client2->connectToServer(socket_path_));
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
// Send the command while another client is connected.
|
||||
ASSERT_TRUE(client2->sendCommand("{ \"command\": \"list-commands\" }"));
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
// The server should not allow for concurrent connections and should send
|
||||
// out an error message.
|
||||
std::string response;
|
||||
ASSERT_TRUE(client2->getResponse(response));
|
||||
EXPECT_EQ("{ \"result\": 1, \"text\": \"exceeded maximum number of concurrent"
|
||||
" connections\" }", response);
|
||||
|
||||
// Now disconnect the first server and retry.
|
||||
client1->disconnectFromServer();
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
ASSERT_TRUE(client2->connectToServer(socket_path_));
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
ASSERT_TRUE(client2->sendCommand("{ \"command\": \"list-commands\" }"));
|
||||
ASSERT_NO_THROW(getIOService()->poll());
|
||||
|
||||
// The server should now respond ok.
|
||||
ASSERT_TRUE(client2->getResponse(response));
|
||||
EXPECT_TRUE(response.find("\"result\": 0") != std::string::npos);
|
||||
|
||||
client2->disconnectFromServer();
|
||||
}
|
||||
|
||||
|
||||
} // End of anonymous namespace
|
||||
|
@ -97,6 +97,10 @@ public:
|
||||
connections_.clear();
|
||||
}
|
||||
|
||||
size_t getConnectionsNum() const {
|
||||
return (connections_.size());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::set<ConnectionPtr> connections_;
|
||||
@ -109,7 +113,14 @@ Connection::receiveHandler(const boost::system::error_code& ec,
|
||||
size_t bytes_transferred) {
|
||||
if (ec) {
|
||||
|
||||
if (ec.value() != boost::asio::error::operation_aborted) {
|
||||
if (ec.value() == boost::asio::error::eof) {
|
||||
// Foreign host has closed the connection. We should remove it from the
|
||||
// connection pool.
|
||||
LOG_INFO(command_logger, COMMAND_SOCKET_CLOSED_BY_FOREIGN_HOST)
|
||||
.arg(socket_->getNative());
|
||||
connection_pool_.stop(shared_from_this());
|
||||
|
||||
} else if (ec.value() != boost::asio::error::operation_aborted) {
|
||||
LOG_ERROR(command_logger, COMMAND_SOCKET_READ_FAIL)
|
||||
.arg(ec.value()).arg(socket_->getNative());
|
||||
}
|
||||
@ -137,8 +148,13 @@ Connection::receiveHandler(const boost::system::error_code& ec,
|
||||
std::string sbuf(&buf_[0], bytes_transferred);
|
||||
cmd = Element::fromJSON(sbuf, true);
|
||||
|
||||
// If successful, then process it as a command.
|
||||
rsp = CommandMgr::instance().processCommand(cmd);
|
||||
if (connection_pool_.getConnectionsNum() > 1) {
|
||||
rsp = createAnswer(CONTROL_RESULT_ERROR, "exceeded maximum number of concurrent"
|
||||
" connections");
|
||||
} else {
|
||||
// If successful, then process it as a command.
|
||||
rsp = CommandMgr::instance().processCommand(cmd);
|
||||
}
|
||||
|
||||
} catch (const Exception& ex) {
|
||||
LOG_WARN(command_logger, COMMAND_PROCESS_ERROR1).arg(ex.what());
|
||||
|
@ -55,6 +55,10 @@ This error indicates that the server detected incoming connection and executed
|
||||
accept system call on said socket, but this call returned an error. Additional
|
||||
information may be provided by the system as second parameter.
|
||||
|
||||
% COMMAND_SOCKET_CLOSED_BY_FOREIGN_HOST Closed command socket %1 by foreign host
|
||||
This is an information message indicating that the command connection has been
|
||||
closed by a command control client.
|
||||
|
||||
% COMMAND_SOCKET_CONNECTION_CLOSED Closed socket %1 for existing command connection
|
||||
This is an informational message that the socket created for handling
|
||||
client's connection is closed. This usually means that the client disconnected,
|
||||
|
Loading…
x
Reference in New Issue
Block a user