Browse Source

Fix mesh topology: try normal decryption first, then INIT

Reversed the decryption order:
1. If link exists with session_ready, try normal decryption first
2. If normal decryption succeeds, process packet normally (goto process_decrypted)
3. If normal decryption fails OR no link OR no session, try INIT decryption
4. If INIT succeeds, create new server-side connection and link

This is more efficient because:
- Most packets are regular data (use normal decryption)
- INIT packets are rare (only during connection setup)
- Works correctly for both standard client-server and mesh topologies

All 23 tests now pass.
nodeinfo-routing-update
Evgeny 8 months ago
parent
commit
a73e36b559
  1. 62
      src/etcp_connections.c

62
src/etcp_connections.c

@ -572,50 +572,45 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
struct ETCP_LINK* link=etcp_link_find_by_addr(e_sock, &addr); struct ETCP_LINK* link=etcp_link_find_by_addr(e_sock, &addr);
// printf("[ETCP DEBUG] Received packet, link=%p, recv_len=%zd\n", link, recv_len); // printf("[ETCP DEBUG] Received packet, link=%p, recv_len=%zd\n", link, recv_len);
// If no link found OR found link is a client link (not server), treat as potential INIT
// Client links shouldn't receive incoming INIT packets - only server links should // Try normal decryption first if we have an established link with session keys
if (link==NULL || link->is_server==0) {// пробуем расшифровать, возможно это init // This is the common case for data packets and responses
// printf("[ETCP DEBUG] No existing link found, trying to decrypt as INIT packet\n"); if (link!=NULL && link->etcp!=NULL && link->etcp->crypto_ctx.session_ready) {
struct secure_channel sc; DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Decrypt start (normal)");
if (!sc_decrypt(&link->etcp->crypto_ctx, data, recv_len, (uint8_t*)&pkt->timestamp, &pkt_len)) {
// Normal decryption succeeded - process packet normally
goto process_decrypted;
}
// Normal decryption failed - might be INIT packet, fall through to INIT handling
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Normal decryption failed, trying INIT decryption");
}
// Try INIT decryption (for incoming connection requests)
// This handles: no link found, or link without session, or normal decrypt failed
if (recv_len<=SC_PUBKEY_SIZE) { if (recv_len<=SC_PUBKEY_SIZE) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback: packet too small for init, size=%zd", recv_len); DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback: packet too small for init, size=%zd", recv_len);
// If we have an existing link (client link), try normal decryption instead
if (link != NULL) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "INIT packet too small, trying normal decryption with existing link");
goto normal_decrypt;
}
errorcode=1; errorcode=1;
goto ec_fr; goto ec_fr;
} }
struct secure_channel sc;
sc_init_ctx(&sc, &e_sock->instance->my_keys); sc_init_ctx(&sc, &e_sock->instance->my_keys);
// printf("[ETCP DEBUG] Extracting peer public key from position %ld, total packet size=%zd\n", recv_len-SC_PUBKEY_SIZE, recv_len);
// printf("[ETCP DEBUG] Last 64 bytes of packet (PUBKEY): ");
// for (int i=0; i<SC_PUBKEY_SIZE; i++) DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "%02x ", data[recv_len-SC_PUBKEY_SIZE+i]);
// Расшифровываем public_key inplace используя собственный ключ // Расшифровываем public_key inplace используя собственный ключ
sc_sha_transcode(e_sock->instance->my_keys.public_key, SC_PUBKEY_SIZE, data + recv_len - SC_PUBKEY_SIZE, SC_PUBKEY_SIZE); sc_sha_transcode(e_sock->instance->my_keys.public_key, SC_PUBKEY_SIZE, data + recv_len - SC_PUBKEY_SIZE, SC_PUBKEY_SIZE);
if (sc_set_peer_public_key(&sc, &data[recv_len-SC_PUBKEY_SIZE], SC_PEER_PUBKEY_BIN)!=SC_OK) { if (sc_set_peer_public_key(&sc, &data[recv_len-SC_PUBKEY_SIZE], SC_PEER_PUBKEY_BIN)!=SC_OK) {
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_connections_read_callback: failed to set peer public key during init"); DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_connections_read_callback: failed to set peer public key during init");
// If we have an existing link (client link), try normal decryption instead
if (link != NULL) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "INIT peer key setup failed, trying normal decryption with existing link");
goto normal_decrypt;
}
errorcode=2; errorcode=2;
goto ec_fr; goto ec_fr;
} }
if (sc_decrypt(&sc, data, recv_len-SC_PUBKEY_SIZE, (uint8_t*)&pkt->timestamp, &pkt_len)) { if (sc_decrypt(&sc, data, recv_len-SC_PUBKEY_SIZE, (uint8_t*)&pkt->timestamp, &pkt_len)) {
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_connections_read_callback: failed to decrypt init packet"); DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_connections_read_callback: failed to decrypt init packet");
// If we have an existing link (client link), try normal decryption instead
if (link != NULL) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "INIT decryption failed, trying normal decryption with existing link");
goto normal_decrypt;
}
errorcode=3; errorcode=3;
goto ec_fr; goto ec_fr;
} }
// printf("[ETCP DEBUG] Decrypt OK\n");
// INIT decryption succeeded - process as new incoming connection
pkt->data_len=pkt_len-2; pkt->data_len=pkt_len-2;
pkt->noencrypt_len=0; pkt->noencrypt_len=0;
struct { struct {
@ -630,11 +625,6 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
memcpy(&peer_id, &ack_hdr->id[0], 8); memcpy(&peer_id, &ack_hdr->id[0], 8);
if (ack_hdr->code!=ETCP_INIT_REQUEST && ack_hdr->code!=ETCP_CHANNEL_INIT) { if (ack_hdr->code!=ETCP_INIT_REQUEST && ack_hdr->code!=ETCP_CHANNEL_INIT) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback: not an init packet, code=%02x", ack_hdr->code); DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback: not an init packet, code=%02x", ack_hdr->code);
// If we have an existing link (client link), try normal decryption instead
if (link != NULL) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Packet is not INIT (code=%02x), trying normal decryption with existing link", ack_hdr->code);
goto normal_decrypt;
}
errorcode=4; errorcode=4;
goto ec_fr; goto ec_fr;
}// не init }// не init
@ -665,7 +655,7 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
else {// check keys если существующее подключение 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 %llu", (unsigned long long)peer_id); goto ec_fr; }// коллизия - peer id совпал а ключи разные. 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 %llu", (unsigned long long)peer_id); goto ec_fr; }// коллизия - peer id совпал а ключи разные.
} }
struct ETCP_LINK* link = etcp_link_new(conn, e_sock, &addr, 1); link = etcp_link_new(conn, e_sock, &addr, 1);
if (!link) { if (new_conn) etcp_connection_close(conn); errorcode=66; DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "etcp_connections_read_callback: failed to create link for connection"); goto ec_fr; }// облом if (!link) { if (new_conn) etcp_connection_close(conn); errorcode=66; DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "etcp_connections_read_callback: failed to create link for connection"); goto ec_fr; }// облом
link->remote_link_id = ack_hdr->link_id; link->remote_link_id = ack_hdr->link_id;
if (ack_hdr->code==0x02) etcp_conn_reset(conn); if (ack_hdr->code==0x02) etcp_conn_reset(conn);
@ -714,18 +704,8 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
} }
return; return;
}
normal_decrypt: process_decrypted:
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Decrypt start");
if (sc_decrypt(&link->etcp->crypto_ctx, data, recv_len, (uint8_t*)&pkt->timestamp, &pkt_len)) {
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_connections_read_callback: failed to decrypt packet from node %llu len=%d", (unsigned long long)link->etcp->instance->node_id, recv_len);
// log_dump("my_privkey",&link->etcp->crypto_ctx.pk->private_key, SC_PRIVKEY_SIZE);
// log_dump("my_pubkey",&link->etcp->crypto_ctx.pk->public_key, SC_PUBKEY_SIZE);
// log_dump("peer_pubkey",&link->etcp->crypto_ctx.peer_public_key, SC_PUBKEY_SIZE);
errorcode=6;
goto ec_fr;
}
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Decrypt end"); 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; } 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-2;

Loading…
Cancel
Save