From ede25f9002b1120fdaa6e2a2116893ffdde0db31 Mon Sep 17 00:00:00 2001
From: retoor <retoor@molodetz.nl>
Date: Tue, 8 Apr 2025 06:21:02 +0200
Subject: [PATCH] Update.

---
 Makefile       |  14 +++++++++
 README.md      |  46 +++++++++++++++++++++++++--
 http.hpp       |  50 ++++++++++++++++++++++++++++++
 httpsbench     | Bin 0 -> 36288 bytes
 main.cpp       |  82 +++++++++++++++++++++++++++++++++++++++++++++++++
 threadpool.hpp |  78 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 268 insertions(+), 2 deletions(-)
 create mode 100644 Makefile
 create mode 100644 http.hpp
 create mode 100755 httpsbench
 create mode 100644 main.cpp
 create mode 100644 threadpool.hpp

diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7895687
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+CC=g++
+CFLAGS=-Werror -Wall -Wextra -Ofast -pedantic
+
+all: build
+
+build:
+	$(CC) main.cpp -o httpsbench -lssl -lcrypto -lcurl -pthread $(CFLAGS)
+
+run: build
+	@echo "Usage: ./httpsbench -c <ThreadCount> -n <RequestCount> <URL>"
+	@echo "Example: ./httpsbench -c 10 -n 1000 http://example.com"
+	./httpsbench $(ARGS)
+
+.PHONY: all build run
\ No newline at end of file
diff --git a/README.md b/README.md
index 5c7fe3d..3b5148d 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,45 @@
-# httpsbench
+# HTTPS Benchmark Tool
 
-Application for benchmarking https servers 
\ No newline at end of file
+This tool is designed to benchmark HTTP requests using a thread pool for concurrent execution.
+
+## Usage
+
+To use the tool, compile and run it with the following commands:
+
+```bash
+make build
+./httpsbench -c <ThreadCount> -n <RequestCount> <URL>
+```
+
+### Example
+
+```bash
+./httpsbench -c 10 -n 1000 http://example.com
+```
+
+## Parameters
+
+- `-c <ThreadCount>`: Number of threads to use in the thread pool.
+- `-n <RequestCount>`: Number of HTTP requests to make.
+- `<URL>`: The URL to benchmark.
+
+## Output
+
+The tool will output the elapsed time in seconds and milliseconds, as well as the requests per second.
+
+## Dependencies
+
+- libcurl
+- libssl
+- libcrypto
+
+## Files
+
+- `main.cpp`: Main program file.
+- `threadpool.hpp`: Thread pool implementation.
+- `http.hpp`: HTTP request function declaration.
+- `Makefile`: Build script.
+
+## License
+
+This project is licensed under the MIT License - see the LICENSE.md file for details.
diff --git a/http.hpp b/http.hpp
new file mode 100644
index 0000000..8d8e2bc
--- /dev/null
+++ b/http.hpp
@@ -0,0 +1,50 @@
+#include <curl/curl.h>
+#include <stdio.h>
+
+
+// Callback function for handling data received from the server
+size_t write_callback(void *buffer, size_t size, size_t nmemb, void *userp) {
+    size_t total_size = size * nmemb;
+    fwrite(buffer, size, nmemb, (FILE *)userp);
+    return total_size;
+}
+
+void http_get(const char * url){
+    CURL *curl;
+    CURLcode res;
+ 
+    curl = curl_easy_init();
+
+    if (curl) {
+        // Set the URL for the request
+        curl_easy_setopt(curl, CURLOPT_URL, url);
+
+        // Use HTTPS
+        curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
+
+        // Verify the server's SSL certificate
+        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); // Enable SSL certificate verification
+        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); // Verify that the certificate matches the hostname
+
+        // Optional: Specify CA certificate if the default is not sufficient
+        // curl_easy_setopt(curl, CURLOPT_CAINFO, "/path/to/cacert.pem");
+
+        // Set the write callback function to handle the response
+        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
+        curl_easy_setopt(curl, CURLOPT_WRITEDATA, stdout);
+
+        // Perform the request
+        res = curl_easy_perform(curl);
+
+        // Check for errors
+        if (res != CURLE_OK) {
+            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
+        }
+
+        // Cleanup
+        curl_easy_cleanup(curl);
+    }
+
+}
+
+
diff --git a/httpsbench b/httpsbench
new file mode 100755
index 0000000000000000000000000000000000000000..28cddaa5cf5a916a16f00f91b07e773ffd6f49cd
GIT binary patch
literal 36288
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
Zsy-O=r)25-db*cy<Iuku7!08D{{T9a;;8@t

literal 0
HcmV?d00001

diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..76a307b
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,82 @@
+#include <iostream>
+#include <vector>
+#include <thread>
+#include <queue>
+#include <functional>
+#include <condition_variable>
+#include "threadpool.hpp"
+#include "http.hpp"
+#include <chrono>
+
+std::mutex mtx;  // Mutex to protect shared data
+int threads_working = 0;
+
+// Function to simulate work that requires thread synchronization
+void incThreadsWorking() {
+    mtx.lock();  // Lock the mutex to enter the critical section
+    threads_working++;
+    mtx.unlock();  // Unlock the mutex to allow other threads to enter the critical section
+}
+void decThreadsWorking(){
+    mtx.lock();
+    threads_working--;
+    mtx.unlock();
+}
+
+int main(int argc, char* argv[]) {
+    const char* url = nullptr;
+    int threadCount = 10; // Default value
+    int requestCount = 1000; // Default value
+
+    // Parse command-line arguments
+    for (int i = 1; i < argc; ++i) {
+        if (std::string(argv[i]) == "-c" && i + 1 < argc) {
+            threadCount = std::stoi(argv[++i]);
+        } else if (std::string(argv[i]) == "-n" && i + 1 < argc) {
+            requestCount = std::stoi(argv[++i]);
+        } else {
+            url = argv[i]; // Assume the last argument is the URL
+        }
+    }
+
+    if (url == nullptr) {
+        std::cerr << "Usage: " << argv[0] << " -c <ThreadCount> -n <RequestCount> <URL>" << std::endl;
+        return 1;
+    }
+
+    // Initialize libcurl
+    curl_global_init(CURL_GLOBAL_DEFAULT);
+
+    auto start = std::chrono::steady_clock::now();
+
+    ThreadPool pool(threadCount);  // Create a pool with specified number of threads
+
+    // Submit tasks to the thread pool
+    for (int i = 0; i < requestCount; ++i) {
+        pool.enqueue([url, i] {
+            incThreadsWorking();
+            http_get(url);
+            decThreadsWorking();
+            std::cout << "Threads working: " << threads_working << std::endl;
+        });
+    }
+
+    while(threads_working){
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+    }
+
+    auto end = std::chrono::steady_clock::now();
+    
+    auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - start);
+    std::cout << "Elapsed time in seconds: " << duration.count() << " seconds." << std::endl;
+
+    auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
+    std::cout << "Elapsed time in milliseconds: " << duration_ms.count() << " ms." << std::endl;
+
+    std::cout << "Requests per second: " << requestCount / duration.count() << "." << std::endl;
+
+    // Cleanup global libcurl state
+    curl_global_cleanup();
+
+    return 0;
+}
\ No newline at end of file
diff --git a/threadpool.hpp b/threadpool.hpp
new file mode 100644
index 0000000..5c290a0
--- /dev/null
+++ b/threadpool.hpp
@@ -0,0 +1,78 @@
+#include <iostream>
+#include <vector>
+#include <thread>
+#include <queue>
+#include <functional>
+#include <condition_variable>
+#include <atomic>
+
+class ThreadPool {
+public:
+    ThreadPool(size_t numThreads) : stop(false) {
+        for (size_t i = 0; i < numThreads; ++i) {
+            workers.emplace_back([this] {
+                while (true) {
+                    std::function<void()> task;
+
+                    // Lock the queue to retrieve the next task
+                    {
+                        std::unique_lock<std::mutex> lock(queueMutex);
+                        condition.wait(lock, [this] {
+                            return stop || !tasks.empty();
+                        });
+
+                        if (stop && tasks.empty()) {
+                            return;
+                        }
+
+                        // Get the next task from the queue
+                        task = std::move(tasks.front());
+                        tasks.pop();
+                    }
+
+                    // Execute the task
+                    task();
+                }
+            });
+        }
+    }
+
+    // Submit a task to the thread pool
+    template <typename F>
+    void enqueue(F&& f) {
+        {
+            std::unique_lock<std::mutex> lock(queueMutex);
+            if (stop) {
+                throw std::runtime_error("ThreadPool is stopped");
+            }
+            tasks.push(std::function<void()>(std::forward<F>(f)));
+        }
+        condition.notify_one();
+    }
+
+    // Wait for all threads to finish executing their tasks
+    void wait() {
+        // Block until all tasks have been completed
+        std::unique_lock<std::mutex> lock(queueMutex);
+        condition.wait(lock, [this] { return tasks.empty(); });
+    }
+
+    // Destructor: join all threads
+    ~ThreadPool() {
+        {
+            std::unique_lock<std::mutex> lock(queueMutex);
+            stop = true;
+        }
+        condition.notify_all();
+        for (std::thread& worker : workers) {
+            worker.join();  // Ensure each thread finishes before destruction
+        }
+    }
+
+private:
+    std::vector<std::thread> workers;
+    std::queue<std::function<void()>> tasks;
+    std::mutex queueMutex;
+    std::condition_variable condition;
+    bool stop;
+};