From 0021fce1bed1361dd3fc292eb3e5a6d1c1d6b487 Mon Sep 17 00:00:00 2001 From: PoliEcho Date: Sun, 1 Jun 2025 13:13:47 +0200 Subject: [PATCH] add listener foundation --- src/common/global.h | 5 ++ src/common/types.h | 135 +++++++++++++++++++++++++++++++++++++++++ src/server/capture.cpp | 5 +- src/server/listen.cpp | 48 +++++++++++++++ src/server/send.cpp | 0 src/server/send.h | 8 +++ 6 files changed, 197 insertions(+), 4 deletions(-) create mode 100644 src/common/types.h create mode 100644 src/server/listen.cpp create mode 100644 src/server/send.cpp create mode 100644 src/server/send.h diff --git a/src/common/global.h b/src/common/global.h index c6670e7..3900e82 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -1,10 +1,15 @@ #ifndef _IF_GLOBAL_HG_ #define _IF_GLOBAL_HG_ +#include #include #include extern WOLFSSL_CTX *ctx; extern int sockfd; +extern std::string interface_name; #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +// this is max size standard Ipv4/6 packet can be plus 1 for message type +// what in understand in practise it is much lower around 1500 bytes +#define IP_PACKET_BUFFER_SIZE 65536 + 1 #endif \ No newline at end of file diff --git a/src/common/types.h b/src/common/types.h new file mode 100644 index 0000000..9006afa --- /dev/null +++ b/src/common/types.h @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +#include + +#ifndef TYPES_H +#define TYPES_H +template class Timer { +public: + using TimerCallback = std::function; + + enum class TimerType { SINGLE_SHOT, PERIODIC }; + +private: + struct CallbackContext { + Timer *timer; + TimerCallback callback; + std::tuple args; + + CallbackContext(Timer *t, TimerCallback cb, Args... arguments) + : timer(t), callback(cb), args(std::make_tuple(arguments...)) {} + }; + + timer_t timerId; + struct sigevent sev; + struct itimerspec its; + std::unique_ptr context; + std::atomic isActive{false}; + std::atomic isCreated{false}; + TimerType timerType; + + static void timerExpired(union sigval sv) { + CallbackContext *ctx = static_cast(sv.sival_ptr); + if (ctx && ctx->timer && ctx->timer->isActive.load()) { + // Unpack tuple and call callback with arguments + std::apply(ctx->callback, ctx->args); + + if (ctx->timer->timerType == TimerType::SINGLE_SHOT) { + ctx->timer->isActive.store(false); + } + } + } + +public: + Timer() { + std::memset(&sev, 0, sizeof(sev)); + std::memset(&its, 0, sizeof(its)); + + sev.sigev_notify = SIGEV_THREAD; + sev.sigev_notify_function = timerExpired; + } + + ~Timer() { + stop(); + if (isCreated.load()) { + timer_delete(timerId); + } + } + + /** + * Arm timer with callback and arguments + */ + void arm(int delayMs, int intervalMs, TimerCallback cb, Args... args, + TimerType type = TimerType::SINGLE_SHOT) { + if (!cb) { + throw std::invalid_argument("Callback function cannot be null"); + } + + stop(); + + // Create context with callback and arguments + context = std::make_unique(this, cb, args...); + timerType = type; + + if (!isCreated.load()) { + sev.sigev_value.sival_ptr = context.get(); + if (timer_create(CLOCK_MONOTONIC, &sev, &timerId) == -1) { + throw std::runtime_error("Failed to create POSIX timer"); + } + isCreated.store(true); + } + + // Configure timer + its.it_value.tv_sec = delayMs / 1000; + its.it_value.tv_nsec = (delayMs % 1000) * 1000000; + + if (type == TimerType::PERIODIC && intervalMs > 0) { + its.it_interval.tv_sec = intervalMs / 1000; + its.it_interval.tv_nsec = (intervalMs % 1000) * 1000000; + } else { + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + } + + if (timer_settime(timerId, 0, &its, nullptr) == -1) { + throw std::runtime_error("Failed to set timer"); + } + + isActive.store(true); + } + + /** + * Reset the timer - restarts with the same configuration + */ + void reset() { + if (!isCreated.load() || !isActive.load()) { + throw std::runtime_error("Timer not armed or not active"); + } + + // Re-arm the timer with the same settings stored in 'its' + if (timer_settime(timerId, 0, &its, nullptr) == -1) { + throw std::runtime_error("Failed to reset timer"); + } + + // For single-shot timers that were previously expired, reactivate them + if (timerType == TimerType::SINGLE_SHOT) { + isActive.store(true); + } + } + + void stop() { + if (isCreated.load() && isActive.load()) { + struct itimerspec disarm = {{0, 0}, {0, 0}}; + timer_settime(timerId, 0, &disarm, nullptr); + isActive.store(false); + } + } + + bool active() const { return isActive.load(); } +}; + +#endif \ No newline at end of file diff --git a/src/server/capture.cpp b/src/server/capture.cpp index a59c62b..eebe90c 100644 --- a/src/server/capture.cpp +++ b/src/server/capture.cpp @@ -1,5 +1,6 @@ #include "../common/cleanup.h" #include "../common/const.h" +#include "../common/global.h" #include "IF_functions.h" #include #include @@ -17,10 +18,6 @@ #include #include -// this is max size standard Ipv4/6 packet can be plus 1 for message type -// what in understand in practise it is much lower around 1500 bytes -#define IP_PACKET_BUFFER_SIZE 65536 + 1 - void process_incoming_ip_packet(unsigned char *buffer, int packet_size, WOLFSSL *ssl) { buffer[0] = IP_PACKET_TYPE; // Set message type diff --git a/src/server/listen.cpp b/src/server/listen.cpp new file mode 100644 index 0000000..6e479bb --- /dev/null +++ b/src/server/listen.cpp @@ -0,0 +1,48 @@ +#include "../common/const.h" +#include "../common/global.h" +#include "../common/types.h" +#include "send.h" +#include +#include +#include +#include + +Timer keep_alive_timer; + +void send_keep_alive(WOLFSSL *ssl) {} + +void listen_for_incoming_packets(WOLFSSL *ssl) { + unsigned char buf[IP_PACKET_BUFFER_SIZE]; + keep_alive_timer.arm( + 180000, 0, [](WOLFSSL *ssl) { send_keep_alive(ssl); }, ssl); + + while (true) { + int bytes = wolfSSL_read(ssl, buf, sizeof(buf) - 1); + if (bytes > 0) { + switch (buf[0]) { + case KEEP_ALIVE_TYPE: { + unsigned char response = KEEPING_ALIVE_TYPE; + wolfSSL_write(ssl, &response, sizeof(response)); + std::clog << "Received keep-alive message, sent response." << std::endl; + keep_alive_timer.reset(); + break; + } + case IP_PACKET_TYPE: { + send_IP_packet(buf + 1, bytes - 1); + break; + } + case TERMINATE_CONNECTION_TYPE: { + std::cout << "Received terminate connection request." << std::endl; + return; + } + } + } else if (bytes == 0) { + std::cout << "Connection closed by peer" << std::endl; + break; + } else { + int ssl_error = wolfSSL_get_error(ssl, bytes); + std::cerr << "wolfSSL_read failed with error: " << ssl_error << std::endl; + break; + } + } +} \ No newline at end of file diff --git a/src/server/send.cpp b/src/server/send.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/server/send.h b/src/server/send.h new file mode 100644 index 0000000..d732daa --- /dev/null +++ b/src/server/send.h @@ -0,0 +1,8 @@ +#ifndef SEND_H +#define SEND_H +#include +#include +#include +int send_IP_packet(const unsigned char *packet, int packet_size); + +#endif // SEND_H \ No newline at end of file