add listener foundation
This commit is contained in:
parent
d48fb807de
commit
0021fce1be
@ -1,10 +1,15 @@
|
|||||||
|
|
||||||
#ifndef _IF_GLOBAL_HG_
|
#ifndef _IF_GLOBAL_HG_
|
||||||
#define _IF_GLOBAL_HG_
|
#define _IF_GLOBAL_HG_
|
||||||
|
#include <string>
|
||||||
#include <wolfssl/options.h>
|
#include <wolfssl/options.h>
|
||||||
#include <wolfssl/ssl.h>
|
#include <wolfssl/ssl.h>
|
||||||
extern WOLFSSL_CTX *ctx;
|
extern WOLFSSL_CTX *ctx;
|
||||||
extern int sockfd;
|
extern int sockfd;
|
||||||
|
extern std::string interface_name;
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
#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
|
#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/cleanup.h"
|
||||||
#include "../common/const.h"
|
#include "../common/const.h"
|
||||||
|
#include "../common/global.h"
|
||||||
#include "IF_functions.h"
|
#include "IF_functions.h"
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
@ -17,10 +18,6 @@
|
|||||||
#include <wolfssl/options.h>
|
#include <wolfssl/options.h>
|
||||||
#include <wolfssl/ssl.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,
|
void process_incoming_ip_packet(unsigned char *buffer, int packet_size,
|
||||||
WOLFSSL *ssl) {
|
WOLFSSL *ssl) {
|
||||||
buffer[0] = IP_PACKET_TYPE; // Set message type
|
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