|
|
|
@ -402,6 +402,27 @@ struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sock |
|
|
|
return lqe->link; |
|
|
|
return lqe->link; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Перепривязывает UDP-линк на новый remote-адрес (пир сменил NAT-адрес, линк ещё down).
|
|
|
|
|
|
|
|
* Пере-индексирует линк в socket->links_queue под новым ключом. */ |
|
|
|
|
|
|
|
static void etcp_link_update_remote_addr(struct ETCP_LINK* link, struct ETCP_SOCKET* e_sock, |
|
|
|
|
|
|
|
const struct sockaddr_storage* new_addr) { |
|
|
|
|
|
|
|
if (!link || !e_sock || !new_addr) return; |
|
|
|
|
|
|
|
if (link->is_tcp) { |
|
|
|
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] update_remote_addr: TCP link skip", link->etcp->log_name); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (link->conn != e_sock) { |
|
|
|
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] update_remote_addr: link socket [%s] != recv socket [%s], skip", |
|
|
|
|
|
|
|
link->etcp->log_name, link->conn ? link->conn->name : "-", e_sock->name); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
remove_link_from_queue(link); |
|
|
|
|
|
|
|
memcpy(&link->remote_addr, new_addr, sizeof(struct sockaddr_storage)); |
|
|
|
|
|
|
|
if (insert_link_queue(e_sock, link) < 0) |
|
|
|
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "[%s] update_remote_addr: re-index FAILED at %s", |
|
|
|
|
|
|
|
link->etcp->log_name, sockaddr_storage_to_str(new_addr).str); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct ETCP_LINK* etcp_link_find_by_remote_id(struct ETCP_CONN* conn, uint8_t remote_link_id) { |
|
|
|
struct ETCP_LINK* etcp_link_find_by_remote_id(struct ETCP_CONN* conn, uint8_t remote_link_id) { |
|
|
|
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, ""); |
|
|
|
DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, ""); |
|
|
|
if (!conn || remote_link_id == 0) return NULL; |
|
|
|
if (!conn || remote_link_id == 0) return NULL; |
|
|
|
@ -2115,6 +2136,32 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { |
|
|
|
// Check if link already exists (for CHANNEL_INIT recovery)
|
|
|
|
// Check if link already exists (for CHANNEL_INIT recovery)
|
|
|
|
|
|
|
|
|
|
|
|
struct ETCP_LINK* existing_link = etcp_link_find_by_remote_id(conn, req->link_id); |
|
|
|
struct ETCP_LINK* existing_link = etcp_link_find_by_remote_id(conn, req->link_id); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Правила 1+2: найден по id, линк down, адрес сменился */ |
|
|
|
|
|
|
|
if (existing_link && existing_link->link_status == 0 |
|
|
|
|
|
|
|
&& !sockaddr_equal(&existing_link->remote_addr, &addr)) { |
|
|
|
|
|
|
|
struct ETCP_LINK* L_addr = etcp_link_find_by_addr(e_sock, &addr, 0); |
|
|
|
|
|
|
|
if (L_addr && L_addr != existing_link && L_addr->etcp == conn && L_addr->link_status == 0) { |
|
|
|
|
|
|
|
/* Правило 2: своп remote_link_id, дальше работаем с L_addr */ |
|
|
|
|
|
|
|
uint8_t id_old = existing_link->remote_link_id; |
|
|
|
|
|
|
|
uint8_t id_swap = L_addr->remote_link_id; |
|
|
|
|
|
|
|
existing_link->remote_link_id = id_swap; |
|
|
|
|
|
|
|
L_addr->remote_link_id = id_old; |
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] swap remote_link_id: id=%u @ %s <-> id=%u @ %s", |
|
|
|
|
|
|
|
conn->log_name, id_old, sockaddr_storage_to_str(&existing_link->remote_addr).str, |
|
|
|
|
|
|
|
id_swap, sockaddr_storage_to_str(&L_addr->remote_addr).str); |
|
|
|
|
|
|
|
existing_link = L_addr; |
|
|
|
|
|
|
|
} else if (!L_addr) { |
|
|
|
|
|
|
|
/* Правило 1: перепривязать адрес */ |
|
|
|
|
|
|
|
etcp_link_update_remote_addr(existing_link, e_sock, &addr); |
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] remote addr updated: id=%u -> %s", |
|
|
|
|
|
|
|
conn->log_name, existing_link->remote_link_id, sockaddr_storage_to_str(&addr).str); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] addr %s busy (up/foreign) — link id=%u left as-is", |
|
|
|
|
|
|
|
conn->log_name, sockaddr_storage_to_str(&addr).str, existing_link->remote_link_id); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!existing_link) { |
|
|
|
if (!existing_link) { |
|
|
|
existing_link = etcp_link_find_by_addr(e_sock, &addr, 0); |
|
|
|
existing_link = etcp_link_find_by_addr(e_sock, &addr, 0); |
|
|
|
if (existing_link && existing_link->etcp == conn) { |
|
|
|
if (existing_link && existing_link->etcp == conn) { |
|
|
|
|