Update emulator uasync lifecycle and document forwarding rules

This commit is contained in:
evgeny committed 2026-10-21 18:12:06 +02:00
1 parent 56d5fcd75a
commit ff3eb02bff
2 files changed
+46 -31

No files matched your search

+16 -9
View File
@@ -3,6 +3,7 @@
#include "net_emulator.h"
#include "u_async.h"
#include "mem.h"
#include "debug_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -79,7 +80,7 @@ static int parse_ip_port(const char *str, struct sockaddr_in *addr) {
static int parse_delay_range(const char *str, delay_range_t *range) {
if (!str || !range) return -1;
char *dash = strchr(str, '-');
const char *dash = strchr(str, '-');
if (!dash) {
// Single value
range->min_ms = atoi(str);
@@ -103,10 +104,10 @@ static int parse_delay_range(const char *str, delay_range_t *range) {
static int parse_rule(const char *line, rule_t *rule) {
if (!line || !rule) return -1;
char *prob_start = strstr(line, "prob=");
const char *prob_start = strstr(line, "prob=");
if (!prob_start) return -1;
char *comma = strchr(prob_start, ',');
const char *comma = strchr(prob_start, ',');
if (!comma) return -1;
// Parse probability
@@ -117,7 +118,7 @@ static int parse_rule(const char *line, rule_t *rule) {
if (rule->probability_percent < 0 || rule->probability_percent > 100) return -1;
// Parse delay
char *delay_start = strstr(comma, "delay=");
const char *delay_start = strstr(comma, "delay=");
if (!delay_start) return -1;
char delay_str[64];
@@ -179,6 +180,7 @@ int parse_emulator_config(const char *filename, net_emulator_t *emulator) {
current_endpoint = &emulator->endpoints[emulator->endpoint_count];
memset(current_endpoint, 0, sizeof(endpoint_t));
current_endpoint->sockfd = -1;
// Parse listen address
if (parse_ip_port(endpoint_str, &current_endpoint->listen_addr) < 0) {
@@ -417,7 +419,7 @@ int net_emulator_init(net_emulator_t *emulator) {
if (create_endpoint_socket(ep) < 0) {
fprintf(stderr, "Failed to create socket for endpoint %s:%u\n",
inet_ntoa(ep->listen_addr.sin_addr), ntohs(ep->listen_addr.sin_port));
uasync_destroy(emulator->ua);
uasync_destroy(emulator->ua, 0);
emulator->ua = NULL;
return -1;
}
@@ -425,7 +427,11 @@ int net_emulator_init(net_emulator_t *emulator) {
ep->emulator = emulator;
// Add socket to u_async
uasync_add_socket(emulator->ua, ep->sockfd, socket_callback, NULL, NULL, "emulator", ep);
if (!uasync_add_socket(emulator->ua, ep->sockfd, socket_callback, NULL, NULL, "emulator", ep)) {
DEBUG_ERROR(DEBUG_CATEGORY_SYS, "net_emulator_init: socket registration failed fd=%d endpoint=%d", ep->sockfd, i);
net_emulator_cleanup(emulator);
return -1;
}
printf("[INIT] Listening on %s:%u\n",
inet_ntoa(ep->listen_addr.sin_addr), ntohs(ep->listen_addr.sin_port));
}
@@ -439,7 +445,7 @@ void net_emulator_run(net_emulator_t *emulator) {
if (!emulator || !emulator->running || !emulator->ua) return;
printf("[EMULATOR] Starting main loop. Press Ctrl+C to stop.\n");
uasync_mainloop(emulator->ua); // This never returns
uasync_mainloop(emulator->ua); // Возвращается после uasync_stop.
}
// Clean up emulator resources
@@ -455,7 +461,7 @@ void net_emulator_cleanup(net_emulator_t *emulator) {
}
if (emulator->ua) {
uasync_destroy(emulator->ua);
uasync_destroy(emulator->ua, 0);
emulator->ua = NULL;
}
@@ -466,6 +472,7 @@ void net_emulator_cleanup(net_emulator_t *emulator) {
int main(int argc, char *argv[]) {
setbuf(stdout, NULL);
setbuf(stderr, NULL);
debug_config_init();
if (argc != 2) {
fprintf(stderr, "Usage: %s <config_file>\n", argv[0]);
@@ -500,4 +507,4 @@ int main(int argc, char *argv[]) {
// Cleanup (never reached)
net_emulator_cleanup(&g_emulator);
return 0;
}
}
+30 -22
View File
@@ -1,4 +1,8 @@
// net_emulator.h - Network emulator for testing utun with delay, loss, reordering
/* IPv4 UDP-эмулятор одного потока uasync: правила случайной задержки и остаточная вероятность потерь.
* Обнулить состояние → parse_emulator_config → init → run → cleanup после возврата из run.
* Конфиг: [IPv4:port], строки prob=N,delay=min-max (мс); до 100 endpoint, до 10 правил на endpoint.
* Для каждого пакета выбирается одно правило по накопленной вероятности; остаток до 100% означает drop.
* Разные задержки могут менять порядок пакетов; отдельного механизма перестановки по reorder_probability нет. */
#ifndef NET_EMULATOR_H
#define NET_EMULATOR_H
@@ -22,8 +26,8 @@ typedef struct net_emulator_s net_emulator_t;
// Delay range (milliseconds)
typedef struct {
int min_ms;
int max_ms;
int min_ms; // Минимальная задержка >=0
int max_ms; // Верхняя граница включительно; max >= min, значение <= INT_MAX/10 для timebase
} delay_range_t;
// Rule: probability and delay
@@ -35,16 +39,15 @@ typedef struct {
// Network endpoint configuration
typedef struct {
struct sockaddr_in listen_addr; // Address to listen on
struct sockaddr_in target_addr; // Address to forward to (port - 10000)
struct sockaddr_in target_addr; // Тот же IP; порт listen-10000 при listen>=10000, иначе исходный порт
rule_t rules[MAX_RULES_PER_ENDPOINT];
int rule_count;
int total_probability; // Sum of probabilities (should be <= 100)
int total_probability; // Сумма 0..100%; вероятность потери — 100-total_probability
// For reordering simulation
int reorder_probability; // Probability to reorder with next packet (0-100)
int reorder_probability; // Не используется и не читается из конфигурации
// Socket descriptor
int sockfd;
int sockfd; // Созданный endpoint-сокет; -1 до создания/после cleanup
net_emulator_t* emulator; // Parent emulator instance
} endpoint_t;
@@ -52,34 +55,39 @@ typedef struct {
struct net_emulator_s {
endpoint_t endpoints[MAX_ENDPOINTS];
int endpoint_count;
int running;
uasync_t* ua; // uasync instance
int running; // init завершён; сам флаг не останавливает mainloop, нужен uasync_stop(ua)
uasync_t* ua; // Принадлежит эмулятору, создаётся init и уничтожается cleanup
};
/**
* @brief Parse configuration file
* @param filename Configuration file path
* @param emulator Emulator state to fill
* @return 0 on success, -1 on error
* @brief Читает endpoint и правила; перед первым вызовом обнулить emulator, живой экземпляр не перенастраивать.
* @param filename путь к конфигу; строки с ';' и пустые пропускаются
* @param emulator состояние, в которое добавляются endpoint; прежние записи не очищаются
* @return 0 после разбора; -1 при NULL, ошибке открытия, неверном endpoint, превышении лимитов/суммы вероятностей
* Ошибочное правило логируется и пропускается без -1; прочие нераспознанные строки игнорируются.
* При -1 уже разобранная часть сохраняется. Диапазон задержек должен помещаться в INT_MAX/10 мс.
*/
int parse_emulator_config(const char *filename, net_emulator_t *emulator);
/**
* @brief Initialize network emulator
* @param emulator Emulator state
* @return 0 on success, -1 on error
* @brief Создаёт собственный uasync и неблокирующие UDP-сокеты настроенных endpoint.
* @param emulator состояние после parse, без живого ua; endpoint/rule counts должны помещаться в массивы
* @return 0 — сокеты созданы и зарегистрированы, -1 — NULL/ошибка ресурсов; после ошибки вызвать cleanup
* При ручном заполнении endpoint до init установить sockfd=-1. Ошибка init может оставить созданные сокеты до cleanup.
*/
int net_emulator_init(net_emulator_t *emulator);
/**
* @brief Run network emulator main loop
* @param emulator Emulator state
* @brief Запускает блокирующий mainloop, возвращается после uasync_stop(emulator->ua).
* @param emulator успешно инициализированное состояние; NULL/нет ua/running=0 ничего не делает
* Остановка и cleanup выполняются при согласованном времени жизни состояния, cleanup — вне callbacks.
*/
void net_emulator_run(net_emulator_t *emulator);
/**
* @brief Clean up emulator resources
* @param emulator Emulator state
* @brief Закрывает созданные endpoint-сокеты и уничтожает собственный ua, сбрасывает running.
* @param emulator состояние после init (в том числе неудачного); NULL и повторный cleanup допустимы
* Перед cleanup завершить отложенные отправки: уничтожение таймеров uasync само не освобождает их packet-аргументы.
*/
void net_emulator_cleanup(net_emulator_t *emulator);
@@ -87,4 +95,4 @@ void net_emulator_cleanup(net_emulator_t *emulator);
}
#endif
#endif /* NET_EMULATOR_H */
#endif /* NET_EMULATOR_H */