::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
::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
connections_.clear();
}
+ size_t getConnectionsNum() const {
+ return (connections_.size());
+ }
+
private:
std::set<ConnectionPtr> connections_;
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());
}
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());
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,