mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 05:55:28 +00:00
[5318] PoC for extending maximum request/response over 64k in Ctrl channel.
This commit is contained in:
@@ -30,6 +30,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -85,6 +86,7 @@ public:
|
|||||||
StatsMgr::instance().removeAll();
|
StatsMgr::instance().removeAll();
|
||||||
|
|
||||||
CommandMgr::instance().closeCommandSocket();
|
CommandMgr::instance().closeCommandSocket();
|
||||||
|
CommandMgr::instance().deregisterAll();
|
||||||
|
|
||||||
server_.reset();
|
server_.reset();
|
||||||
};
|
};
|
||||||
@@ -296,6 +298,18 @@ public:
|
|||||||
ADD_FAILURE() << "Invalid expected status: " << exp_status;
|
ADD_FAILURE() << "Invalid expected status: " << exp_status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Command handler which generates long response
|
||||||
|
static ConstElementPtr longResponseHandler(const std::string&,
|
||||||
|
const ConstElementPtr&) {
|
||||||
|
ElementPtr arguments = Element::createList();
|
||||||
|
std::string arg = "responseresponseresponseresponseresponseresponse"
|
||||||
|
"response";
|
||||||
|
for (unsigned i = 0; i < 8000; ++i) {
|
||||||
|
arguments->add(Element::create(arg));
|
||||||
|
}
|
||||||
|
return (createAnswer(0, arguments));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(CtrlChannelDhcpv4SrvTest, commands) {
|
TEST_F(CtrlChannelDhcpv4SrvTest, commands) {
|
||||||
@@ -431,7 +445,8 @@ TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelNegative) {
|
|||||||
|
|
||||||
sendUnixCommand("utter nonsense", response);
|
sendUnixCommand("utter nonsense", response);
|
||||||
EXPECT_EQ("{ \"result\": 1, "
|
EXPECT_EQ("{ \"result\": 1, "
|
||||||
"\"text\": \"error: unexpected character u in <string>:1:2\" }",
|
"\"text\": \"invalid first character u : "
|
||||||
|
"current state: [ 12 RECEIVE_START_ST ] next event: [ 1 START_EVT ]\" }",
|
||||||
response);
|
response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,7 +725,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configSet) {
|
|||||||
// Should fail with a syntax error
|
// Should fail with a syntax error
|
||||||
EXPECT_EQ("{ \"result\": 1, "
|
EXPECT_EQ("{ \"result\": 1, "
|
||||||
"\"text\": \"subnet configuration failed: mandatory 'subnet' "
|
"\"text\": \"subnet configuration failed: mandatory 'subnet' "
|
||||||
"parameter is missing for a subnet being configured (<string>:20:17)\" }",
|
"parameter is missing for a subnet being configured (<wire>:19:17)\" }",
|
||||||
response);
|
response);
|
||||||
|
|
||||||
// Check that the config was not lost
|
// Check that the config was not lost
|
||||||
@@ -909,7 +924,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configTest) {
|
|||||||
// Should fail with a syntax error
|
// Should fail with a syntax error
|
||||||
EXPECT_EQ("{ \"result\": 1, "
|
EXPECT_EQ("{ \"result\": 1, "
|
||||||
"\"text\": \"subnet configuration failed: mandatory 'subnet' "
|
"\"text\": \"subnet configuration failed: mandatory 'subnet' "
|
||||||
"parameter is missing for a subnet being configured (<string>:20:17)\" }",
|
"parameter is missing for a subnet being configured (<wire>:19:17)\" }",
|
||||||
response);
|
response);
|
||||||
|
|
||||||
// Check that the config was not lost
|
// Check that the config was not lost
|
||||||
@@ -1108,4 +1123,93 @@ TEST_F(CtrlChannelDhcpv4SrvTest, concurrentConnections) {
|
|||||||
ASSERT_NO_THROW(getIOService()->poll());
|
ASSERT_NO_THROW(getIOService()->poll());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CtrlChannelDhcpv4SrvTest, longCommand) {
|
||||||
|
createUnixChannelServer();
|
||||||
|
|
||||||
|
boost::scoped_ptr<UnixControlClient> client(new UnixControlClient());
|
||||||
|
ASSERT_TRUE(client);
|
||||||
|
|
||||||
|
ASSERT_TRUE(client->connectToServer(socket_path_));
|
||||||
|
getIOService()->run_one();
|
||||||
|
getIOService()->poll();
|
||||||
|
|
||||||
|
size_t bytes_transferred = 0;
|
||||||
|
const size_t payload_size = 1024 * 1000;
|
||||||
|
bool first_payload = true;
|
||||||
|
while (bytes_transferred < payload_size) {
|
||||||
|
if (bytes_transferred == 0) {
|
||||||
|
std::string preamble = "{ \"command\": \"foo\", \"arguments\": [ ";
|
||||||
|
ASSERT_TRUE(client->sendCommand(preamble));
|
||||||
|
bytes_transferred += preamble.size();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
std::ostringstream payload;
|
||||||
|
if (!first_payload) {
|
||||||
|
payload << ", ";
|
||||||
|
}
|
||||||
|
first_payload = false;
|
||||||
|
payload << "\"blablablablablablablablablablablablablablablabla\"";
|
||||||
|
|
||||||
|
if (bytes_transferred + payload.tellp() > payload_size) {
|
||||||
|
payload << "] }";
|
||||||
|
}
|
||||||
|
ASSERT_TRUE(client->sendCommand(payload.str()));
|
||||||
|
|
||||||
|
bytes_transferred += payload.tellp();
|
||||||
|
}
|
||||||
|
|
||||||
|
getIOService()->run_one();
|
||||||
|
getIOService()->poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string response;
|
||||||
|
ASSERT_TRUE(client->getResponse(response));
|
||||||
|
|
||||||
|
EXPECT_EQ("{ \"result\": 2, \"text\": \"'foo' command not supported.\" }",
|
||||||
|
response);
|
||||||
|
|
||||||
|
client->disconnectFromServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CtrlChannelDhcpv4SrvTest, longResponse) {
|
||||||
|
ASSERT_NO_THROW(
|
||||||
|
CommandMgr::instance().registerCommand("foo",
|
||||||
|
boost::bind(&CtrlChannelDhcpv4SrvTest::longResponseHandler, _1, _2));
|
||||||
|
);
|
||||||
|
|
||||||
|
createUnixChannelServer();
|
||||||
|
|
||||||
|
std::string reference_response = longResponseHandler("foo", ConstElementPtr())->str();
|
||||||
|
std::ostringstream response;
|
||||||
|
std::thread th([this, &response, reference_response]() {
|
||||||
|
|
||||||
|
size_t long_response_size = reference_response.size();
|
||||||
|
|
||||||
|
boost::scoped_ptr<UnixControlClient> client(new UnixControlClient());
|
||||||
|
ASSERT_TRUE(client);
|
||||||
|
|
||||||
|
ASSERT_TRUE(client->connectToServer(socket_path_));
|
||||||
|
|
||||||
|
std::string command = "{ \"command\": \"foo\", \"arguments\": { } }";
|
||||||
|
ASSERT_TRUE(client->sendCommand(command));
|
||||||
|
|
||||||
|
while (response.tellp() < long_response_size) {
|
||||||
|
std::string partial;
|
||||||
|
client->getResponse(partial);
|
||||||
|
response << partial;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->disconnectFromServer();
|
||||||
|
|
||||||
|
getIOService()->stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
getIOService()->run();
|
||||||
|
|
||||||
|
th.join();
|
||||||
|
|
||||||
|
EXPECT_EQ(reference_response, response.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // End of anonymous namespace
|
} // End of anonymous namespace
|
||||||
|
@@ -484,7 +484,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configSet) {
|
|||||||
|
|
||||||
// Should fail with a syntax error
|
// Should fail with a syntax error
|
||||||
EXPECT_EQ("{ \"result\": 1, "
|
EXPECT_EQ("{ \"result\": 1, "
|
||||||
"\"text\": \"subnet configuration failed: mandatory 'subnet' parameter is missing for a subnet being configured (<string>:21:17)\" }",
|
"\"text\": \"subnet configuration failed: mandatory 'subnet' parameter is missing for a subnet being configured (<wire>:20:17)\" }",
|
||||||
response);
|
response);
|
||||||
|
|
||||||
// Check that the config was not lost
|
// Check that the config was not lost
|
||||||
@@ -630,7 +630,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configTest) {
|
|||||||
// Should fail with a syntax error
|
// Should fail with a syntax error
|
||||||
EXPECT_EQ("{ \"result\": 1, "
|
EXPECT_EQ("{ \"result\": 1, "
|
||||||
"\"text\": \"subnet configuration failed: mandatory 'subnet' parameter "
|
"\"text\": \"subnet configuration failed: mandatory 'subnet' parameter "
|
||||||
"is missing for a subnet being configured (<string>:21:17)\" }",
|
"is missing for a subnet being configured (<wire>:20:17)\" }",
|
||||||
response);
|
response);
|
||||||
|
|
||||||
// Check that the config was not lost
|
// Check that the config was not lost
|
||||||
@@ -737,7 +737,8 @@ TEST_F(CtrlChannelDhcpv6SrvTest, controlChannelNegative) {
|
|||||||
|
|
||||||
sendUnixCommand("utter nonsense", response);
|
sendUnixCommand("utter nonsense", response);
|
||||||
EXPECT_EQ("{ \"result\": 1, "
|
EXPECT_EQ("{ \"result\": 1, "
|
||||||
"\"text\": \"error: unexpected character u in <string>:1:2\" }",
|
"\"text\": \"invalid first character u : "
|
||||||
|
"current state: [ 12 RECEIVE_START_ST ] next event: [ 1 START_EVT ]\" }",
|
||||||
response);
|
response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include <config/command_mgr.h>
|
#include <config/command_mgr.h>
|
||||||
#include <cc/data.h>
|
#include <cc/data.h>
|
||||||
#include <cc/command_interpreter.h>
|
#include <cc/command_interpreter.h>
|
||||||
|
#include <cc/json_feed.h>
|
||||||
#include <dhcp/iface_mgr.h>
|
#include <dhcp/iface_mgr.h>
|
||||||
#include <config/config_log.h>
|
#include <config/config_log.h>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
@@ -42,24 +43,13 @@ public:
|
|||||||
/// a transmission over the control socket is received.
|
/// a transmission over the control socket is received.
|
||||||
Connection(const boost::shared_ptr<UnixDomainSocket>& socket,
|
Connection(const boost::shared_ptr<UnixDomainSocket>& socket,
|
||||||
ConnectionPool& connection_pool)
|
ConnectionPool& connection_pool)
|
||||||
: socket_(socket), connection_pool_(connection_pool),
|
: socket_(socket), buf_(), response_(), connection_pool_(connection_pool),
|
||||||
response_in_progress_(false) {
|
feed_(), response_in_progress_(false) {
|
||||||
// Callback value of 0 is used to indicate that callback function is
|
// Callback value of 0 is used to indicate that callback function is
|
||||||
// not installed.
|
// not installed.
|
||||||
isc::dhcp::IfaceMgr::instance().addExternalSocket(socket_->getNative(), 0);
|
isc::dhcp::IfaceMgr::instance().addExternalSocket(socket_->getNative(), 0);
|
||||||
}
|
// Initialize state model for receiving and preparsing commands.
|
||||||
|
feed_.initModel();
|
||||||
/// @brief Start asynchronous read over the unix domain socket.
|
|
||||||
///
|
|
||||||
/// This method doesn't block. Once the transmission is received over the
|
|
||||||
/// socket, the @c Connection::receiveHandler callback is invoked to
|
|
||||||
/// process received data.
|
|
||||||
void start() {
|
|
||||||
socket_->asyncReceive(&buf_[0], sizeof(buf_),
|
|
||||||
boost::bind(&Connection::receiveHandler,
|
|
||||||
shared_from_this(), _1, _2));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Close current connection.
|
/// @brief Close current connection.
|
||||||
@@ -78,6 +68,29 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Start asynchronous read over the unix domain socket.
|
||||||
|
///
|
||||||
|
/// This method doesn't block. Once the transmission is received over the
|
||||||
|
/// socket, the @c Connection::receiveHandler callback is invoked to
|
||||||
|
/// process received data.
|
||||||
|
void doReceive() {
|
||||||
|
socket_->asyncReceive(&buf_[0], sizeof(buf_),
|
||||||
|
boost::bind(&Connection::receiveHandler,
|
||||||
|
shared_from_this(), _1, _2));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Starts asynchronous send over the unix domain socket.
|
||||||
|
///
|
||||||
|
/// This method doesn't block. Once the send operation is completed, the
|
||||||
|
/// @c Connection::sendHandler cllback is invoked.
|
||||||
|
void doSend() {
|
||||||
|
size_t chunk_size = response_.size() < 8192 ? response_.size() : 8192;
|
||||||
|
socket_->asyncSend(&response_[0], chunk_size,
|
||||||
|
boost::bind(&Connection::sendHandler, shared_from_this(), _1, _2));
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Handler invoked when the data is received over the control
|
/// @brief Handler invoked when the data is received over the control
|
||||||
/// socket.
|
/// socket.
|
||||||
///
|
///
|
||||||
@@ -86,6 +99,13 @@ public:
|
|||||||
void receiveHandler(const boost::system::error_code& ec,
|
void receiveHandler(const boost::system::error_code& ec,
|
||||||
size_t bytes_transferred);
|
size_t bytes_transferred);
|
||||||
|
|
||||||
|
|
||||||
|
/// @brief Handler invoked when the data is sent over the control socket.
|
||||||
|
///
|
||||||
|
/// @param ec Error code.
|
||||||
|
/// @param bytes_transferred Number of bytes sent.
|
||||||
|
void sendHandler(const boost::system::error_code& ec,
|
||||||
|
size_t bytes_trasferred);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// @brief Pointer to the socket used for transmission.
|
/// @brief Pointer to the socket used for transmission.
|
||||||
@@ -94,9 +114,16 @@ private:
|
|||||||
/// @brief Buffer used for received data.
|
/// @brief Buffer used for received data.
|
||||||
std::array<char, 65535> buf_;
|
std::array<char, 65535> buf_;
|
||||||
|
|
||||||
|
/// @brief Response created by the server.
|
||||||
|
std::string response_;
|
||||||
|
|
||||||
/// @brief Reference to the pool of connections.
|
/// @brief Reference to the pool of connections.
|
||||||
ConnectionPool& connection_pool_;
|
ConnectionPool& connection_pool_;
|
||||||
|
|
||||||
|
/// @brief State model used to receive data over the connection and detect
|
||||||
|
/// when the command ends.
|
||||||
|
JSONFeed feed_;
|
||||||
|
|
||||||
/// @brief Boolean flag indicating if the request to stop connection is a
|
/// @brief Boolean flag indicating if the request to stop connection is a
|
||||||
/// result of server reconfiguration.
|
/// result of server reconfiguration.
|
||||||
bool response_in_progress_;
|
bool response_in_progress_;
|
||||||
@@ -114,7 +141,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param connection Pointer to the new connection object.
|
/// @param connection Pointer to the new connection object.
|
||||||
void start(const ConnectionPtr& connection) {
|
void start(const ConnectionPtr& connection) {
|
||||||
connection->start();
|
connection->doReceive();
|
||||||
connections_.insert(connection);
|
connections_.insert(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,17 +207,25 @@ Connection::receiveHandler(const boost::system::error_code& ec,
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Try to interpret it as JSON.
|
feed_.postBuffer(&buf_[0], bytes_transferred);
|
||||||
std::string sbuf(&buf_[0], bytes_transferred);
|
feed_.poll();
|
||||||
cmd = Element::fromJSON(sbuf, true);
|
if (feed_.needData()) {
|
||||||
|
doReceive();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
response_in_progress_ = true;
|
if (feed_.feedOk()) {
|
||||||
|
cmd = feed_.toElement();
|
||||||
|
response_in_progress_ = true;
|
||||||
|
|
||||||
// If successful, then process it as a command.
|
// If successful, then process it as a command.
|
||||||
rsp = CommandMgr::instance().processCommand(cmd);
|
rsp = CommandMgr::instance().processCommand(cmd);
|
||||||
|
|
||||||
response_in_progress_ = false;
|
response_in_progress_ = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
isc_throw(BadValue, feed_.getErrorMessage());
|
||||||
|
}
|
||||||
|
|
||||||
} catch (const Exception& ex) {
|
} catch (const Exception& ex) {
|
||||||
LOG_WARN(command_logger, COMMAND_PROCESS_ERROR1).arg(ex.what());
|
LOG_WARN(command_logger, COMMAND_PROCESS_ERROR1).arg(ex.what());
|
||||||
@@ -203,30 +238,52 @@ Connection::receiveHandler(const boost::system::error_code& ec,
|
|||||||
rsp = createAnswer(CONTROL_RESULT_ERROR,
|
rsp = createAnswer(CONTROL_RESULT_ERROR,
|
||||||
"internal server error: no response generated");
|
"internal server error: no response generated");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Let's convert JSON response to text. Note that at this stage
|
||||||
|
// the rsp pointer is always set.
|
||||||
|
response_ = rsp->str();
|
||||||
|
|
||||||
|
doSend();
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* size_t len = response_.length();
|
||||||
|
if (len > 65535) {
|
||||||
|
// Hmm, our response is too large. Let's send the first
|
||||||
|
// 64KB and hope for the best.
|
||||||
|
LOG_ERROR(command_logger, COMMAND_SOCKET_RESPONSE_TOOLARGE).arg(len);
|
||||||
|
|
||||||
|
len = 65535;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Send the data back over socket.
|
||||||
|
socket_->write(response_.c_str(), len);
|
||||||
|
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
// Response transmission failed. Since the response failed, it doesn't
|
||||||
|
// make sense to send any status codes. Let's log it and be done with
|
||||||
|
// it.
|
||||||
|
LOG_ERROR(command_logger, COMMAND_SOCKET_WRITE_FAIL)
|
||||||
|
.arg(len).arg(socket_->getNative()).arg(ex.what());
|
||||||
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's convert JSON response to text. Note that at this stage
|
connection_pool_.stop(shared_from_this());
|
||||||
// the rsp pointer is always set.
|
}
|
||||||
std::string txt = rsp->str();
|
|
||||||
size_t len = txt.length();
|
|
||||||
if (len > 65535) {
|
|
||||||
// Hmm, our response is too large. Let's send the first
|
|
||||||
// 64KB and hope for the best.
|
|
||||||
LOG_ERROR(command_logger, COMMAND_SOCKET_RESPONSE_TOOLARGE).arg(len);
|
|
||||||
|
|
||||||
len = 65535;
|
void
|
||||||
}
|
Connection::sendHandler(const boost::system::error_code& ec,
|
||||||
|
size_t bytes_transferred) {
|
||||||
try {
|
if (ec && ec.value() != boost::asio::error::operation_aborted) {
|
||||||
// Send the data back over socket.
|
|
||||||
socket_->write(txt.c_str(), len);
|
|
||||||
|
|
||||||
} catch (const std::exception& ex) {
|
|
||||||
// Response transmission failed. Since the response failed, it doesn't
|
|
||||||
// make sense to send any status codes. Let's log it and be done with
|
|
||||||
// it.
|
|
||||||
LOG_ERROR(command_logger, COMMAND_SOCKET_WRITE_FAIL)
|
LOG_ERROR(command_logger, COMMAND_SOCKET_WRITE_FAIL)
|
||||||
.arg(len).arg(socket_->getNative()).arg(ex.what());
|
.arg(socket_->getNative()).arg(ec.message());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
response_.erase(0, bytes_transferred);
|
||||||
|
if (!response_.empty()) {
|
||||||
|
doSend();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_pool_.stop(shared_from_this());
|
connection_pool_.stop(shared_from_this());
|
||||||
|
@@ -88,13 +88,6 @@ over command socket identified by specified file descriptor.
|
|||||||
This error message indicates that an error was encountered while
|
This error message indicates that an error was encountered while
|
||||||
reading from command socket.
|
reading from command socket.
|
||||||
|
|
||||||
% COMMAND_SOCKET_RESPONSE_TOOLARGE Server's response was larger (%1) than supported 64KB
|
|
||||||
This error message indicates that the server received a command and generated
|
|
||||||
an answer for it, but that response was larger than supported 64KB. Server
|
|
||||||
will attempt to send the first 64KB of the response. Depending on the nature
|
|
||||||
of this response, this may indicate a software or configuration error. Future
|
|
||||||
Kea versions are expected to have better support for large responses.
|
|
||||||
|
|
||||||
% COMMAND_SOCKET_UNIX_CLOSE Command socket closed: UNIX, fd=%1, path=%2
|
% COMMAND_SOCKET_UNIX_CLOSE Command socket closed: UNIX, fd=%1, path=%2
|
||||||
This informational message indicates that the daemon closed a command
|
This informational message indicates that the daemon closed a command
|
||||||
processing socket. This was a UNIX socket. It was opened with the file
|
processing socket. This was a UNIX socket. It was opened with the file
|
||||||
@@ -109,6 +102,6 @@ descriptor and path specified.
|
|||||||
This debug message indicates that the specified number of bytes was sent
|
This debug message indicates that the specified number of bytes was sent
|
||||||
over command socket identifier by the specified file descriptor.
|
over command socket identifier by the specified file descriptor.
|
||||||
|
|
||||||
% COMMAND_SOCKET_WRITE_FAIL Error while writing %1 bytes to command socket %2 : %3
|
% COMMAND_SOCKET_WRITE_FAIL Error while writing to command socket %1 : %2
|
||||||
This error message indicates that an error was encountered while
|
This error message indicates that an error was encountered while
|
||||||
attempting to send a response to the command socket.
|
attempting to send a response to the command socket.
|
||||||
|
@@ -95,7 +95,6 @@ bool UnixControlClient::getResponse(std::string& response) {
|
|||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
case 0:
|
case 0:
|
||||||
ADD_FAILURE() << "No response data sent";
|
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Reference in New Issue
Block a user