2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-01 06:25:34 +00:00

[3902] UnixControlClient moved to lib/testutils

This commit is contained in:
Tomek Mrugalski
2015-07-14 15:02:45 +02:00
parent c0d2c32d02
commit c6b6ea4048
5 changed files with 224 additions and 144 deletions

View File

@@ -19,6 +19,7 @@
#include <dhcpsrv/cfgmgr.h>
#include <dhcp6/ctrl_dhcp6_srv.h>
#include <hooks/hooks_manager.h>
#include <testutils/unix_control_client.h>
#include "marker_file.h"
#include "test_libraries.h"
@@ -39,150 +40,6 @@ using namespace isc::hooks;
namespace {
/// Class that acts as a UnixCommandSocket client
/// It can connect to an open UnixCommandSocket and exchange ControlChannel
/// commands and responses.
class UnixControlClient {
public:
UnixControlClient() {
socket_fd_ = -1;
}
~UnixControlClient() {
disconnectFromServer();
}
/// @brief Closes the Control Channel socket
void disconnectFromServer() {
if (socket_fd_ >= 0) {
static_cast<void>(close(socket_fd_));
socket_fd_ = -1;
}
}
/// @brief Connects to a Unix socket at the given path
/// @param socket_path pathname of the socket to open
/// @return true if the connect was successful, false otherwise
bool connectToServer(const std::string& socket_path) {
// Create UNIX socket
socket_fd_ = socket(AF_UNIX, SOCK_STREAM, 0);
if (socket_fd_ < 0) {
const char* errmsg = strerror(errno);
ADD_FAILURE() << "Failed to open unix stream socket: " << errmsg;
return (false);
}
struct sockaddr_un srv_addr;
if (socket_path.size() > sizeof(srv_addr.sun_path) - 1) {
ADD_FAILURE() << "Socket path specified (" << socket_path
<< ") is larger than " << (sizeof(srv_addr.sun_path) - 1)
<< " allowed.";
disconnectFromServer();
return (false);
}
// Prepare socket address
memset(&srv_addr, 0, sizeof(srv_addr));
srv_addr.sun_family = AF_UNIX;
strncpy(srv_addr.sun_path, socket_path.c_str(),
sizeof(srv_addr.sun_path));
socklen_t len = sizeof(srv_addr);
// Connect to the specified UNIX socket
int status = connect(socket_fd_, (struct sockaddr*)&srv_addr, len);
if (status == -1) {
const char* errmsg = strerror(errno);
ADD_FAILURE() << "Failed to connect unix socket: fd=" << socket_fd_
<< ", path=" << socket_path << " : " << errmsg;
disconnectFromServer();
return (false);
}
return (true);
}
/// @brief Sends the given command across the open Control Channel
/// @param command the command text to execute in JSON form
/// @return true if the send succeeds, false otherwise
bool sendCommand(const std::string& command) {
// Send command
int bytes_sent = send(socket_fd_, command.c_str(), command.length(), 0);
if (bytes_sent < command.length()) {
const char* errmsg = strerror(errno);
ADD_FAILURE() << "Failed to send " << command.length()
<< " bytes, send() returned " << bytes_sent
<< " : " << errmsg;
return (false);
}
return (true);
}
/// @brief Reads the response text from the open Control Channel
/// @param response variable into which the received response should be
/// placed.
/// @return true if data was successfully read from the socket,
/// false otherwise
bool getResponse(std::string& response) {
// Receive response
// @todo implement select check to see if data is waiting
char buf[65536];
memset(buf, 0, sizeof(buf));
switch (selectCheck()) {
case -1: {
const char* errmsg = strerror(errno);
ADD_FAILURE() << "getResponse - select failed: " << errmsg;
return (false);
}
case 0:
ADD_FAILURE() << "No response data sent";
return (false);
default:
break;
}
int bytes_rcvd = recv(socket_fd_, buf, sizeof(buf), 0);
if (bytes_rcvd < 0) {
const char* errmsg = strerror(errno);
ADD_FAILURE() << "Failed to receive a response. recv() returned "
<< bytes_rcvd << " : " << errmsg;
return (false);
}
if (bytes_rcvd >= sizeof(buf)) {
ADD_FAILURE() << "Response size too large: " << bytes_rcvd;
return (false);
}
// Convert the response to a string
response = string(buf, bytes_rcvd);
return (true);
}
/// @brief Uses select to poll the Control Channel for data waiting
/// @return -1 on error, 0 if no data is available, 1 if data is ready
int selectCheck() {
int maxfd = 0;
fd_set read_fds;
FD_ZERO(&read_fds);
// Add this socket to listening set
FD_SET(socket_fd_, &read_fds);
maxfd = socket_fd_;
struct timeval select_timeout;
select_timeout.tv_sec = 0;
select_timeout.tv_usec = 0;
return (select(maxfd + 1, &read_fds, NULL, NULL, &select_timeout));
}
/// @brief Retains the fd of the open socket
int socket_fd_;
};
class NakedControlledDhcpv6Srv: public ControlledDhcpv6Srv {