From 25ebad9f52efb857f596bedcd839ba51fddf0ac8 Mon Sep 17 00:00:00 2001 From: evgeny Date: Thu, 6 Aug 2026 14:08:20 +0300 Subject: [PATCH] fix: UDP packet size and addr_type classification - etcp_connections.h: add WIRE_OVERHEAD, IP_UDP_OVERHEAD_V4/V6, SC_ENCRYPT_OVERHEAD (properly accounts for v6 IP(40)+UDP(8)+SC(3)+CCM tag(16) = 67 vs old UDP_HDR_SIZE=28) - etcp_connections.c etcp_encrypt_send: use WIRE_OVERHEAD instead of UDP_HDR_SIZE - etcp_connections.c send_init_response: clamp padding to max_data = mtu - WIRE_OVERHEAD - chat_core_priv.h: add addr_type_from_ip() classifier - chat_profile.c, chat_sync.c, member_sync.c: use classified addr_type instead of hardcoded 0 - chat_sync.c: skip zero nat_addr in JOIN, fall back to interface_addr - topo_node_sqlite.c, member_sync.c: remove addr_type=0 filter from SELECT/DELETE - chat_profile.c, member_sync.c: DELETE all addresses (not just addr_type=0) --- src/chat/chat_core_priv.h | 24 ++++++++ src/chat/chat_profile.c | 28 +++++---- src/chat/chat_sync.c | 35 +++++++---- src/chat/member_sync.c | 16 ++--- src/routing_layer/topo_node_sqlite.c | 2 +- src/transport_layer/etcp_connections.c | 13 ++-- src/transport_layer/etcp_connections.h | 4 ++ .../utun/chat/ui/screens/MemberListScreen.kt | 61 +++++++++++++------ 8 files changed, 128 insertions(+), 55 deletions(-) diff --git a/src/chat/chat_core_priv.h b/src/chat/chat_core_priv.h index af6d9f88..a1826df1 100644 --- a/src/chat/chat_core_priv.h +++ b/src/chat/chat_core_priv.h @@ -73,6 +73,30 @@ static inline size_t b64_decode(const char* src, size_t src_len, uint8_t* dst, s return out; } +/* ── addr_type classification ── */ + +#include "../routing_layer/topo_node.h" + +static inline int addr_type_from_ip(int family, const uint8_t* addr) { + if (!addr) return ADDR_TYPE_NETIF; + if (family == 4) { + uint8_t b0 = addr[0], b1 = addr[1]; + if (b0 == 0 || b0 == 10 || b0 == 127) return ADDR_TYPE_NETIF; + if (b0 == 169 && b1 == 254) return ADDR_TYPE_NETIF; + if (b0 >= 224 && b0 <= 239) return ADDR_TYPE_NETIF; + if (b0 == 172 && b1 >= 16 && b1 <= 31) return ADDR_TYPE_NETIF; + if (b0 == 192 && b1 == 168) return ADDR_TYPE_NETIF; + { uint32_t ip; memcpy(&ip, addr, 4); if (ip == 0 || ip == 0xffffffff) return ADDR_TYPE_NETIF; } + return ADDR_TYPE_DIRECT; + } else { + if (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) return ADDR_TYPE_NETIF; + if (addr[0] == 0xfc || addr[0] == 0xfd) return ADDR_TYPE_NETIF; + { static const uint8_t z[16]; if (!memcmp(addr, z, 16)) return ADDR_TYPE_NETIF; } + { static const uint8_t lb[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; if (!memcmp(addr,lb,16)) return ADDR_TYPE_NETIF; } + return ADDR_TYPE_DIRECT; + } +} + /* ── Глобальное состояние (определено в chat_core.c) ── */ struct chat_core_ctx { diff --git a/src/chat/chat_profile.c b/src/chat/chat_profile.c index 70d8a803..6b8e2e8e 100644 --- a/src/chat/chat_profile.c +++ b/src/chat/chat_profile.c @@ -95,19 +95,19 @@ void chat_core_sync_my_addresses(void) { DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] sync_my_addresses START my_node=0x%016llx", CC_ID, (unsigned long long)g_cc.my_node_id); sqlite3_stmt* del = NULL; - sqlite3_prepare_v2(g_cc.db, "DELETE FROM node_addresses WHERE node_id=? AND addr_type=0", -1, &del, NULL); + sqlite3_prepare_v2(g_cc.db, "DELETE FROM node_addresses WHERE node_id=?", -1, &del, NULL); if (del) { sqlite3_bind_int64(del, 1, (sqlite3_int64)g_cc.my_node_id); sqlite3_step(del); int deleted = sqlite3_changes(g_cc.db); - DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] DELETE addr_type=0 for my_node=0x%016llx: %d rows deleted", CC_ID, (unsigned long long)g_cc.my_node_id, deleted); + DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] DELETE for my_node=0x%016llx: %d rows deleted", CC_ID, (unsigned long long)g_cc.my_node_id, deleted); sqlite3_finalize(del); } sqlite3_stmt* ins = NULL; sqlite3_prepare_v2(g_cc.db, "INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)" - " VALUES(?,?,1,?,?,0,?)", -1, &ins, NULL); + " VALUES(?,?,1,?,?,?,?)", -1, &ins, NULL); if (!ins) { DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] FAIL prepare INSERT stmt my_node=0x%016llx", CC_ID, (unsigned long long)g_cc.my_node_id); return; @@ -129,7 +129,8 @@ void chat_core_sync_my_addresses(void) { sqlite3_bind_int(ins, 2, 4); sqlite3_bind_blob(ins, 3, &sin->sin_addr, 4, SQLITE_STATIC); sqlite3_bind_int(ins, 4, (int)ntohs(sin->sin_port)); - sqlite3_bind_int(ins, 5, (int)sock->sock_id); + sqlite3_bind_int(ins, 5, addr_type_from_ip(4, (const uint8_t*)&sin->sin_addr)); + sqlite3_bind_int(ins, 6, (int)sock->sock_id); sqlite3_step(ins); sqlite3_reset(ins); uint8_t* ip = (uint8_t*)&sin->sin_addr; DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] INSERT my_node=0x%016llx sock=%d %d.%d.%d.%d:%d", @@ -141,7 +142,8 @@ void chat_core_sync_my_addresses(void) { sqlite3_bind_int(ins, 2, 6); sqlite3_bind_blob(ins, 3, &sin6->sin6_addr, 16, SQLITE_STATIC); sqlite3_bind_int(ins, 4, (int)ntohs(sin6->sin6_port)); - sqlite3_bind_int(ins, 5, (int)sock->sock_id); + sqlite3_bind_int(ins, 5, addr_type_from_ip(6, sin6->sin6_addr.s6_addr)); + sqlite3_bind_int(ins, 6, (int)sock->sock_id); sqlite3_step(ins); sqlite3_reset(ins); DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] INSERT v6 my_node=0x%016llx sock=%d port=%d", CC_ID, (unsigned long long)g_cc.my_node_id, sock->sock_id, (int)ntohs(sin6->sin6_port)); @@ -154,7 +156,7 @@ void chat_core_sync_my_addresses(void) { { sqlite3_stmt* tcp_ins = NULL; sqlite3_prepare_v2(g_cc.db, "INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)" - " VALUES(?,?,2,?,?,0,?)", -1, &tcp_ins, NULL); + " VALUES(?,?,2,?,?,?,?)", -1, &tcp_ins, NULL); if (tcp_ins) { struct TCP_SOCKET* ts = g_cc.inst->tcp_sockets; int tcp_count = 0; @@ -164,12 +166,13 @@ void chat_core_sync_my_addresses(void) { if (!addr || !addr->ss_family) { ts = ts->next; continue; } if (addr->ss_family == AF_INET) { struct sockaddr_in* sin = (struct sockaddr_in*)addr; - if (sin->sin_addr.s_addr == 0) { ts = ts->next; continue; } // skip 0.0.0.0 + if (sin->sin_addr.s_addr == 0) { ts = ts->next; continue; } sqlite3_bind_int64(tcp_ins, 1, (sqlite3_int64)g_cc.my_node_id); sqlite3_bind_int(tcp_ins, 2, 4); sqlite3_bind_blob(tcp_ins, 3, &sin->sin_addr, 4, SQLITE_STATIC); sqlite3_bind_int(tcp_ins, 4, (int)ntohs(sin->sin_port)); - sqlite3_bind_int(tcp_ins, 5, (int)ts->sock_id); + sqlite3_bind_int(tcp_ins, 5, addr_type_from_ip(4, (const uint8_t*)&sin->sin_addr)); + sqlite3_bind_int(tcp_ins, 6, (int)ts->sock_id); sqlite3_step(tcp_ins); sqlite3_reset(tcp_ins); uint8_t* ip = (uint8_t*)&sin->sin_addr; DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] INSERT TCP my_node=0x%016llx sock=%d %d.%d.%d.%d:%d", @@ -177,12 +180,13 @@ void chat_core_sync_my_addresses(void) { tcp_written++; } else if (addr->ss_family == AF_INET6) { struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr; - if (memcmp(&sin6->sin6_addr, &in6addr_any, 16) == 0) { ts = ts->next; continue; } // skip :: + if (memcmp(&sin6->sin6_addr, &in6addr_any, 16) == 0) { ts = ts->next; continue; } sqlite3_bind_int64(tcp_ins, 1, (sqlite3_int64)g_cc.my_node_id); sqlite3_bind_int(tcp_ins, 2, 6); sqlite3_bind_blob(tcp_ins, 3, &sin6->sin6_addr, 16, SQLITE_STATIC); sqlite3_bind_int(tcp_ins, 4, (int)ntohs(sin6->sin6_port)); - sqlite3_bind_int(tcp_ins, 5, (int)ts->sock_id); + sqlite3_bind_int(tcp_ins, 5, addr_type_from_ip(6, sin6->sin6_addr.s6_addr)); + sqlite3_bind_int(tcp_ins, 6, (int)ts->sock_id); sqlite3_step(tcp_ins); sqlite3_reset(tcp_ins); DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] INSERT TCP v6 my_node=0x%016llx sock=%d port=%d", CC_ID, (unsigned long long)g_cc.my_node_id, ts->sock_id, (int)ntohs(sin6->sin6_port)); @@ -205,11 +209,11 @@ void chat_core_sync_my_addresses(void) { CC_ID, written, tcp_written, written + tcp_written, skipped, (unsigned long long)g_cc.my_node_id); sqlite3_stmt* chk = NULL; - sqlite3_prepare_v2(g_cc.db, "SELECT COUNT(*) FROM node_addresses WHERE node_id=? AND addr_type=0", -1, &chk, NULL); + sqlite3_prepare_v2(g_cc.db, "SELECT COUNT(*) FROM node_addresses WHERE node_id=?", -1, &chk, NULL); if (chk) { sqlite3_bind_int64(chk, 1, (sqlite3_int64)g_cc.my_node_id); int cnt = sqlite3_step(chk) == SQLITE_ROW ? sqlite3_column_int(chk, 0) : -1; - DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] VERIFY: total addr_type=0 rows for my_node=0x%016llx = %d", + DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] VERIFY: total rows for my_node=0x%016llx = %d", CC_ID, (unsigned long long)g_cc.my_node_id, cnt); sqlite3_finalize(chk); } diff --git a/src/chat/chat_sync.c b/src/chat/chat_sync.c index 2cd6d22c..b50c145d 100644 --- a/src/chat/chat_sync.c +++ b/src/chat/chat_sync.c @@ -1,5 +1,6 @@ #include "chat_sync.h" #include "chat_core.h" +#include "chat_core_priv.h" #include "chat_setting.h" #include "chat_event.h" #include "../routing_layer/topo_node_sqlite.h" @@ -1063,13 +1064,14 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer, struct sockaddr_in* sin = (struct sockaddr_in*)&lk->remote_addr; uint8_t ip[4]; memcpy(ip, &sin->sin_addr, 4); uint16_t port = ntohs(sin->sin_port); char sql[256]; snprintf(sql, sizeof(sql), - "INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id) VALUES(?,4,1,?,?,0,?)"); + "INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id) VALUES(?,4,1,?,?,?,?)"); sqlite3_stmt* as = NULL; if (sqlite3_prepare_v2(vdb, sql, -1, &as, NULL) == SQLITE_OK) { sqlite3_bind_int64(as, 1, (sqlite3_int64)peer); sqlite3_bind_blob(as, 2, ip, 4, SQLITE_STATIC); sqlite3_bind_int(as, 3, port); - sqlite3_bind_int(as, 4, (int)lk->conn->sock_id); + sqlite3_bind_int(as, 4, addr_type_from_ip(4, ip)); + sqlite3_bind_int(as, 5, (int)lk->conn->sock_id); sqlite3_step(as); sqlite3_finalize(as); lk_written++; DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] INFO_RESP INSERT peer=%016llx sock=%d %d.%d.%d.%d:%d", @@ -1122,10 +1124,16 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer, jbuf[joff++] = 0; struct ETCP_SOCKET* sock = cs->inst->etcp_sockets; while (sock && addr_cnt < 255) { - struct sockaddr_storage* sa; - if (sock->nat_addr.ss_family) sa = &sock->nat_addr; - else if (sock->interface_addr.ss_family) sa = &sock->interface_addr; - else { sock = sock->next; continue; } + struct sockaddr_storage* sa = NULL; + if (sock->nat_addr.ss_family) { + sa = &sock->nat_addr; + int is_zero = 0; + if (sa->ss_family == AF_INET) { if (((struct sockaddr_in*)sa)->sin_addr.s_addr == 0) is_zero = 1; } + else { static const uint8_t z[16]; if (!memcmp(&((struct sockaddr_in6*)sa)->sin6_addr, z, 16)) is_zero = 1; } + if (is_zero) sa = NULL; + } + if (!sa && sock->interface_addr.ss_family) sa = &sock->interface_addr; + if (!sa) { sock = sock->next; continue; } if (sa->ss_family == AF_INET) { struct sockaddr_in* sin = (struct sockaddr_in*)sa; if (joff + 9 > sizeof(jbuf)) break; @@ -1214,7 +1222,7 @@ static void cs_handle_channel_join(struct chat_sync* cs, uint64_t peer, char sql[256]; snprintf(sql, sizeof(sql), "INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)" - " VALUES(?,?,?,?,?,0,?)"); + " VALUES(?,?,?,?,?,?,?)"); sqlite3_stmt* stmt = NULL; if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) { sqlite3_bind_int64(stmt, 1, (sqlite3_int64)node_id); @@ -1222,7 +1230,8 @@ static void cs_handle_channel_join(struct chat_sync* cs, uint64_t peer, sqlite3_bind_int(stmt, 3, (int)proto); sqlite3_bind_blob(stmt, 4, ip, ip_len, SQLITE_STATIC); sqlite3_bind_int(stmt, 5, (int)port); - sqlite3_bind_int(stmt, 6, (int)sid); + sqlite3_bind_int(stmt, 6, addr_type_from_ip(fm, ip)); + sqlite3_bind_int(stmt, 7, (int)sid); sqlite3_step(stmt); sqlite3_finalize(stmt); } if (fm == 4) @@ -1389,7 +1398,7 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer, char sql[256]; snprintf(sql, sizeof(sql), "INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)" - " VALUES(?,?,?,?,?,0,?)"); + " VALUES(?,?,?,?,?,?,?)"); sqlite3_stmt* stmt2 = NULL; if (sqlite3_prepare_v2(db, sql, -1, &stmt2, NULL) == SQLITE_OK) { sqlite3_bind_int64(stmt2, 1, (sqlite3_int64)node_id); @@ -1397,7 +1406,8 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer, sqlite3_bind_int(stmt2, 3, (int)proto); sqlite3_bind_blob(stmt2, 4, ip, ip_len, SQLITE_STATIC); sqlite3_bind_int(stmt2, 5, (int)port); - sqlite3_bind_int(stmt2, 6, (int)sid); + sqlite3_bind_int(stmt2, 6, addr_type_from_ip(fm, ip)); + sqlite3_bind_int(stmt2, 7, (int)sid); sqlite3_step(stmt2); sqlite3_finalize(stmt2); } if (fm == 4) @@ -1503,7 +1513,7 @@ static void cs_handle_peer_upsert(struct chat_sync* cs, uint64_t peer, char sql[256]; snprintf(sql, sizeof(sql), "INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)" - " VALUES(?,?,?,?,?,0,?)"); + " VALUES(?,?,?,?,?,?,?)"); sqlite3_stmt* stmt = NULL; if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) { sqlite3_bind_int64(stmt, 1, (sqlite3_int64)node_id); @@ -1511,7 +1521,8 @@ static void cs_handle_peer_upsert(struct chat_sync* cs, uint64_t peer, sqlite3_bind_int(stmt, 3, (int)proto); sqlite3_bind_blob(stmt, 4, ip, ip_len, SQLITE_STATIC); sqlite3_bind_int(stmt, 5, (int)port); - sqlite3_bind_int(stmt, 6, (int)sid); + sqlite3_bind_int(stmt, 6, addr_type_from_ip(fm, ip)); + sqlite3_bind_int(stmt, 7, (int)sid); sqlite3_step(stmt); sqlite3_finalize(stmt); } if (fm == 4) diff --git a/src/chat/member_sync.c b/src/chat/member_sync.c index f018fed1..eadf6f93 100644 --- a/src/chat/member_sync.c +++ b/src/chat/member_sync.c @@ -1,7 +1,8 @@ #include "member_sync.h" + #include "../routing_layer/topo_node_sqlite.h" #include "chat_core.h" - +#include "chat_core_priv.h" #include "../utun_instance.h" #include "../../lib/debug_config.h" #include "../../lib/mem.h" @@ -130,7 +131,7 @@ static int _member_update_bucket_hash(void* ctx, const char* ns, uint8_t level, uint8_t addrs[2048]; int addr_off = 0; int addr_count = 0; sqlite3_stmt* as = NULL; sqlite3_prepare_v2(db, - "SELECT family, socket_id, protocol, address, port FROM node_addresses WHERE node_id=? AND addr_type=0" + "SELECT family, socket_id, protocol, address, port FROM node_addresses WHERE node_id=?" " ORDER BY family, address, port", -1, &as, NULL); if (as) { sqlite3_bind_int64(as, 1, (sqlite3_int64)nid); @@ -205,7 +206,7 @@ static int _member_get_items(void* ctx, const char* ns, uint8_t level, sqlite3_stmt* as = NULL; sqlite3_prepare_v2(db, - "SELECT family, socket_id, protocol, address, port FROM node_addresses WHERE node_id=? AND addr_type=0" + "SELECT family, socket_id, protocol, address, port FROM node_addresses WHERE node_id=?" " ORDER BY family, address, port", -1, &as, NULL); uint8_t addrs[2048]; int addr_off = 0; int addr_count = 0; if (as) { @@ -528,17 +529,17 @@ int member_sync_put(struct UTUN_INSTANCE* inst, const char* ch_id, MS_ID, (unsigned long long)member_id, ch_id, addr_count); sqlite3_exec(db, "BEGIN", NULL, NULL, NULL); sqlite3_stmt* ds = NULL; - sqlite3_prepare_v2(db, "DELETE FROM node_addresses WHERE node_id=? AND addr_type=0", -1, &ds, NULL); + sqlite3_prepare_v2(db, "DELETE FROM node_addresses WHERE node_id=?", -1, &ds, NULL); if (ds) { sqlite3_bind_int64(ds, 1, (sqlite3_int64)member_id); sqlite3_step(ds); int deleted = sqlite3_changes(db); - DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] member_sync_put DELETE addr_type=0 node=0x%016llx: %d rows deleted", + DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: [ADDR_SYNC] member_sync_put DELETE node=0x%016llx: %d rows deleted", MS_ID, (unsigned long long)member_id, deleted); sqlite3_finalize(ds); } sqlite3_stmt* as = NULL; sqlite3_prepare_v2(db, "INSERT INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)" - " VALUES(?,?,?,?,?,0,?)", -1, &as, NULL); + " VALUES(?,?,?,?,?,?,?)", -1, &as, NULL); if (as) { const uint8_t* p = addrs_data; int written = 0; @@ -554,7 +555,8 @@ int member_sync_put(struct UTUN_INSTANCE* inst, const char* ch_id, p += ip_sz; uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2; sqlite3_bind_int(as, 5, port); - sqlite3_bind_int(as, 6, (int)sid); + sqlite3_bind_int(as, 6, addr_type_from_ip(fam, p - ip_sz - 2)); + sqlite3_bind_int(as, 7, (int)sid); sqlite3_step(as); sqlite3_reset(as); if (fam == 4) { const uint8_t* ip = p - 6; /* p advanced by ip_sz(4) + port(2) - back to start of ip */ diff --git a/src/routing_layer/topo_node_sqlite.c b/src/routing_layer/topo_node_sqlite.c index 3464ddda..388b5fd1 100644 --- a/src/routing_layer/topo_node_sqlite.c +++ b/src/routing_layer/topo_node_sqlite.c @@ -383,7 +383,7 @@ int topo_node_sqlite_channel_peers_all(sqlite3* db, const char* channel_id, sqlite3_stmt* ast = NULL; snprintf(sql, sizeof(sql), "SELECT family, socket_id, protocol, address, port FROM node_addresses" - " WHERE node_id=? AND addr_type=0 LIMIT 16"); + " WHERE node_id=? LIMIT 16"); if (sqlite3_prepare_v2(db, sql, -1, &ast, NULL) != SQLITE_OK) continue; sqlite3_bind_int64(ast, 1, (sqlite3_int64)node_id); diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index 146410fa..c6fa95e2 100644 --- a/src/transport_layer/etcp_connections.c +++ b/src/transport_layer/etcp_connections.c @@ -1045,7 +1045,8 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) { int errcode=0; sc_context_t* sc = &dgram->link->etcp->crypto_ctx; int len=dgram->data_len-dgram->noencrypt_len;// не забываем добавить timestamp (2 bytes) - if (len<0 || len>dgram->link->mtu - UDP_HDR_SIZE) { dgram->link->send_errors++; errcode=1; goto es_err; } + int wire_ov = WIRE_OVERHEAD(dgram->link->remote_addr.ss_family); + if (len<0 || len>dgram->link->mtu - wire_ov) { dgram->link->send_errors++; errcode=1; goto es_err; } uint8_t enc_buf[1600]; size_t enc_buf_len=0; dgram->timestamp=get_current_timestamp(); @@ -1480,13 +1481,17 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk int xoffset=sizeof(struct ETCP_INIT_RESPONSE_PKT); // padding + int wire_ov = WIRE_OVERHEAD(link->remote_addr.ss_family); + int max_data = link->mtu - wire_ov; int s = rand() % (link->handshake_maxsize - link->handshake_minsize) + link->handshake_minsize; if (s > (int)(link->mtu)) s = (int)(link->mtu); if (s < 0) s = 0; - int to_add=s - xoffset - UDP_HDR_SIZE - UDP_SC_HDR_SIZE; - if (to_add<0) to_add=0; - if (xoffset + to_add > PACKET_DATA_SIZE) { to_add = PACKET_DATA_SIZE - xoffset; if (to_add<0) to_add=0; } + int to_add = s - xoffset - wire_ov; + if (to_add < 0) to_add = 0; + if (xoffset + to_add > PACKET_DATA_SIZE) { to_add = PACKET_DATA_SIZE - xoffset; if (to_add < 0) to_add = 0; } + if (xoffset + to_add > max_data) to_add = max_data - xoffset; + if (to_add < 0) to_add = 0; for (int i=0; idata[xoffset++]=rand();// fill pad // padding end diff --git a/src/transport_layer/etcp_connections.h b/src/transport_layer/etcp_connections.h index a525af07..676ee78d 100644 --- a/src/transport_layer/etcp_connections.h +++ b/src/transport_layer/etcp_connections.h @@ -19,6 +19,10 @@ extern "C" { #define UDP_HDR_SIZE 28// размер udp header + ethernet заголовков (ipv4) [для ipv6 = 48 байт] #define UDP_SC_HDR_SIZE (13+8+4 + 5)// 13+8+4 - sc_nonce+tag size+crc, 5 - payload hdr #define ACK_REZERV 100// сколько байт резервировать под ack и прочие заголовки +#define SC_ENCRYPT_OVERHEAD (3 + SC_TAG_SIZE) // timestamp(2)+flag_up(1)+AES-CCM tag(16) — поверх plaintext +#define IP_UDP_OVERHEAD_V4 (20 + 8) // IP(20)+UDP(8) +#define IP_UDP_OVERHEAD_V6 (40 + 8) // IP(40)+UDP(8) +#define WIRE_OVERHEAD(fam) ((fam) == AF_INET6 ? IP_UDP_OVERHEAD_V6 + SC_ENCRYPT_OVERHEAD : IP_UDP_OVERHEAD_V4 + SC_ENCRYPT_OVERHEAD) #define INFLIGHT_LIM_MIN 8192 // 8K #define INFLIGHT_LIM_MAX 1048576 // 1M diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/MemberListScreen.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/MemberListScreen.kt index c401377a..f7825b4a 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/MemberListScreen.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/MemberListScreen.kt @@ -89,6 +89,7 @@ fun MemberListScreen( MemberDetailCard( detail = detail, memberLinks = memberLinks, + isSelf = members.any { it.nodeId == detail.nodeId && it.isSelf }, onDismiss = { } ) } @@ -140,12 +141,16 @@ private fun MemberListItem( modifier = Modifier.padding(horizontal = 16.dp, vertical = 10.dp), verticalAlignment = Alignment.CenterVertically ) { - Box( - modifier = Modifier - .size(10.dp) - .clip(CircleShape) - .background(onlineColor) - ) + if (member.isSelf) { + Text("✓", fontSize = 12.sp, color = Color(0xFF4CAF50)) + } else { + Box( + modifier = Modifier + .size(10.dp) + .clip(CircleShape) + .background(onlineColor) + ) + } Spacer(Modifier.width(10.dp)) Column(modifier = Modifier.weight(1f)) { @@ -161,7 +166,8 @@ private fun MemberListItem( if (member.isAdmin) parts.add("Admin") if (member.isSuper) parts.add("Super") if (member.isStorage) parts.add("Storage") - if (member.directUp) parts.add("direct↑") + if (member.isSelf) parts.add("self") + else if (member.directUp) parts.add("direct↑") else if (member.indirectUp) parts.add("indirect↑") else if (member.directPresence || member.indirectPresence || member.bgpPresence) parts.add("down") if (member.rtt > 0) parts.add("${member.rtt}ms") @@ -170,7 +176,7 @@ private fun MemberListItem( Text( text = parts.joinToString(" "), fontSize = 11.sp, - color = if (member.directUp || member.indirectUp) + color = if (member.isSelf || member.directUp || member.indirectUp) Color(0xFF4CAF50) else Color.Gray ) } @@ -186,6 +192,7 @@ private fun MemberListItem( private fun MemberDetailCard( detail: MemberDetail, memberLinks: MemberLinks, + isSelf: Boolean = false, onDismiss: () -> Unit ) { fun linkDotColor(addr: MemberAddr): Color { @@ -247,15 +254,7 @@ private fun MemberDetailCard( Spacer(Modifier.height(6.dp)) Text("Addresses:", fontSize = 13.sp, fontWeight = FontWeight.Medium) detail.addresses.forEach { a -> - val dcol = linkDotColor(a) - Row(verticalAlignment = Alignment.CenterVertically) { - Box( - modifier = Modifier - .size(8.dp) - .clip(CircleShape) - .background(dcol) - ) - Spacer(Modifier.width(6.dp)) + if (isSelf) { Text( text = "${a.protocol} ${a.address}:${a.port}" + (if (a.rtt > 0) " (${a.rtt / 10}ms)" else ""), @@ -263,13 +262,37 @@ private fun MemberDetailCard( fontSize = 11.sp, color = Color.DarkGray ) + } else { + val dcol = linkDotColor(a) + Row(verticalAlignment = Alignment.CenterVertically) { + Box( + modifier = Modifier + .size(8.dp) + .clip(CircleShape) + .background(dcol) + ) + Spacer(Modifier.width(6.dp)) + Text( + text = "${a.protocol} ${a.address}:${a.port}" + + (if (a.rtt > 0) " (${a.rtt / 10}ms)" else ""), + fontFamily = FontFamily.Monospace, + fontSize = 11.sp, + color = Color.DarkGray + ) + } } } } val rttTypeName = when (detail.rttType) { 0 -> "interface" 1 -> "nat" 2 -> "real" else -> "?" } Spacer(Modifier.height(6.dp)) Text("Connection:", fontSize = 13.sp, fontWeight = FontWeight.Medium) - if (detail.directPresence) { + if (isSelf) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text("✓", fontSize = 12.sp, color = Color(0xFF4CAF50)) + Spacer(Modifier.width(4.dp)) + Text("self (local)", fontSize = 12.sp, color = Color(0xFF4CAF50)) + } + } else if (detail.directPresence) { Row(verticalAlignment = Alignment.CenterVertically) { Box(Modifier.size(8.dp).clip(CircleShape) .background(if (detail.directUp) Color(0xFF4CAF50) else Color(0xFFE53935))) @@ -295,7 +318,7 @@ private fun MemberDetailCard( Text("BGP: visible", fontSize = 12.sp, color = Color.DarkGray) } } - if (!detail.directPresence && !detail.indirectPresence && !detail.bgpPresence) { + if (!isSelf && !detail.directPresence && !detail.indirectPresence && !detail.bgpPresence) { Text("offline", fontSize = 12.sp, color = Color.Gray) } }