fix reconnect
This commit is contained in:
1 parent
b605219a87
commit
59162bd29a
5 files changed
+95
-59
No files matched your search
+67
-58
@@ -34,12 +34,12 @@ static void keepalive_timer_cb(void* arg);
|
|||||||
|
|
||||||
static void etcp_link_send_init(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_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;
|
if (!link || !link->etcp || !link->etcp->instance) return;
|
||||||
|
|
||||||
struct ETCP_DGRAM* dgram = u_malloc(sizeof(struct ETCP_DGRAM) + 100);
|
struct ETCP_DGRAM* dgram = u_malloc(sizeof(struct ETCP_DGRAM) + 100);
|
||||||
if (!dgram) {
|
if (!dgram) {
|
||||||
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "etcp_link_send_init: malloc failed");
|
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "malloc failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,29 +96,55 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset) {
|
|||||||
u_free(dgram);
|
u_free(dgram);
|
||||||
|
|
||||||
link->init_retry_count++;
|
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) {
|
static void etcp_link_init_timer_cbk(void* arg) {
|
||||||
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
|
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
|
||||||
struct ETCP_LINK* link = (struct ETCP_LINK*)arg;
|
struct ETCP_LINK* link = (struct ETCP_LINK*)arg;
|
||||||
if (!link || link->initialized || link->is_server != 0) return;
|
if (!link) return;
|
||||||
|
|
||||||
link->init_timer = NULL;
|
if ((link->init_retry_count % 10) == 0 && link->init_timeout < INIT_TIMEOUT_MAX) {
|
||||||
etcp_link_send_init(link,1);
|
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)
|
// Send empty keepalive packet (only timestamp, no sections)
|
||||||
static void etcp_link_send_keepalive(struct ETCP_LINK* link) {
|
static void etcp_link_send_keepalive(struct ETCP_LINK* link) {
|
||||||
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
|
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
|
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
|
// Cancel init_timer for all links of an ETCP_CONN
|
||||||
static void etcp_cancel_all_init_timers(struct ETCP_CONN* etcp) {
|
static void etcp_cancel_all_init_timers(struct ETCP_CONN* etcp) {
|
||||||
if (!etcp) return;
|
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) {
|
static void keepalive_timer_cb(void* arg) {
|
||||||
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
|
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "");
|
||||||
struct ETCP_LINK* link = (struct ETCP_LINK*)arg;
|
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;
|
link->keepalive_timer = NULL;
|
||||||
|
|
||||||
// Check if all links are down and start recovery if needed (client only)
|
// Check if all links are down and start recovery if needed (client only)
|
||||||
if (link->is_server == 0 && etcp_all_links_down(link->etcp)) {
|
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);
|
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] All links are down, starting recovery", link->etcp->log_name);
|
||||||
etcp_start_link_recovery(link);
|
etcp_link_enter_reinit(link);// keepalive timr после reinit не нужен
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,14 +249,7 @@ static void keepalive_timer_cb(void* arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send keepalive only if no packets were sent since last tick
|
// Send keepalive only if no packets were sent since last tick
|
||||||
if (!link->pkt_sent_since_keepalive) {
|
if (!link->pkt_sent_since_keepalive) etcp_link_send_keepalive(link);
|
||||||
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
|
|
||||||
link->pkt_sent_since_keepalive = 0;
|
link->pkt_sent_since_keepalive = 0;
|
||||||
|
|
||||||
restart_timer:
|
restart_timer:
|
||||||
@@ -598,7 +602,7 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn
|
|||||||
|
|
||||||
if (is_server == 0) {
|
if (is_server == 0) {
|
||||||
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "etcp_link_new: client link, calling etcp_link_send_init");
|
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;
|
return link;
|
||||||
@@ -1078,10 +1082,23 @@ process_decrypted:
|
|||||||
link->etcp->peer_node_id = server_node_id; // If not set
|
link->etcp->peer_node_id = server_node_id; // If not set
|
||||||
etcp_update_log_name(link->etcp); // Update log_name with peer_node_id
|
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
|
// Mark link as initialized
|
||||||
// DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "Setting link->initialized=1, link=%p, is_server=%d", link, link->is_server);
|
// 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->initialized = 1;// получен init response (client)
|
||||||
// link->link_status = 1; // Link is up after successful initialization
|
// link->link_status = 1; // Link is up after successful initialization
|
||||||
|
link->link_state = 3; // connected
|
||||||
|
|
||||||
if (link->etcp->initialized == 0) {
|
if (link->etcp->initialized == 0) {
|
||||||
etcp_conn_ready(link->etcp);
|
etcp_conn_ready(link->etcp);
|
||||||
}
|
}
|
||||||
@@ -1092,24 +1109,16 @@ process_decrypted:
|
|||||||
|
|
||||||
// Start keepalive timer
|
// Start keepalive timer
|
||||||
etcp_link_send_keepalive(link);
|
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)",
|
if (link->keepalive_interval > 0) {
|
||||||
link->etcp->log_name, link, link->keepalive_interval);
|
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_timer = uasync_set_timeout(link->etcp->instance->ua, link->keepalive_interval * 10, link, keepalive_timer_cb);
|
||||||
link->keepalive_interval * 10,
|
|
||||||
link, keepalive_timer_cb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadbalancer_link_ready(link);
|
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);
|
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);
|
memory_pool_free(e_sock->instance->pkt_pool, pkt);
|
||||||
return; // INIT_RESPONSE is handled, no further processing needed
|
return; // INIT_RESPONSE is handled, no further processing needed
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ struct ETCP_LINK {
|
|||||||
uint8_t recv_keepalive; // 1 - up, 0 - down (принимаются ли пакеты)
|
uint8_t recv_keepalive; // 1 - up, 0 - down (принимаются ли пакеты)
|
||||||
uint8_t remote_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_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=не подключается)
|
void* init_timer; // Таймер для повторов INIT (NULL=не подключается)
|
||||||
|
|||||||
+25
-1
@@ -5,4 +5,28 @@
|
|||||||
2. вписываешь в link_ready_for_send_fn свою функцию
|
2. вписываешь в link_ready_for_send_fn свою функцию
|
||||||
3. в тесте открываешь ответный сокет
|
3. в тесте открываешь ответный сокет
|
||||||
4. добавляешь линк к etcp
|
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)
|
||||||
@@ -385,6 +385,7 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Run mainloop");
|
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Run mainloop");
|
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Run mainloop");
|
||||||
|
|
||||||
while (instance && instance->running) {
|
while (instance && instance->running) {
|
||||||
uasync_poll(ua, 100);
|
uasync_poll(ua, 100);
|
||||||
|
|||||||
@@ -400,6 +400,7 @@ int utun_instance_init(struct UTUN_INSTANCE *instance) {
|
|||||||
// Start the main loop
|
// Start the main loop
|
||||||
instance->running = 1;
|
instance->running = 1;
|
||||||
|
|
||||||
|
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "Connections initialized successfully");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user