marlborg-worm / src /network /marlborg_socket.c
SNAPKITTYWEST's picture
push from SNAPKITTYWEST/marlborg-worm
75619b0 verified
Raw
History Blame Contribute Delete
6.13 kB
//
// Copyright (c) 2026 BEL ESPRIT D ACCORD TRUST HOLDINGS INC
// All rights reserved.
#define _POSIX_C_SOURCE 200809L
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MARLBORG_PORT 8443
#define BACKLOG 128
#define BUFFER_SIZE 4096
#define MAX_CLIENTS 1024
#define TIMEOUT_SECONDS 300
typedef struct {
int fd;
struct sockaddr_in addr;
socklen_t addr_len;
time_t last_active;
int is_authenticated;
} marlborg_conn_t;
static marlborg_conn_t connections[MAX_CLIENTS];
static int listen_fd = -1;
static int epoll_fd = -1;
static void marlborg_close_conn(int index);
int marlborg_socket_init(void) {
listen_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
if (listen_fd < 0) {
perror("socket");
return -1;
}
int opt = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
setsockopt(listen_fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_addr.s_addr = INADDR_ANY,
.sin_port = htons(MARLBORG_PORT)
};
if (bind(listen_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
perror("bind");
close(listen_fd);
return -1;
}
if (listen(listen_fd, BACKLOG) < 0) {
perror("listen");
close(listen_fd);
return -1;
}
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (epoll_fd < 0) {
perror("epoll_create1");
close(listen_fd);
return -1;
}
struct epoll_event ev = {
.events = EPOLLIN | EPOLLET,
.data.fd = listen_fd
};
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) < 0) {
perror("epoll_ctl: listen_fd");
close(listen_fd);
close(epoll_fd);
return -1;
}
for (int i = 0; i < MAX_CLIENTS; i++) {
connections[i].fd = -1;
}
return 0;
}
static int marlborg_accept_conn(void) {
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
int conn_fd = accept4(listen_fd,
(struct sockaddr*)&addr,
&addr_len,
SOCK_NONBLOCK | SOCK_CLOEXEC);
if (conn_fd < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
perror("accept4");
}
return -1;
}
for (int i = 0; i < MAX_CLIENTS; i++) {
if (connections[i].fd == -1) {
connections[i] = (marlborg_conn_t){
.fd = conn_fd,
.addr = addr,
.addr_len = addr_len,
.last_active = time(NULL),
.is_authenticated = 0
};
struct epoll_event ev = {
.events = EPOLLIN | EPOLLOUT | EPOLLET,
.data.u64 = (uint64_t)i
};
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev) < 0) {
perror("epoll_ctl: conn");
close(conn_fd);
connections[i].fd = -1;
return -1;
}
return i;
}
}
close(conn_fd);
return -1;
}
static void marlborg_handle_client(int index) {
marlborg_conn_t* conn = &connections[index];
char buffer[BUFFER_SIZE];
ssize_t n;
conn->last_active = time(NULL);
n = read(conn->fd, buffer, BUFFER_SIZE - 1);
if (n > 0) {
buffer[n] = '\0';
printf("Received from %s:%d: %.*s\n",
inet_ntoa(conn->addr.sin_addr),
ntohs(conn->addr.sin_port),
(int)n, buffer);
write(conn->fd, buffer, n);
} else if (n == 0) {
printf("Client %s:%d disconnected\n",
inet_ntoa(conn->addr.sin_addr),
ntohs(conn->addr.sin_port));
marlborg_close_conn(index);
} else if (errno != EAGAIN && errno != EWOULDBLOCK) {
perror("read");
marlborg_close_conn(index);
}
}
static void marlborg_close_conn(int index) {
marlborg_conn_t* conn = &connections[index];
if (conn->fd != -1) {
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, conn->fd, NULL);
close(conn->fd);
conn->fd = -1;
}
}
void marlborg_socket_run(void) {
struct epoll_event events[MAX_CLIENTS];
while (1) {
int nfds = epoll_wait(epoll_fd, events, MAX_CLIENTS, -1);
if (nfds < 0) {
if (errno == EINTR) continue;
perror("epoll_wait");
break;
}
for (int i = 0; i < nfds; i++) {
if (events[i].data.fd == listen_fd) {
int idx = marlborg_accept_conn();
if (idx >= 0) {
printf("New connection from %s:%d (slot %d)\n",
inet_ntoa(connections[idx].addr.sin_addr),
ntohs(connections[idx].addr.sin_port),
idx);
}
} else {
marlborg_handle_client((int)events[i].data.u64);
}
}
time_t now = time(NULL);
for (int i = 0; i < MAX_CLIENTS; i++) {
if (connections[i].fd != -1 &&
(now - connections[i].last_active) > TIMEOUT_SECONDS) {
printf("Timeout: closing connection %d\n", i);
marlborg_close_conn(i);
}
}
}
close(listen_fd);
close(epoll_fd);
}
int main(void) {
if (marlborg_socket_init() < 0) {
fprintf(stderr, "Failed to initialize socket layer\n");
return EXIT_FAILURE;
}
printf("Marlborg-Wormhole socket layer listening on port %d\n", MARLBORG_PORT);
marlborg_socket_run();
return EXIT_SUCCESS;
}