add listener foundation
This commit is contained in:
parent
d48fb807de
commit
0021fce1be
@ -1,10 +1,15 @@
|
||||
|
||||
#ifndef _IF_GLOBAL_HG_
|
||||
#define _IF_GLOBAL_HG_
|
||||
#include <string>
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
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
|
135
src/common/types.h
Normal file
135
src/common/types.h
Normal file
@ -0,0 +1,135 @@
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <signal.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
template <typename... Args> class Timer {
|
||||
public:
|
||||
using TimerCallback = std::function<void(Args...)>;
|
||||
|
||||
enum class TimerType { SINGLE_SHOT, PERIODIC };
|
||||
|
||||
private:
|
||||
struct CallbackContext {
|
||||
Timer *timer;
|
||||
TimerCallback callback;
|
||||
std::tuple<Args...> 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<CallbackContext> context;
|
||||
std::atomic<bool> isActive{false};
|
||||
std::atomic<bool> isCreated{false};
|
||||
TimerType timerType;
|
||||
|
||||
static void timerExpired(union sigval sv) {
|
||||
CallbackContext *ctx = static_cast<CallbackContext *>(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<CallbackContext>(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
|
@ -1,5 +1,6 @@
|
||||
#include "../common/cleanup.h"
|
||||
#include "../common/const.h"
|
||||
#include "../common/global.h"
|
||||
#include "IF_functions.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <cerrno>
|
||||
@ -17,10 +18,6 @@
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
|
||||
// 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
|
||||
|
48
src/server/listen.cpp
Normal file
48
src/server/listen.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "../common/const.h"
|
||||
#include "../common/global.h"
|
||||
#include "../common/types.h"
|
||||
#include "send.h"
|
||||
#include <iostream>
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
#include <wolfssl/wolfcrypt/types.h>
|
||||
|
||||
Timer<WOLFSSL *> 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;
|
||||
}
|
||||
}
|
||||
}
|
0
src/server/send.cpp
Normal file
0
src/server/send.cpp
Normal file
8
src/server/send.h
Normal file
8
src/server/send.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef SEND_H
|
||||
#define SEND_H
|
||||
#include <string>
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
int send_IP_packet(const unsigned char *packet, int packet_size);
|
||||
|
||||
#endif // SEND_H
|
Loading…
x
Reference in New Issue
Block a user