Browse Source

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)
topo_upd
evgeny 2 months ago
parent
commit
25ebad9f52
  1. 24
      src/chat/chat_core_priv.h
  2. 28
      src/chat/chat_profile.c
  3. 35
      src/chat/chat_sync.c
  4. 16
      src/chat/member_sync.c
  5. 2
      src/routing_layer/topo_node_sqlite.c
  6. 13
      src/transport_layer/etcp_connections.c
  7. 4
      src/transport_layer/etcp_connections.h
  8. 61
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/MemberListScreen.kt

24
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 {

28
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);
}

35
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)

16
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 */

2
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);

13
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; i<to_add; i++) pkt->data[xoffset++]=rand();// fill pad
// padding end

4
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

61
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)
}
}

Loading…
Cancel
Save