Browse Source

compile fixes

nodeinfo-routing-update
Evgeny 1 month ago
parent
commit
8502451ec7
  1. 3
      .gitignore
  2. 2
      lib/u_async.c
  3. 4
      src/config_parser.c
  4. 1
      src/config_parser.h
  5. 19
      src/control_server.c
  6. 2
      src/etcp_api.h
  7. 65
      src/etcp_connections.c
  8. 3
      src/etcp_connections.h
  9. BIN
      tests/bench_timeout_heap
  10. BIN
      tests/bench_uasync_timeouts
  11. 198
      tests/test_dummynet_simple.c

3
.gitignore vendored

@ -7,6 +7,7 @@
*.so.*
utun
*.exe
*[^.]* # binaries
# Autotools
Makefile
@ -53,7 +54,7 @@ tests/*.trs
tests/logs/
# Test binaries (files without extension in tests/)
tests/test_*
# All log files
*.log

2
lib/u_async.c

@ -10,7 +10,7 @@
#include <limits.h>
#include <pthread.h>
#ifndef _WIN32
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/time.h>

4
src/config_parser.c

@ -282,6 +282,10 @@ static int parse_global(const char *key, const char *value, struct global_config
global->keepalive_timeout = atoi(value);
return 0;
}
if (strcmp(key, "keepalive_interval") == 0) {
global->keepalive_interval = atoi(value);
return 0;
}
if (strcmp(key, "control_ip") == 0) {
// Store for later processing with control_port
return 0; // We'll handle this when we see control_port

1
src/config_parser.h

@ -78,6 +78,7 @@ struct global_config {
int tun_test_mode; // test mode: 1 = don't open real TUN, queues only
int keepalive_timeout; // keepalive timeout in ms (default: 2000)
int keepalive_interval; // keepalive interval in ms (default: 200)
};
struct utun_config {

19
src/control_server.c

@ -236,20 +236,18 @@ void control_server_shutdown(struct control_server* server) {
while (server->clients) {
close_client(server, server->clients);
}
/* Close listening socket */
#ifdef _WIN32
if (server->listen_fd != INVALID_SOCKET) {
uasync_remove_socket_t(server->ua, server->listen_fd);
server->listen_socket_id = NULL;
}
#ifdef _WIN32
if (server->listen_fd != INVALID_SOCKET) {
closesocket(server->listen_fd);
server->listen_fd = INVALID_SOCKET;
}
#else
if (server->listen_fd >= 0) {
uasync_remove_socket_t(server->ua, server->listen_fd);
server->listen_socket_id = NULL;
close(server->listen_fd);
server->listen_fd = -1;
}
@ -506,19 +504,16 @@ static void close_client(struct control_server* server, struct control_client* c
(unsigned long long)get_timestamp_ms());
fflush(server->log_file);
}
/* Remove from uasync */
if (client->fd != INVALID_SOCKET) {
uasync_remove_socket_t(server->ua, client->fd);
}
/* Close socket */
#ifdef _WIN32
if (client->fd != INVALID_SOCKET) {
uasync_remove_socket_t(server->ua, client->fd);
closesocket(client->fd);
}
#else
if (client->fd >= 0) {
uasync_remove_socket_t(server->ua, client->fd);
close(client->fd);
}
#endif

2
src/etcp_api.h

@ -80,7 +80,7 @@ int etcp_bind(struct UTUN_INSTANCE* inst, uint8_t id, etcp_recv_fn callback);
int etcp_unbind(struct UTUN_INSTANCE* inst, uint8_t id);
/**
* @brief Коллбэк для очередей output ll_queue normalizer
* @brief Внутренняя функция etcp: Коллбэк для очередей output ll_queue normalizer
*
* Собирает пакеты из всех подключений и отправляет в bind->cbk
* по ID (первый байт кодограммы).

65
src/etcp_connections.c

@ -33,7 +33,7 @@ static void packet_dump(const char* prefix, const uint8_t* data, size_t len, str
log_dump(prefix, data, len);
}
static void etcp_link_send_init(struct ETCP_LINK* link);
static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset);
static int etcp_link_send_reset(struct ETCP_LINK* link);
static void etcp_link_init_timer_cbk(void* arg);
static void etcp_link_send_keepalive(struct ETCP_LINK* link);
@ -42,7 +42,7 @@ static void keepalive_timer_cb(void* arg);
#define INIT_TIMEOUT_INITIAL 500
#define INIT_TIMEOUT_MAX 50000
static void etcp_link_send_init_internal(struct ETCP_LINK* link, uint8_t reset) {
static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "etcp_link_send_init link=%p, is_server=%d, reset=%d", link, link ? link->is_server : -1, reset);
if (!link || !link->etcp || !link->etcp->instance) return;
@ -111,23 +111,13 @@ static void etcp_link_send_init_internal(struct ETCP_LINK* link, uint8_t reset)
}
}
// Wrapper for backward compatibility - sends init WITH reset (0x02)
static void etcp_link_send_init(struct ETCP_LINK* link) {
etcp_link_send_init_internal(link, 1);
}
// Send init WITHOUT reset (0x04) - for link recovery
static void etcp_link_send_channel_init(struct ETCP_LINK* link) {
etcp_link_send_init_internal(link, 0);
}
static void etcp_link_init_timer_cbk(void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
struct ETCP_LINK* link = (struct ETCP_LINK*)arg;
if (!link || link->initialized || link->is_server != 0) return;
link->init_timer = NULL;
etcp_link_send_init(link);
etcp_link_send_init(link,1);
}
// Send empty keepalive packet (only timestamp, no sections)
@ -169,24 +159,19 @@ static int etcp_all_links_down(struct ETCP_CONN* etcp) {
}
// Start link recovery process - send CHANNEL_INIT (0x04) on all links
static void etcp_start_link_recovery(struct ETCP_CONN* etcp) {
if (!etcp) return;
static void etcp_start_link_recovery(struct ETCP_LINK* link) {
if (!link) return;
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Starting link recovery - all links are down",
etcp->log_name ? etcp->log_name : "????→????");
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Starting link recovery - all links are down", link->etcp->log_name ? link->etcp->log_name : "????→????");
struct ETCP_LINK* link = etcp->links;
while (link) {
if (link->is_server == 0) { // Only client links
// Reset link state for recovery
link->initialized = 0;
// Send CHANNEL_INIT (0x04) without reset
etcp_link_send_channel_init(link);
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Sent CHANNEL_INIT on link %p for recovery",
etcp->log_name, link);
}
link = link->next;
struct ETCP_CONN* etcp = link->etcp;
if (link->is_server == 0) { // Only client links
// Send CHANNEL_INIT (0x04) without reset
etcp_link_send_init(link, 0);
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Sent CHANNEL_INIT on link %p for recovery",
etcp->log_name, link);
}
link = link->next;
}
// Cancel init_timer for all links of an ETCP_CONN
@ -215,10 +200,10 @@ static void keepalive_timer_cb(void* arg) {
// Check if all links are down and start recovery if needed (client only)
if (link->is_server == 0 && etcp_all_links_down(link->etcp)) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] All links are down, starting recovery",
link->etcp->log_name);
etcp_start_link_recovery(link->etcp);
// Don't restart keepalive timer during recovery
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] All links are down, starting recovery", link->etcp->log_name);
etcp_start_link_recovery(link);
if (link->recovery_interval==0) link->recovery_interval=link->keepalive_interval*10;
link->keepalive_timer = uasync_set_timeout(link->etcp->instance->ua, link->recovery_interval, link, keepalive_timer_cb);
return;
}
@ -247,8 +232,7 @@ static void keepalive_timer_cb(void* arg) {
if (link->recv_keepalive != 1) {
link->recv_keepalive = 1; // up
// loadbalancer_link_ready(link);
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Link %p (local_id=%d) recv status changed to UP",
link->etcp->log_name, link, link->local_link_id);
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Link %p (local_id=%d) recv status changed to UP", link->etcp->log_name, link, link->local_link_id);
}
}
@ -256,8 +240,8 @@ static void keepalive_timer_cb(void* arg) {
if (!link->pkt_sent_since_keepalive) {
etcp_link_send_keepalive(link);
} else {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Keepalive skipped - packet sent since last tick",
link->etcp->log_name);
// DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Keepalive skipped - packet sent since last tick", link->etcp->log_name);
link->recovery_interval=0;
}
// Reset flag for next interval
@ -567,7 +551,6 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn
link->etcp = etcp;
link->is_server = is_server;
link->mtu = 1500;
link->keepalive_interval = 30;
link->initialized = 0;
link->init_timer = NULL;
link->init_timeout = 0;
@ -577,8 +560,10 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn
// Initialize keepalive timeout from global config
if (etcp->instance && etcp->instance->config) {
link->keepalive_timeout = etcp->instance->config->global.keepalive_timeout;
link->keepalive_interval = etcp->instance->config->global.keepalive_interval;
} else {
link->keepalive_timeout = 2000; // Default 2 seconds
link->keepalive_interval = 200; // Default 0.2 s
}
// Выделяем свободный local_link_id
@ -604,7 +589,7 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn
if (is_server == 0) {
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "etcp_link_new: client link, calling etcp_link_send_init");
etcp_link_send_init(link);
etcp_link_send_init(link,1);
}
return link;
@ -806,7 +791,7 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
}
if (link!=NULL && link->etcp!=NULL && link->etcp->crypto_ctx.session_ready) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Decrypt start (normal)");
// DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Decrypt start (normal)");
if (!sc_decrypt(&link->etcp->crypto_ctx, data, recv_len, (uint8_t*)&pkt->timestamp, &pkt_len)) {
// Normal decryption succeeded - process packet normally
goto process_decrypted;
@ -992,7 +977,7 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
return;
process_decrypted:
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Decrypt end");
// DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Decrypt end");
if (pkt_len<3) { errorcode=46; DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback: decrypted packet too small, size=%zu", pkt_len); goto ec_fr; }
pkt->data_len=pkt_len-3;
pkt->noencrypt_len=0;

3
src/etcp_connections.h

@ -58,7 +58,8 @@ struct ETCP_LINK {
// Параметры соединения
uint16_t mtu; // MTU удаленного узла
uint16_t keepalive_interval; // Keepalive интервал
uint16_t keepalive_interval; // Keepalive интервал (x1ms)
uint32_t recovery_interval; // recovery интервал (x0.1ms)
uint8_t is_server; // инициирует подключение клиент
uint8_t initialized; // Флаг инициализации (1=подтверждено или получен request)
uint8_t local_link_id; // id моего линка

BIN
tests/bench_timeout_heap

Binary file not shown.

BIN
tests/bench_uasync_timeouts

Binary file not shown.

198
tests/test_dummynet_simple.c

@ -1,198 +0,0 @@
#include <inttypes.h>
/**
* @file test_dummynet_simple.c
* @brief Упрощённый тест модуля dummynet
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#include <pthread.h>
#include "../lib/u_async.h"
#include "../lib/socket_compat.h"
#include "../lib/debug_config.h"
#include "../src/dummynet.h"
#define LISTEN_PORT 17000
#define PKT_COUNT 100
#define MAX_PKT_SIZE 1500
struct test_header {
uint32_t seq_num;
uint64_t send_time_us;
} __attribute__((packed));
static int tests_passed = 0;
static int tests_failed = 0;
static inline uint64_t get_time_us(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)tv.tv_sec * 1000000ULL + tv.tv_usec;
}
static socket_t create_bound_socket(uint16_t port) {
socket_t sock = socket_create_udp(AF_INET);
if (sock == SOCKET_INVALID) return SOCKET_INVALID;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(port);
int reuse = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
socket_close_wrapper(sock);
return SOCKET_INVALID;
}
return sock;
}
/* Функция для запуска uasync в отдельном потоке */
static void* uasync_thread(void* arg) {
struct UASYNC* ua = (struct UASYNC*)arg;
printf(" [uasync] Event loop started\n");
/* Запускаем цикл на 5 секунд */
for (int i = 0; i < 500; i++) {
uasync_poll(ua, 10); /* 10 timebase = 1ms */
usleep(1000); /* 1ms */
}
printf(" [uasync] Event loop finished\n");
return NULL;
}
int main(void) {
printf("========================================\n");
printf("Dummynet Simple Test\n");
printf("========================================\n\n");
srand((unsigned int)time(NULL));
debug_config_init();
debug_set_level(DEBUG_LEVEL_WARN);
socket_platform_init();
struct UASYNC* ua = uasync_create();
if (!ua) {
printf("[FAIL] Failed to create uasync\n");
return 1;
}
/* Создаём сокеты */
socket_t sock_a = create_bound_socket(LISTEN_PORT - 1);
socket_t sock_b = create_bound_socket(LISTEN_PORT + 1);
if (sock_a == SOCKET_INVALID || sock_b == SOCKET_INVALID) {
printf("[FAIL] Failed to create sockets\n");
return 1;
}
/* Создаём dummynet с задержкой 50ms и jitter 20ms */
struct dummynet* dn = dummynet_create(ua, "127.0.0.1", LISTEN_PORT);
if (!dn) {
printf("[FAIL] Failed to create dummynet\n");
return 1;
}
dummynet_set_direction(dn, DUMMYNET_FORWARD,
50, 20, /* delay: 50ms + 0..20ms */
0, /* unlimited bandwidth */
100, /* max queue */
0, /* no loss */
"127.0.0.1", LISTEN_PORT + 1);
dummynet_set_direction(dn, DUMMYNET_BACKWARD,
50, 20,
0,
100,
0,
"127.0.0.1", LISTEN_PORT - 1);
printf("Configuration:\n");
printf(" Listen port: %d\n", LISTEN_PORT);
printf(" Delay: 50ms + 0-20ms\n");
printf(" Bandwidth: unlimited\n");
printf(" Queue size: 100 packets\n");
printf(" Loss: 0%%\n\n");
/* Запускаем uasync в отдельном потоке */
pthread_t thread;
pthread_create(&thread, NULL, uasync_thread, ua);
/* Отправляем пакеты */
printf("Sending %d packets A->B and B->A...\n", PKT_COUNT);
uint8_t buf[sizeof(struct test_header) + 100];
struct test_header* hdr = (struct test_header*)buf;
for (int i = 0; i < PKT_COUNT; i++) {
/* A -> B */
hdr->seq_num = i;
hdr->send_time_us = get_time_us();
struct sockaddr_in dest;
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("127.0.0.1");
dest.sin_port = htons(LISTEN_PORT);
socket_sendto(sock_a, buf, sizeof(buf), (struct sockaddr*)&dest, sizeof(dest));
/* B -> A */
hdr->seq_num = i + 1000;
hdr->send_time_us = get_time_us();
socket_sendto(sock_b, buf, sizeof(buf), (struct sockaddr*)&dest, sizeof(dest));
usleep(1000); /* 1ms между пакетами */
}
printf("Waiting for packets...\n");
/* Ждём завершения потока uasync */
pthread_join(thread, NULL);
/* Получаем статистику */
const struct dummynet_stats* stats_fw = dummynet_get_stats(dn, DUMMYNET_FORWARD);
const struct dummynet_stats* stats_bw = dummynet_get_stats(dn, DUMMYNET_BACKWARD);
printf("\nResults:\n");
printf(" Forward (A->B): recv=%llu, sent=%llu, dropped=%llu\n",
stats_fw->recv, stats_fw->sent, stats_fw->dropped);
printf(" Backward (B->A): recv=%llu, sent=%llu, dropped=%llu\n",
stats_bw->recv, stats_bw->sent, stats_bw->dropped);
/* Проверяем результаты */
int passed = 1;
if (stats_fw->recv < PKT_COUNT * 0.9 || stats_bw->recv < PKT_COUNT * 0.9) {
printf("\n[FAIL] Expected >90%% packets received\n");
printf(" Forward: %llu/%d, Backward: %llu/%d\n",
stats_fw->recv, PKT_COUNT, stats_bw->recv, PKT_COUNT);
passed = 0;
tests_failed++;
} else {
printf("\n[PASS] >90%% packets received successfully\n");
tests_passed++;
}
/* Очистка */
dummynet_destroy(dn);
socket_close_wrapper(sock_a);
socket_close_wrapper(sock_b);
uasync_destroy(ua, 1);
socket_platform_cleanup();
printf("\n========================================\n");
printf("Results: %d passed, %d failed\n", tests_passed, tests_failed);
printf("========================================\n");
return tests_failed > 0 ? 1 : 0;
}
Loading…
Cancel
Save