0% found this document useful (0 votes)
2 views4 pages

Multi-threaded HTTP Script Server

This document is a C++ program that implements a multi-threaded HTTP server using the ASIO library. It allows for the management and execution of Lua scripts stored in a specified directory, providing endpoints to list, read, and execute these scripts. The program includes thread synchronization mechanisms and ensures the script directory exists before starting the server.

Uploaded by

asserelhajab
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views4 pages

Multi-threaded HTTP Script Server

This document is a C++ program that implements a multi-threaded HTTP server using the ASIO library. It allows for the management and execution of Lua scripts stored in a specified directory, providing endpoints to list, read, and execute these scripts. The program includes thread synchronization mechanisms and ensures the script directory exists before starting the server.

Uploaded by

asserelhajab
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

#include <iostream>

#include <filesystem>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <mutex>
#include <thread>
#include <queue>
#include <condition_variable>
#include <future>
#include <[Link]>

using namespace std;


namespace fs = std::filesystem;

// Configuration
const int PORT = 3000;
const int MAX_THREADS = std::thread::hardware_concurrency();
const std::string SCRIPTS_DIR = "scripts";

// Thread synchronization
std::mutex queueMutex;
std::condition_variable queueCond;
std::queue<std::function<void()>> taskQueue;
bool stopProcessing = false;

// Thread Pool
std::vector<std::thread> workers;

void log_info(const std::string& msg) { std::cout << "[INFO] " << msg << std::endl;
}
void log_error(const std::string& msg) { std::cerr << "[ERROR] " << msg <<
std::endl; }

// Worker Thread Function


void worker_thread() {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(queueMutex);
[Link](lock, [] { return ![Link]() ||
stopProcessing; });

if (stopProcessing && [Link]()) return;


task = std::move([Link]());
[Link]();
}
task();
}
}

// Initialize Thread Pool


void start_thread_pool() {
for (int i = 0; i < MAX_THREADS; i++) {
workers.emplace_back(worker_thread);
}
}
// Stop Thread Pool
void stop_thread_pool() {
{
std::unique_lock<std::mutex> lock(queueMutex);
stopProcessing = true;
}
queueCond.notify_all();
for (std::thread& worker : workers) {
[Link]();
}
}

// Ensure Script Directory Exists


void ensure_directory_exists() {
if (!fs::exists(SCRIPTS_DIR)) {
fs::create_directory(SCRIPTS_DIR);
}
}

// Read a file safely


std::string read_file(const std::string& filePath) {
std::ifstream file(filePath, std::ios::binary);
if (!file) return "Error: Unable to open file";

std::ostringstream buffer;
buffer << [Link]();
return [Link]();
}

// Secure Script Execution


std::string execute_script(const std::string& scriptPath) {
if (!fs::exists(scriptPath) || !fs::is_regular_file(scriptPath)) return "Error:
Script not found";

std::string command = "lua " + scriptPath + " 2>&1"; // Example using Lua
std::array<char, 128> buffer;
std::string result;
FILE* pipe = popen(command.c_str(), "r");

if (!pipe) return "Error: Execution failed";


while (fgets([Link](), [Link](), pipe) != nullptr) {
result += [Link]();
}

pclose(pipe);
return result;
}

// HTTP Server Class (Custom)


class CustomHTTPServer {
private:
asio::io_context io_context;
asio::ip::tcp::acceptor acceptor;

public:
CustomHTTPServer(int port)
: acceptor(io_context, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port))
{}
void start() {
log_info("Server running on port " + std::to_string(PORT));
accept_connections();
io_context.run();
}

private:
void accept_connections() {
auto socket = std::make_shared<asio::ip::tcp::socket>(io_context);
acceptor.async_accept(*socket, [this, socket](std::error_code ec) {
if (!ec) {
handle_request(socket);
}
accept_connections();
});
}

void handle_request(std::shared_ptr<asio::ip::tcp::socket> socket) {


auto buffer = std::make_shared<asio::streambuf>();
asio::async_read_until(*socket, *buffer, "\r\n\r\n",
[this, socket, buffer](std::error_code ec, std::size_t) {
if (!ec) {
std::istream requestStream([Link]());
std::string requestLine;
std::getline(requestStream, requestLine);

std::istringstream iss(requestLine);
std::string method, path, protocol;
iss >> method >> path >> protocol;

std::ostringstream response;
if (path == "/scripts") {
handle_scripts_list(response);
}
else if ([Link]("/scripts/", 0) == 0) {
handle_script_read([Link](9), response);
}
else if ([Link]("/execute/", 0) == 0) {
handle_script_execute([Link](9), response);
}
else {
response << "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\
n\r\n";
}

asio::async_write(*socket, asio::buffer([Link]()),
[socket](std::error_code, std::size_t) {});
}
});
}

void handle_scripts_list(std::ostringstream& response) {


std::vector<std::string> scriptFiles;
for (const auto& entry : fs::directory_iterator(SCRIPTS_DIR)) {
if (fs::is_regular_file([Link]())) {
scriptFiles.push_back([Link]().filename().string());
}
}
std::ostringstream jsonResponse;
jsonResponse << "{ \"scripts\": [";
for (size_t i = 0; i < [Link](); ++i) {
if (i > 0) jsonResponse << ",";
jsonResponse << "\"" << scriptFiles[i] << "\"";
}
jsonResponse << "] }";

response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n";


response << "Content-Length: " << [Link]().size() << "\r\n\r\n";
response << [Link]();
}

void handle_script_read(const std::string& scriptName, std::ostringstream&


response) {
fs::path scriptPath = fs::path(SCRIPTS_DIR) / scriptName;
std::string fileContent = read_file([Link]());

response << "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n";


response << "Content-Length: " << [Link]() << "\r\n\r\n";
response << fileContent;
}

void handle_script_execute(const std::string& scriptName, std::ostringstream&


response) {
fs::path scriptPath = fs::path(SCRIPTS_DIR) / scriptName;
std::string output = execute_script([Link]());

response << "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n";


response << "Content-Length: " << [Link]() << "\r\n\r\n";
response << output;
}
};

int main() {
try {
ensure_directory_exists();
start_thread_pool();
CustomHTTPServer server(PORT);
[Link]();
} catch (const std::exception& e) {
log_error("Fatal error: " + std::string([Link]()));
}

stop_thread_pool();
return 0;
}

You might also like