Skip to content

Commit

Permalink
Merge pull request #110 from MortezaBashsiz/dev
Browse files Browse the repository at this point in the history
Fix concurent requests issue
  • Loading branch information
MortezaBashsiz authored Sep 30, 2024
2 parents 8d0b247 + ff47e55 commit ec87699
Show file tree
Hide file tree
Showing 20 changed files with 192 additions and 739 deletions.
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

0 comments on commit ec87699

Please sign in to comment.