@ -345,6 +345,16 @@ static void remove_link(struct ETCP_SOCKET* e_sock, uint32_t hash) {
e_sock - > num_channels - - ;
}
static int sockaddr_equal ( const struct sockaddr_storage * a , const struct sockaddr_storage * b ) {
if ( ! a | | ! b | | a - > ss_family ! = b - > ss_family ) return 0 ;
if ( a - > ss_family = = AF_INET ) {
const struct sockaddr_in * sa = ( const struct sockaddr_in * ) a ;
const struct sockaddr_in * sb = ( const struct sockaddr_in * ) b ;
return ( sa - > sin_addr . s_addr = = sb - > sin_addr . s_addr & & sa - > sin_port = = sb - > sin_port ) ;
}
return 0 ; // IPv6 not fully supported yet
}
// надо править, используй sockaddr_hash
struct ETCP_LINK * etcp_link_find_by_addr ( struct ETCP_SOCKET * e_sock , struct sockaddr_storage * addr ) {
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " " ) ;
@ -356,6 +366,17 @@ struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sock
return e_sock - > links [ idx ] ;
}
struct ETCP_LINK * etcp_link_find_by_remote_id ( struct ETCP_CONN * conn , uint8_t remote_link_id ) {
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " " ) ;
if ( ! conn | | remote_link_id = = 0 ) return NULL ;
struct ETCP_LINK * l = conn - > links ;
while ( l ) {
if ( l - > remote_link_id = = remote_link_id ) return l ;
l = l - > next ;
}
return NULL ;
}
int etcp_find_free_local_link_id ( struct ETCP_CONN * etcp ) {
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " " ) ;
if ( ! etcp ) return - 1 ;
@ -931,13 +952,28 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
else { // check keys если существующее подключение
if ( memcmp ( conn - > crypto_ctx . peer_public_key , sc . peer_public_key , SC_PUBKEY_SIZE ) ) { errorcode = 5 ; DEBUG_ERROR ( DEBUG_CATEGORY_CRYPTO , " etcp_connections_read_callback: peer key mismatch for node %016llx " , ( unsigned long long ) peer_id ) ; goto ec_fr ; } // коллизия - peer id совпал а ключи разные.
}
// Check if link already exists (for CHANNEL_INIT recovery)
struct ETCP_LINK * existing_link = etcp_link_find_by_addr ( e_sock , & addr ) ;
struct ETCP_LINK * existing_link = etcp_link_find_by_remote_id ( conn , ack_hdr - > link_id ) ;
uint8_t send_reset = 0 ;
if ( existing_link & & existing_link - > etcp = = conn ) { // существующий линк
// Link exists - reuse it for recovery
link = existing_link ;
if ( ! sockaddr_equal ( & link - > remote_addr , & addr ) ) {
DEBUG_WARN ( DEBUG_CATEGORY_CONNECTION , " [%s] IP:port changed for remote_link_id=%d socket:[%s] " , conn - > log_name , ack_hdr - > link_id , e_sock - > name ) ;
if ( link - > conn ) remove_link ( link - > conn , link - > ip_port_hash ) ; // remove old connection from old socket
link - > conn = e_sock ;
memcpy ( & link - > remote_addr , & addr , sizeof ( addr ) ) ;
link - > ip_port_hash = sockaddr_hash ( & addr ) ;
if ( insert_link ( link - > conn , link ) < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " Failed to reinsert link after addr change " ) ;
goto ec_fr ;
}
}
// Link exists - reuse it for recovery
link - > remote_link_id = ack_hdr - > link_id ;
// For CHANNEL_INIT (0x04): if link already initialized - no reset, otherwise reset