Backup before fixing test_routing_mesh segfault
This commit is contained in:
1 parent
42cd803432
commit
a36cf652ff
11 files changed
+62
-1130
No files matched your search
@@ -255,6 +255,7 @@ Crypto: Fixed CCM nonce size to 13 bytes, all crypto tests passing
|
||||
- прежде чем вносить правки хорошо разберись как должно работать, просмотри все нужные функции полностью, нужно целостное понимание.
|
||||
- при написании кода мысленно анализируй логику работы, думай как сделать проще и удобнее. Проверяй дубликаты и что уже есть, продумай логику до тех пор пока не будет полного понимания
|
||||
- во всех блоках обработки ошибок/нештатных ситуаций должны быть сообщения DEBUG_ERROR/DEBUG_WARN
|
||||
- тесты: запускаё все сразу (make check) - ошибок быть не должно. если что не такт смотри логи - каждый тест пишет лог.
|
||||
|
||||
Действия при поиске бага:
|
||||
1. создать комит или бэкап всего что меняешь
|
||||
@@ -290,30 +291,8 @@ Crypto: Fixed CCM nonce size to 13 bytes, all crypto tests passing
|
||||
/doc/etcp_protocol.txt - основной протокол (похож на TCP+QUIC, поддеиживает шифрования, load balancing multi-link, работу а неустойчивых каналах, утилизацию полосы и недопущение перегрузки каналов связи)
|
||||
- реализация в /src/etcp*.c/h
|
||||
|
||||
## Навигация по коду: c_util
|
||||
|
||||
Скрипт для навигации по C-коду проекта.
|
||||
|
||||
**Команды:**
|
||||
|
||||
```bash
|
||||
# Оглавление проекта - все функции/структуры/enum с номерами строк
|
||||
./c_util toc
|
||||
|
||||
# Показать сигнатуры с комментариями (по именам)
|
||||
./c_util description <name1> [name2 ...]
|
||||
|
||||
# Показать полный код с номерами строк и checksum
|
||||
./c_util show <name1> [name2 ...]
|
||||
|
||||
# Редактировать код с проверкой checksum
|
||||
./c_util edit <file> <start_line> <checksum1> [checksum2 ...] <<'EOF'
|
||||
<новый код>
|
||||
EOF
|
||||
```
|
||||
|
||||
**edit:** заменяет блок строк начиная с `start_line`. Проверяет контрольные суммы всех заменяемых строк (hex, 2 символа). При несовпадении - ошибка без изменений. Новый код автоматически форматируется с правильными отступами (табы/пробелы определяются из файла).
|
||||
|
||||
|
||||
запуск utun от root (для tun) - /home/vnc1/proj/utun3/utun_start.sh
|
||||
стоп utun: sudo /home/vnc1/proj/utun3/utun_stop1.sh
|
||||
логи - utun.log
|
||||
|
||||
*Last updated: 2026-02-13 - c_util fully functional with toc/description/show/edit commands*
|
||||
@@ -10,15 +10,14 @@
|
||||
1. берем пакет из списка неподтвержденных пакетов ожидающих отправку
|
||||
2. если есть место в rwin (объём inflight данных) то берем очередной пакет из ETCP input_queue и его отправляем
|
||||
если пакет найден:
|
||||
1. вызываем функцию формирования опциональных секций (ACK, RETRANS, channel timestamp) - они записываются в начало
|
||||
1. вызываем функцию формирования опциональных секций (ACK, channel timestamp) - они записываются в начало
|
||||
2. в конец добавляем секцию 0x00 с данными пакета
|
||||
при отправке пакета помечаем в inflight списке с какого интерфейса он отправлен
|
||||
Функция прикрепления опциональных секций:
|
||||
- запрашивает выбор канала передачи.
|
||||
- добавляет накопившиеся ACK и RETRANS
|
||||
- добавляет накопившиеся ACK
|
||||
При приёме пакета (от etcp_connections):
|
||||
- последовательно сканируем секции и отдаём их на обработку нужным обработчикам:
|
||||
- retrans: помечаем секции как нужна ретрансмиссия. также ставим флаг в конце запустить etcp если он в wait timeout, т.е. wait_timeout!=NULL
|
||||
- ack: помечаем в inflight пакеты как подтверждённые и проставляем время подтверждения. также и ставим флаг в конце запустить etcp если он в wait timeout, т.е. wait_timeout!=NULL
|
||||
- timestamp: обновляем last RTT, пересчитываем RTT10,RTT100 (плавающим окном за последние 10/100 пакетов), и jitter=max(last 10)-min(last 10 packets)
|
||||
- [0x00] payload: добавляем пакет в нужное место сборочного linked-list (сверяем по ID если дубликат - игнорируем).
|
||||
@@ -55,8 +54,10 @@ bandwidth по каждому линку адаптивно подстраива
|
||||
**** Формат кодограмм для etcp.c/h ****
|
||||
Каждая кодограмма состоит из обязательного заголовка и опциональных секций:
|
||||
1. Обязательный заголовок всего пакета (2 байта) добавляется при передаче, есть во всех пакетах:
|
||||
[Timestamp high][Timestamp low]
|
||||
[Timestamp high][Timestamp low][flags]
|
||||
- Timestamp: время отправки в единицах 0.1 мс (циклическое). при переповторах время обновляется
|
||||
- flags: bit0 = up/down (recv_keepalive)
|
||||
|
||||
шифруется строго ВСЁ включая ВСЕ заголовки (кроме INIT+publickey). timestamp вставляется ВСЕГДА ВО ВСЕ КОДОГРАММЫ
|
||||
2. Опциональные секции (одна или несколько) добавляются в etcp.c:
|
||||
а) Подтверждения (ACK) - заголовок 0x01:
|
||||
@@ -64,10 +65,6 @@ bandwidth по каждому линку адаптивно подстраива
|
||||
- count: количество пар ID+timestamp (1-32)
|
||||
- last_delivered_id: последний ID, доставленный получателю
|
||||
- last_rx_id: последний полученный ID (для синхронизации прогресса)
|
||||
б) Запросы ретрансмиссии (RETRANS) - заголовок 0x10-0x2F:
|
||||
[0x10+(count-1)][(id_hi,id_lo)×count][last_delivered_hi,lo][last_rx_hi,lo]
|
||||
- count: (заголовок & 0x0F) + 1 (1-32)
|
||||
- last_delivered_id, last_rx_id: для синхронизации состояния
|
||||
в) channel timestamp (добавляется после выбора канала передачи):
|
||||
[0x0F] [RET_Timestamp high][RET_Timestamp low] [RECV_Timestamp high][RECV_Timestamp low]
|
||||
- RET_Timestamp: это timestamp последнего принятого пакета по этому каналу ETCP_LINK плюс разница времени между принятием этого пакета и текущим временем. т.е. приёмная сторона по этому timestamp (и зная своё время) может просчитать время в пути туда + обратно
|
||||
|
||||
+40
-15
@@ -163,17 +163,19 @@ static void keepalive_timer_cb(void* arg) {
|
||||
uint64_t elapsed = now - link->last_recv_local_time;
|
||||
|
||||
if (elapsed > timeout_units) {
|
||||
if (link->link_status != 0) {
|
||||
link->link_status = 0; // down
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] Link %p (local_id=%d) status changed to DOWN - "
|
||||
if (link->recv_keepalive != 0) {
|
||||
link->recv_keepalive = 0; // down
|
||||
link->link_status = 0;
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] Link %p (local_id=%d) recv status changed to DOWN - "
|
||||
"no packets received for %llu ms (timeout=%u ms)",
|
||||
link->etcp->log_name, link, link->local_link_id,
|
||||
(unsigned long long)(elapsed / 10), link->keepalive_timeout);
|
||||
}
|
||||
} else {
|
||||
if (link->link_status != 1) {
|
||||
link->link_status = 1; // up
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Link %p (local_id=%d) status changed to UP",
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -580,8 +582,12 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
|
||||
|
||||
if (!dgram || !dgram->link) return -1;
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Send rk=%d lk=%d up=%d",
|
||||
dgram->link->etcp->log_name, dgram->link->recv_keepalive, dgram->link->remote_keepalive, dgram->link->link_status);
|
||||
|
||||
// Mark that packet was sent (for keepalive logic)
|
||||
dgram->link->pkt_sent_since_keepalive = 1;
|
||||
dgram->flag_up=dgram->link->recv_keepalive;
|
||||
|
||||
int errcode=0;
|
||||
sc_context_t* sc = &dgram->link->etcp->crypto_ctx;
|
||||
@@ -594,7 +600,7 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
|
||||
// DUMP: Show packet before encryption
|
||||
if (debug_should_output(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_CRYPTO)) log_dump("ECTP_ENCRYPT_SEND", dgram->data, dgram->data_len);
|
||||
// DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Encrypt start");
|
||||
sc_encrypt(sc, (uint8_t*)&dgram->timestamp/*не править это, тут верно!*/, sizeof(uint16_t) + len, enc_buf, &enc_buf_len);
|
||||
sc_encrypt(sc, (uint8_t*)&dgram->timestamp/*не править это, тут верно!*/, 3 + len, enc_buf, &enc_buf_len);
|
||||
// DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Encrypt end");
|
||||
if (enc_buf_len == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_encrypt_send: encryption failed for node %llu", (unsigned long long)dgram->link->etcp->instance->node_id);
|
||||
@@ -647,6 +653,7 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
|
||||
// 4 - не init пакет (неверный код)
|
||||
// 5 - коллизия peer ID и ключей
|
||||
// 6 - не удалось расшифровать обычный пакет
|
||||
// 7 - слишком короткий пакет
|
||||
// 13 - переполнение при парсинге пакета
|
||||
// 46 - расшифрованный пакет слишком маленький (< 3 байта)
|
||||
// 55 - не удалось создать подключение
|
||||
@@ -682,6 +689,10 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
|
||||
|
||||
// Try normal decryption first if we have an established link with session keys
|
||||
// This is the common case for data packets and responses
|
||||
if (link) {
|
||||
link->recv_keepalive = 1; // Link is up after successful initialization
|
||||
}
|
||||
|
||||
if (link!=NULL && link->etcp!=NULL && link->etcp->crypto_ctx.session_ready) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Decrypt start (normal)");
|
||||
if (!sc_decrypt(&link->etcp->crypto_ctx, data, recv_len, (uint8_t*)&pkt->timestamp, &pkt_len)) {
|
||||
@@ -718,7 +729,13 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
|
||||
}
|
||||
|
||||
// INIT decryption succeeded - process as new incoming connection
|
||||
pkt->data_len=pkt_len-2;
|
||||
if (pkt_len<3) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_connections_read_callback: too short packet");
|
||||
errorcode=7;
|
||||
goto ec_fr;
|
||||
}
|
||||
|
||||
pkt->data_len=pkt_len-3;
|
||||
pkt->noencrypt_len=0;
|
||||
struct {
|
||||
uint8_t code;
|
||||
@@ -796,6 +813,8 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
|
||||
pkt->data_len=sizeof(*ack_repl_hdr);
|
||||
pkt->noencrypt_len=0;
|
||||
pkt->link=link;
|
||||
link->recv_keepalive = 1;
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "Sending INIT RESPONSE, link=%p, local_link_id=%d, remote_link_id=%d", link, link->local_link_id, link->remote_link_id);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP DEBUG] Send INIT RESPONSE");
|
||||
etcp_encrypt_send(pkt);
|
||||
@@ -803,7 +822,6 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
|
||||
|
||||
memory_pool_free(e_sock->instance->pkt_pool, pkt);
|
||||
link->initialized = 1;// получен init request (server), считаем линк уже готовым к работе
|
||||
link->link_status = 1; // Link is up after successful initialization
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Link %p (local_id=%d) initialized and marked as UP (server)",
|
||||
link->etcp->log_name, link, link->local_link_id);
|
||||
|
||||
@@ -828,17 +846,22 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
|
||||
process_decrypted:
|
||||
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-2;
|
||||
pkt->data_len=pkt_len-3;
|
||||
pkt->noencrypt_len=0;
|
||||
pkt->link=link;
|
||||
|
||||
link->remote_keepalive=pkt->flag_up;
|
||||
if ( link->remote_keepalive && !link->link_status && link->initialized) loadbalancer_link_ready(link);// up выставляем только если и remote=up и local=up
|
||||
link->link_status=link->remote_keepalive;
|
||||
|
||||
link->last_recv_local_time=get_current_time_units();
|
||||
link->last_recv_timestamp=pkt->timestamp;
|
||||
link->last_recv_updated=1;
|
||||
|
||||
// Mark link as up when receiving packets
|
||||
if (link->link_status != 1) {
|
||||
link->link_status = 1;
|
||||
if (link->recv_keepalive != 1) {
|
||||
link->recv_keepalive = 1;
|
||||
// loadbalancer_link_ready(link);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Link %p (local_id=%d) status changed to UP - packet received",
|
||||
link->etcp->log_name, link, link->local_link_id);
|
||||
}
|
||||
@@ -913,11 +936,13 @@ process_decrypted:
|
||||
// Mark link as initialized
|
||||
// DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "Setting link->initialized=1, link=%p, is_server=%d", link, link->is_server);
|
||||
link->initialized = 1;// получен init response (client)
|
||||
link->link_status = 1; // Link is up after successful initialization
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Link %p (local_id=%d) initialized and marked as UP (client)",
|
||||
link->etcp->log_name, link, link->local_link_id);
|
||||
// link->link_status = 1; // Link is up after successful initialization
|
||||
loadbalancer_link_ready(link);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Link %p (local_id=%d) initialized and marked as UP (client): rk=%d lk=%d up=%d",
|
||||
link->etcp->log_name, link, link->local_link_id, link->recv_keepalive, link->remote_keepalive, link->link_status);
|
||||
|
||||
// Start keepalive timer
|
||||
etcp_link_send_keepalive(link);
|
||||
if (!link->keepalive_timer && link->keepalive_interval > 0) {
|
||||
link->keepalive_timer = uasync_set_timeout(link->etcp->instance->ua,
|
||||
link->keepalive_interval * 10,
|
||||
|
||||
@@ -17,13 +17,16 @@
|
||||
#define ETCP_CHANNEL_RESPONSE 0x05
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ETCP_DGRAM {// пакет (незашифрованный)
|
||||
struct ETCP_LINK* link;// откуда получена или куда отправялем
|
||||
uint16_t data_len;// общий размер пакета не включая timestamp
|
||||
uint16_t noencrypt_len;// число байт (с конца) которые не надо шифровать. для передачи pubkey
|
||||
uint16_t timestamp;// timestamp отправляющего узла при отправке пакета
|
||||
uint8_t flag_up:1;// bit0 = up/down (recv_keepalive)
|
||||
uint8_t data[0];// данные пакета (без timestamp)
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
// список активных подключений которые обслуживает сокет. каждый сокет может обслуживать много подключений
|
||||
struct ETCP_SOCKET {
|
||||
@@ -60,7 +63,9 @@ struct ETCP_LINK {
|
||||
uint8_t initialized; // Флаг инициализации (1=подтверждено или получен request)
|
||||
uint8_t local_link_id; // id моего линка
|
||||
uint8_t remote_link_id; // id этого линка на peer (устанавливается в момент initialized)
|
||||
uint8_t link_status; // 1 - up, 0 - down
|
||||
uint8_t recv_keepalive; // 1 - up, 0 - down (принимаются ли пакеты)
|
||||
uint8_t remote_keepalive; // 1 - up, 0 - down (удаленная сторона сообщает - принимаются ли у нее пакеты)
|
||||
uint8_t link_status; // 1 - up, 0 - down (итоговый статус - если есть проблемы на любой стороне - линк down)
|
||||
|
||||
// Состояние установки соединения (только для клиентов)
|
||||
void* init_timer; // Таймер для повторов INIT (NULL=не подключается)
|
||||
|
||||
+1
-1
@@ -264,7 +264,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
debug_config_init();
|
||||
debug_set_level(DEBUG_LEVEL_TRACE);
|
||||
debug_set_categories(DEBUG_CATEGORY_ALL & ~DEBUG_CATEGORY_UASYNC); // Enable all except uasync
|
||||
debug_set_categories(DEBUG_CATEGORY_ALL & ~DEBUG_CATEGORY_UASYNC & ~DEBUG_CATEGORY_TIMERS); // Enable all except uasync
|
||||
debug_enable_function_name(1);
|
||||
|
||||
if (args.debug_config) {
|
||||
|
||||
Binary file not shown.
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
sudo ./utun >utun.log 2>utun_err.log
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
killall -9 utun
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
sudo ./utun_stop.sh
|
||||
BIN
Binary file not shown.
Reference in new issue
Block a user