Browse Source

fix reconnect

nodeinfo-routing-update
jeka 3 weeks ago
parent
commit
59162bd29a
  1. 125
      src/etcp_connections.c
  2. 1
      src/etcp_connections.h
  3. 26
      src/etcp_send_test.txt
  4. 1
      src/utun.c
  5. 1
      src/utun_instance.c

125
src/etcp_connections.c

@ -34,12 +34,12 @@ static void keepalive_timer_cb(void* arg);
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);
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "link=%p, is_server=%d, reset=%d", link, link ? link->is_server : -1, reset);
if (!link || !link->etcp || !link->etcp->instance) return;
struct ETCP_DGRAM* dgram = u_malloc(sizeof(struct ETCP_DGRAM) + 100);
if (!dgram) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "etcp_link_send_init: malloc failed");
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "malloc failed");
return;
}
@ -96,29 +96,55 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset) {
u_free(dgram);
link->init_retry_count++;
if (!link->init_timer && link->is_server == 0) {
link->init_timeout = INIT_TIMEOUT_INITIAL;
link->init_timer = uasync_set_timeout(link->etcp->instance->ua, link->init_timeout, link, etcp_link_init_timer_cbk);
} else if (link->init_timer) {
if ((link->init_retry_count % 10) == 0 && link->init_timeout < INIT_TIMEOUT_MAX) {
link->init_timeout *= 2;
if (link->init_timeout > INIT_TIMEOUT_MAX) link->init_timeout = INIT_TIMEOUT_MAX;
}
uasync_cancel_timeout(link->etcp->instance->ua, link->init_timer);
link->init_timer = uasync_set_timeout(link->etcp->instance->ua, link->init_timeout, link, etcp_link_init_timer_cbk);
}
}
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;
if (!link) return;
link->init_timer = NULL;
etcp_link_send_init(link,1);
if ((link->init_retry_count % 10) == 0 && link->init_timeout < INIT_TIMEOUT_MAX) {
link->init_timeout += link->init_timeout/4 +1;
if (link->init_timeout > INIT_TIMEOUT_MAX) link->init_timeout = INIT_TIMEOUT_MAX;
}
link->init_timer = uasync_set_timeout(link->etcp->instance->ua, link->init_timeout, link, etcp_link_init_timer_cbk);
if (link->link_state == 1) etcp_link_send_init(link,1);// init (with etcp reset)
else etcp_link_send_init(link,0);// no etcp reset (reinit)
}
void etcp_link_restart_init_timer(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (link->init_timer) uasync_cancel_timeout(link->etcp->instance->ua, link->init_timer);
link->init_timeout = INIT_TIMEOUT_INITIAL;
link->init_timer = uasync_set_timeout(link->etcp->instance->ua, link->init_timeout, link, etcp_link_init_timer_cbk);
}
void etcp_link_enter_init(struct ETCP_LINK* link) {//
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!link) return;
link->link_state = 1; // handshake
if (link->is_server != 0) return;
etcp_link_send_init(link,1);// init with reset
etcp_link_restart_init_timer(link);
}
void etcp_link_enter_reinit(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
if (!link) return;
link->link_state = 2; // reconnect
if (link->is_server != 0) return;
etcp_link_send_init(link,0);// init without reset
if (link->keepalive_timer) {// keepalive заменяяется reinit запросами
uasync_cancel_timeout(link->etcp->instance->ua, link->keepalive_timer);
link->keepalive_timer = NULL;
}
etcp_link_restart_init_timer(link);
}
// Send empty keepalive packet (only timestamp, no sections)
static void etcp_link_send_keepalive(struct ETCP_LINK* link) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
@ -159,22 +185,6 @@ static int etcp_all_links_down(struct ETCP_CONN* etcp) {
return 1; // All links are down
}
// Start link recovery process - send CHANNEL_INIT (0x04) on all links
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", link->etcp->log_name ? link->etcp->log_name : "????→????");
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
static void etcp_cancel_all_init_timers(struct ETCP_CONN* etcp) {
if (!etcp) return;
@ -195,16 +205,17 @@ static void etcp_cancel_all_init_timers(struct ETCP_CONN* etcp) {
static void keepalive_timer_cb(void* arg) {
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
struct ETCP_LINK* link = (struct ETCP_LINK*)arg;
if (!link || !link->etcp || !link->etcp->instance) return;
if (!link || !link->etcp || !link->etcp->instance) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "KEEPALIVE NULL !!!!!!!!");
return;
}
link->keepalive_timer = NULL;
// 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);
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);
etcp_link_enter_reinit(link);// keepalive timr после reinit не нужен
return;
}
@ -238,14 +249,7 @@ static void keepalive_timer_cb(void* arg) {
}
// Send keepalive only if no packets were sent since last tick
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);
link->recovery_interval=0;
}
// Reset flag for next interval
if (!link->pkt_sent_since_keepalive) etcp_link_send_keepalive(link);
link->pkt_sent_since_keepalive = 0;
restart_timer:
@ -598,7 +602,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,1);
etcp_link_enter_init(link);
}
return link;
@ -1078,10 +1082,23 @@ process_decrypted:
link->etcp->peer_node_id = server_node_id; // If not set
etcp_update_log_name(link->etcp); // Update log_name with peer_node_id
// Cancel init timer if exists
if (link->init_timer) {
uasync_cancel_timeout(link->etcp->instance->ua, link->init_timer);
link->init_timer = NULL;
}
if (link->keepalive_timer) {
uasync_cancel_timeout(link->etcp->instance->ua, link->keepalive_timer);
link->keepalive_timer = NULL;
}
// 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
link->link_state = 3; // connected
if (link->etcp->initialized == 0) {
etcp_conn_ready(link->etcp);
}
@ -1092,24 +1109,16 @@ process_decrypted:
// Start keepalive timer
etcp_link_send_keepalive(link);
if (!link->keepalive_timer && link->keepalive_interval > 0) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Keepalive timer started on link %p (interval=%d ms)",
link->etcp->log_name, link, link->keepalive_interval);
link->keepalive_timer = uasync_set_timeout(link->etcp->instance->ua,
link->keepalive_interval * 10,
link, keepalive_timer_cb);
if (link->keepalive_interval > 0) {
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Keepalive timer started on link %p (interval=%d ms)", link->etcp->log_name, link, link->keepalive_interval);
link->keepalive_timer = uasync_set_timeout(link->etcp->instance->ua, link->keepalive_interval * 10, link, keepalive_timer_cb);
}
loadbalancer_link_ready(link);
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "etcp client: Link initialized successfully! Server node_id=%016llx, mtu=%d, local_link_id=%d, remote_link_id=%d", (unsigned long long)server_node_id, link->mtu, link->local_link_id, link->remote_link_id);
// Cancel init timer if exists
if (link->init_timer) {
uasync_cancel_timeout(link->etcp->instance->ua, link->init_timer);
link->init_timer = NULL;
}
memory_pool_free(e_sock->instance->pkt_pool, pkt);
return; // INIT_RESPONSE is handled, no further processing needed
}

1
src/etcp_connections.h

@ -72,6 +72,7 @@ struct ETCP_LINK {
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)
uint8_t link_state; // 0 - just init, 1 - handshake, 2 - try reconnect, 3 - connected
// Состояние установки соединения (только для клиентов)
void* init_timer; // Таймер для повторов INIT (NULL=не подключается)

26
src/etcp_send_test.txt

@ -5,4 +5,28 @@
2. вписываешь в link_ready_for_send_fn свою функцию
3. в тесте открываешь ответный сокет
4. добавляешь линк к etcp
5.
5.
link initialization:
client:
1. init timer:
- шлём init with reset
Получили response:
- отменяем init, переходим в обычный режим + keepalive
link не отвечает:
- шлём init without reset
server:
- просто ждёт init request.
как получил init, делает линк инициализированным.
общая логика keepalive (client+server):
далее на init линках шлём keepalive со статусом remote keepalive.
если remote keepalive =0 - значит на другой стороне всё плохо и не шлём данные (только keepalive)

1
src/utun.c

@ -385,6 +385,7 @@ int main(int argc, char *argv[]) {
}
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Run mainloop");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Run mainloop");
while (instance && instance->running) {
uasync_poll(ua, 100);

1
src/utun_instance.c

@ -400,6 +400,7 @@ int utun_instance_init(struct UTUN_INSTANCE *instance) {
// Start the main loop
instance->running = 1;
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "Connections initialized successfully");
return 0;
}

Loading…
Cancel
Save