Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix concurent requests issue #110

Merged
merged 9 commits into from
Sep 30, 2024
66 changes: 25 additions & 41 deletions core/src/agenthandler.cpp
Original file line number Diff line number Diff line change
@@ -1,51 +1,41 @@
#include "agenthandler.hpp"

// Constructor for the AgentHandler class
AgentHandler::AgentHandler(boost::asio::streambuf &readBuffer,
boost::asio::streambuf &writeBuffer,
const std::shared_ptr<Config> &config,
const std::shared_ptr<Log> &log,
const TCPClient::pointer &client,
const std::string &clientConnStr,
boost::uuids::uuid uuid)
: config_(config), // Initialize configuration
log_(log), // Initialize logging
client_(client), // Initialize TCP client
readBuffer_(readBuffer), // Reference to the read buffer
writeBuffer_(writeBuffer),// Reference to the write buffer
: config_(config),
log_(log),
client_(client),
readBuffer_(readBuffer),
writeBuffer_(writeBuffer),
request_(HTTP::create(config, log, readBuffer, uuid)),
clientConnStr_(clientConnStr),// Initialize client connection string
clientConnStr_(clientConnStr),
uuid_(uuid) {}

// Destructor for the AgentHandler class
AgentHandler::~AgentHandler() {}

// Main handler function for processing requests
void AgentHandler::handle() {
std::lock_guard<std::mutex> lock(mutex_);// Lock the mutex for thread safety
std::lock_guard<std::mutex> lock(mutex_);

// Initialize encryption status
BoolStr encryption{false, std::string("FAILED")};

// Encrypt the request data from the read buffer
encryption =
aes256Encrypt(hexStreambufToStr(readBuffer_), config_->agent().token);

if (encryption.ok) {
// Log successful token validation
log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Encryption Done]", Log::Level::DEBUG);

// Generate a new HTTP POST request string with the encrypted message
std::string newReq(
request_->genHttpPostReqString(encode64(encryption.message)));

// Check if the request type is valid
if (request_->detectType()) {
// Log the HTTP request details
log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Request] : " + request_->toString(),
Log::Level::DEBUG);

// Log the client connention string and HTTP request target
if (request_->parsedHttpRequest().target().length() > 0) {
log_->write("[" + to_string(uuid_) + "] [CONNECT] [SRC " + clientConnStr_ + "]" + " [DST " +
boost::lexical_cast<std::string>(
Expand All @@ -54,11 +44,9 @@ void AgentHandler::handle() {
Log::Level::INFO);
}

// If the client socket is not open or the request type is HTTP or CONNECT
if (!client_->socket().is_open() ||
request_->httpType() == HTTP::HttpType::http ||
request_->httpType() == HTTP::HttpType::connect) {
// Connect the TCP client to the server
boost::system::error_code ec;
;

Expand All @@ -71,7 +59,6 @@ void AgentHandler::handle() {
Log::Level::INFO);
}

// Check for connection errors
if (ec) {
log_->write(std::string("[" + to_string(uuid_) + "] [AgentHandler handle] Connection error: ") +
ec.message(),
Expand All @@ -80,47 +67,44 @@ void AgentHandler::handle() {
}
}

// Copy the new request to the read buffer
copyStringToStreambuf(newReq, readBuffer_);

// Log the request to be sent to the server
log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Request To Server] : \n" + newReq,
Log::Level::DEBUG);

// Write the request to the client socket and initiate a read
// operation

client_->doWrite(readBuffer_);
client_->doRead();

// Check if there is data available in the read buffer

if (client_->readBuffer().size() > 0) {
// If the HTTP request type is not CONNECT

if (request_->httpType() != HTTP::HttpType::connect) {
// Create an HTTP response handler

HTTP::pointer response =
HTTP::create(config_, log_, client_->readBuffer(), uuid_);

// Parse the HTTP response

if (response->parseHttpResp()) {
// Log the response details

log_->write(
"[" + to_string(uuid_) + "] [AgentHandler handle] [Response] : " + response->restoString(),
Log::Level::DEBUG);

// Decrypt the response body

BoolStr decryption{false, std::string("FAILED")};
decryption =
aes256Decrypt(decode64(boost::lexical_cast<std::string>(
response->parsedHttpResponse().body())),
config_->agent().token);

// Check if decryption was successful

if (decryption.ok) {
// Copy the decrypted message to the write buffer

copyStringToStreambuf(decryption.message, writeBuffer_);
log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Decryption Done]", Log::Level::DEBUG);
} else {
// Log decryption failure and close the socket

log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Decryption Failed] : [ " +
decryption.message + "] ",
Log::Level::DEBUG);
Expand All @@ -130,38 +114,38 @@ void AgentHandler::handle() {
client_->socket().close();
}
} else {
// Log if the response is not an HTTP response

log_->write(
"[AgentHandler handle] [NOT HTTP Response] "
"[Response] : " +
streambufToString(client_->readBuffer()),
Log::Level::DEBUG);
}
} else {
// Log the response to a CONNECT request

log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Response to connect] : \n" +
streambufToString(client_->readBuffer()),
Log::Level::DEBUG);

// Move the response from the read buffer to the write buffer

moveStreambuf(client_->readBuffer(), writeBuffer_);
}
} else {
// Close the socket if no data is available

client_->socket().close();
return;
}
} else {
// Log if the request is not a valid HTTP request

log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [NOT HTTP Request] [Request] : " +
streambufToString(readBuffer_),
Log::Level::DEBUG);
// Close the socket if no data is available

client_->socket().close();
return;
}
} else {
// Log encryption failure and close the socket

log_->write("[" + to_string(uuid_) + "] [AgentHandler handle] [Encryption Failed] : [ " +
encryption.message + "] ",
Log::Level::DEBUG);
Expand All @@ -170,7 +154,7 @@ void AgentHandler::handle() {
client_->socket().remote_endpoint().address().to_string() + ":" +
std::to_string(client_->socket().remote_endpoint().port()) + "] ",
Log::Level::INFO);
// Close the socket if no data is available

client_->socket().close();
return;
}
Expand Down
63 changes: 10 additions & 53 deletions core/src/agenthandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,11 @@
#include "log.hpp"
#include "tcpclient.hpp"

/**
* @brief This class handles requests when the process is running in agent
* mode.
*
* The AgentHandler processes HTTP requests by encrypting/decrypting data,
* forwarding requests to a TCP server, and handling responses.
*/
class AgentHandler : private Uncopyable {
public:
using pointer = std::shared_ptr<AgentHandler>;///< Shared pointer type for
///< AgentHandler
using pointer = std::shared_ptr<AgentHandler>;


/**
* @brief Factory method to create an instance of AgentHandler.
*
* @param readBuffer The buffer to read incoming data from.
* @param writeBuffer The buffer to write outgoing data to.
* @param config Shared configuration object.
* @param log Shared logging object.
* @param client Shared pointer to a TCP client.
* @return pointer A shared pointer to the created AgentHandler instance.
*/
static pointer create(boost::asio::streambuf &readBuffer,
boost::asio::streambuf &writeBuffer,
const std::shared_ptr<Config> &config,
Expand All @@ -42,41 +25,15 @@ class AgentHandler : private Uncopyable {
client, clientConnStr, uuid));
}

~AgentHandler();///< Destructor for AgentHandler
~AgentHandler();

/**
* @brief Handles the HTTP request.
*
* This function is called from the TCPConnection::handleRead function.
* It processes the request, encrypts or decrypts data as needed,
* forwards requests to the server, and handles responses.
*/
void handle();

/**
* @brief Gets a reference to the HTTP request object.
*
* @return The HTTP request object.
*/
inline const HTTP::pointer &request() & { return request_; }

/**
* @brief Gets a rvalue reference to the HTTP request object.
*
* @return The HTTP request object (rvalue).
*/
inline const HTTP::pointer &&request() && { return std::move(request_); }

private:
/**
* @brief Constructs an AgentHandler instance.
*
* @param readBuffer The buffer to read incoming data from.
* @param writeBuffer The buffer to write outgoing data to.
* @param config Shared configuration object.
* @param log Shared logging object.
* @param client Shared pointer to a TCP client.
*/
AgentHandler(boost::asio::streambuf &readBuffer,
boost::asio::streambuf &writeBuffer,
const std::shared_ptr<Config> &config,
Expand All @@ -85,16 +42,16 @@ class AgentHandler : private Uncopyable {
const std::string &clientConnStr,
boost::uuids::uuid uuid);

const std::shared_ptr<Config> &config_;///< Shared configuration object
const std::shared_ptr<Log> &log_; ///< Shared logging object
const TCPClient::pointer &client_; ///< Shared pointer to a TCP client
const std::shared_ptr<Config> &config_;
const std::shared_ptr<Log> &log_;
const TCPClient::pointer &client_;
boost::asio::streambuf &readBuffer_,
&writeBuffer_; ///< References to buffers for reading and writing data
HTTP::pointer request_;///< HTTP request object
&writeBuffer_;
HTTP::pointer request_;
const std::string
&clientConnStr_;///< socket client connection string "ip:port"
&clientConnStr_;

boost::uuids::uuid uuid_;

std::mutex mutex_;///< Mutex to make the class thread-safe
std::mutex mutex_;
};
21 changes: 2 additions & 19 deletions core/src/config.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
#include "config.hpp"

/**
* @brief Constructs a Config instance with specified mode and file path.
*
* @param mode The operational mode of the application (server or agent).
* @param filePath The path to the configuration file.
*/
Config::Config(const RunMode &mode, const std::string &filePath)
: runMode_(mode),
filePath_(filePath),
Expand Down Expand Up @@ -46,11 +40,7 @@ Config::Config(const RunMode &mode, const std::string &filePath)
}
}

/**
* @brief Copy constructor for Config.
*
* @param config A shared pointer to another Config instance.
*/

Config::Config(const Config::pointer &config)
: runMode_(config->runMode()),
configYaml_(YAML::LoadFile(config->filePath())),
Expand All @@ -59,16 +49,9 @@ Config::Config(const Config::pointer &config)
server_(config->server()),
agent_(config->agent()) {}

/**
* @brief Destructor for Config.
*/

Config::~Config() = default;

/**
* @brief Returns a string representation of the current configuration.
*
* @return A string describing the configuration settings.
*/
std::string Config::toString() const {
std::lock_guard<std::mutex> lock(configMutex_);
std::stringstream ss;
Expand Down
4 changes: 2 additions & 2 deletions core/src/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <yaml-cpp/yaml.h>

#include <memory>
#include <mutex>// Include mutex header for thread safety
#include <mutex>
#include <sstream>

#include "general.hpp"
Expand Down Expand Up @@ -50,7 +50,7 @@ class Config : private Uncopyable {
std::string listenIp_;
unsigned short listenPort_;

mutable std::mutex configMutex_;// Mutex for thread safety
mutable std::mutex configMutex_;

explicit Config(const RunMode &mode, const std::string &filePath);

Expand Down
Loading
Loading