Browse Source

add error logging to all silent returns in chat_sync invite/join chain + GUI self-invite check

topo_upd
evgeny 2 months ago
parent
commit
f8d98cab47
  1. 70
      src/chat/chat_sync.c
  2. 33
      tools/chatgui/src/invitedialog.cpp

70
src/chat/chat_sync.c

@ -95,19 +95,19 @@ static struct ETCP_CONN* cs_find_conn_for_node(struct UTUN_INSTANCE* inst, uint6
static int cs_send(struct chat_sync* cs, const char* ch_id, uint64_t dst, static int cs_send(struct chat_sync* cs, const char* ch_id, uint64_t dst,
const uint8_t* payload, size_t len) { const uint8_t* payload, size_t len) {
if (len < 1) return -1; if (len < 1) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: cs_send len<1", CS_ID); return -1; }
uint8_t ch_len = (uint8_t)strlen(ch_id); uint8_t ch_len = (uint8_t)strlen(ch_id);
if (ch_len > 63) return -1; if (ch_len > 63) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: cs_send ch_len=%u > 63", CS_ID, ch_len); return -1; }
size_t total = 1 + 1 + ch_len + len; size_t total = 1 + 1 + ch_len + len;
uint8_t* buf = u_malloc(total); uint8_t* buf = u_malloc(total);
if (!buf) return -1; if (!buf) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: cs_send alloc(%zu) failed", CS_ID, total); return -1; }
uint8_t* p = buf; uint8_t* p = buf;
*p++ = ETCP_RT_ID_CHAT_SYNC; *p++ = ETCP_RT_ID_CHAT_SYNC;
*p++ = ch_len; *p++ = ch_len;
memcpy(p, ch_id, ch_len); p += ch_len; memcpy(p, ch_id, ch_len); p += ch_len;
memcpy(p, payload, len); memcpy(p, payload, len);
struct ll_entry* entry = queue_entry_new(0); struct ll_entry* entry = queue_entry_new(0);
if (!entry) { u_free(buf); return -1; } if (!entry) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: cs_send queue_entry_new failed", CS_ID); u_free(buf); return -1; }
entry->dgram = buf; entry->len = total; entry->dgram = buf; entry->len = total;
DEBUG_INFO(DEBUG_CATEGORY_DB_SYNC, "%s: SEND %s to=%016llx ch=%s len=%zu", DEBUG_INFO(DEBUG_CATEGORY_DB_SYNC, "%s: SEND %s to=%016llx ch=%s len=%zu",
CS_ID, cs_msg_name(payload[0]), (unsigned long long)dst, ch_id, len); CS_ID, cs_msg_name(payload[0]), (unsigned long long)dst, ch_id, len);
@ -150,7 +150,10 @@ static void cs_handle_channel_invite(struct chat_sync* cs, uint64_t peer,
static void chat_sync_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) { static void chat_sync_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
if (!entry || entry->len < 4) { if (!entry || entry->len < 4) {
if (entry) { if (entry->dgram) u_free(entry->dgram); queue_entry_free(entry); } if (entry) {
DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: recv short entry len=%zu conn=%s", CS_ID, entry->len, conn ? conn->log_name : "?");
if (entry->dgram) u_free(entry->dgram); queue_entry_free(entry);
}
return; return;
} }
if (!g_cs || !g_cs->initialized) { u_free(entry->dgram); queue_entry_free(entry); return; } if (!g_cs || !g_cs->initialized) { u_free(entry->dgram); queue_entry_free(entry); return; }
@ -725,7 +728,7 @@ void chat_sync_connect_from_invite(uint64_t channel_id, uint64_t node_id,
} }
struct chat_invite* inv = u_calloc(1, sizeof(struct chat_invite)); struct chat_invite* inv = u_calloc(1, sizeof(struct chat_invite));
if (!inv) return; if (!inv) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: connect_from_invite calloc failed", CS_ID); return; }
inv->channel_id = channel_id; inv->channel_id = channel_id;
inv->node_id = node_id; inv->node_id = node_id;
@ -733,7 +736,7 @@ void chat_sync_connect_from_invite(uint64_t channel_id, uint64_t node_id,
size_t addrs_sz = addrs_data_len > 0 ? (size_t)addrs_data_len : (size_t)addr_count * 9; size_t addrs_sz = addrs_data_len > 0 ? (size_t)addrs_data_len : (size_t)addr_count * 9;
inv->addrs_data = u_malloc(addrs_sz); inv->addrs_data = u_malloc(addrs_sz);
if (!inv->addrs_data) { u_free(inv); return; } if (!inv->addrs_data) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: connect_from_invite malloc(%zu) failed", CS_ID, addrs_sz); u_free(inv); return; }
memcpy(inv->addrs_data, addrs_data, addrs_sz); memcpy(inv->addrs_data, addrs_data, addrs_sz);
inv->addr_count = addr_count; inv->addr_count = addr_count;
@ -765,7 +768,9 @@ void chat_sync_connect_from_invite(uint64_t channel_id, uint64_t node_id,
/* ─── chat_sync_join_channel: join channel via already-connected peer ─── */ /* ─── chat_sync_join_channel: join channel via already-connected peer ─── */
void chat_sync_join_channel(struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t target_node_id) { void chat_sync_join_channel(struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t target_node_id) {
if (!g_cs || !inst || !ch_id || !ch_id[0]) return; if (!g_cs) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: join_channel: g_cs=NULL, chat_sync not initialized", CS_ID); return; }
if (!inst) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: join_channel: inst=NULL", CS_ID); return; }
if (!ch_id || !ch_id[0]) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: join_channel: ch_id NULL/empty", CS_ID); return; }
uint64_t channel_id = strtoull(ch_id, NULL, 10); uint64_t channel_id = strtoull(ch_id, NULL, 10);
if (channel_id == 0) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: join_channel invalid ch_id='%s'", CS_ID, ch_id); return; } if (channel_id == 0) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: join_channel invalid ch_id='%s'", CS_ID, ch_id); return; }
@ -832,7 +837,7 @@ static int _get_node_name(sqlite3* db, uint64_t node_id, char* out, size_t sz) {
if (!db || !out || !sz) return -1; if (!db || !out || !sz) return -1;
sqlite3_stmt* st = NULL; sqlite3_stmt* st = NULL;
sqlite3_prepare_v2(db, "SELECT name FROM nodes WHERE node_id=?", -1, &st, NULL); sqlite3_prepare_v2(db, "SELECT name FROM nodes WHERE node_id=?", -1, &st, NULL);
if (!st) return -1; if (!st) { DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: _get_node_name prepare failed node=0x%016llx", CS_ID, (unsigned long long)node_id); return -1; }
sqlite3_bind_int64(st, 1, (sqlite3_int64)node_id); sqlite3_bind_int64(st, 1, (sqlite3_int64)node_id);
int rc = -1; int rc = -1;
if (sqlite3_step(st) == SQLITE_ROW) { if (sqlite3_step(st) == SQLITE_ROW) {
@ -956,7 +961,9 @@ static void cs_handle_channel_info_resp(struct chat_sync* cs, uint64_t peer,
uint8_t inv_flags = *p++; uint8_t inv_flags = *p++;
const uint8_t* inviter_join_sig = NULL; uint64_t inviter_join_ts = 0; const uint8_t* inviter_join_sig = NULL; uint64_t inviter_join_ts = 0;
if (inv_flags & PEERS_FLAG_HAS_JOIN) { if (inv_flags & PEERS_FLAG_HAS_JOIN) {
if (p + 72 > pl + len) return; inviter_join_sig = p; p += 64; memcpy(&inviter_join_ts, p, 8); p += 8; } if (p + 72 > pl + len) { DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: CHANNEL_INFO_RESP truncated at inviter_join_sig peer=%016llx", CS_ID, (unsigned long long)peer); return; }
inviter_join_sig = p; p += 64; memcpy(&inviter_join_ts, p, 8); p += 8;
}
const uint8_t* inviter_update_sig = p; p += 64; uint64_t inviter_update_ts; const uint8_t* inviter_update_sig = p; p += 64; uint64_t inviter_update_ts;
memcpy(&inviter_update_ts, p, 8); p += 8; memcpy(&inviter_update_ts, p, 8); p += 8;
uint8_t inv_userinfo_len = *p++; uint8_t inv_userinfo_len = *p++;
@ -1157,7 +1164,7 @@ static void cs_handle_channel_join(struct chat_sync* cs, uint64_t peer,
uint8_t sid = *p++; uint8_t sid = *p++;
uint8_t proto = *p++; uint8_t proto = *p++;
int ip_len = (fm == 4) ? 4 : 16; int ip_len = (fm == 4) ? 4 : 16;
if (p + ip_len + 2 > pl + len) break; if (p + ip_len + 2 > pl + len) { DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: JOIN addr truncated node=0x%016llx fm=%u i=%u", CS_ID, (unsigned long long)node_id, fm, i); break; }
const uint8_t* ip = p; p += ip_len; const uint8_t* ip = p; p += ip_len;
uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2; uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2;
@ -1251,14 +1258,14 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer,
uint16_t pc; memcpy(&pc, p, 2); p += 2; uint16_t pc; memcpy(&pc, p, 2); p += 2;
DEBUG_TRACE(DEBUG_CATEGORY_DB_SYNC, "%s: WELCOME ch=%s from=%016llx peers=%u", CS_ID, ch_id, (unsigned long long)peer, pc); DEBUG_TRACE(DEBUG_CATEGORY_DB_SYNC, "%s: WELCOME ch=%s from=%016llx peers=%u", CS_ID, ch_id, (unsigned long long)peer, pc);
for (uint16_t i = 0; i < pc; i++) { for (uint16_t i = 0; i < pc; i++) {
if ((size_t)(p - pl) + 8 + 32 + 32 + 1 + 64 + 8 + 1 > len) break; /* min: id+x25519+ed+flags+update_sig(64+8)+nl+ac */ if ((size_t)(p - pl) + 8 + 32 + 32 + 1 + 64 + 8 + 1 > len) { DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: WELCOME peer[%u] truncated at %td len=%zu", CS_ID, i, p - pl, len); break; } /* min: id+x25519+ed+flags+update_sig(64+8)+nl+ac */
uint64_t node_id; memcpy(&node_id, p, 8); p += 8; uint64_t node_id; memcpy(&node_id, p, 8); p += 8;
const uint8_t* x25519 = p; p += 32; const uint8_t* x25519 = p; p += 32;
const uint8_t* ed_pub = p; p += 32; const uint8_t* ed_pub = p; p += 32;
uint8_t flags = *p++; uint8_t flags = *p++;
const uint8_t* join_sig = NULL; uint64_t join_ts = 0; const uint8_t* join_sig = NULL; uint64_t join_ts = 0;
if (flags & PEERS_FLAG_HAS_JOIN) { if (flags & PEERS_FLAG_HAS_JOIN) {
if (p + 64 + 8 > pl + len) break; if (p + 64 + 8 > pl + len) { DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: WELCOME join_sig truncated node=0x%016llx i=%u", CS_ID, (unsigned long long)node_id, i); break; }
join_sig = p; p += 64; join_sig = p; p += 64;
memcpy(&join_ts, p, 8); p += 8; memcpy(&join_ts, p, 8); p += 8;
} }
@ -1313,28 +1320,27 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer,
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: [ADDR_SYNC] WELCOME save addrs node=0x%016llx ac=%d", CS_ID, (unsigned long long)node_id, ac); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: [ADDR_SYNC] WELCOME save addrs node=0x%016llx ac=%d", CS_ID, (unsigned long long)node_id, ac);
for (uint8_t j = 0; j < ac; j++) { for (uint8_t j = 0; j < ac; j++) {
if (p + 2 > pl + len) break; if (p + 2 > pl + len) { DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: WELCOME addr[%u] header truncated node=0x%016llx", CS_ID, j, (unsigned long long)node_id); break; }
uint8_t fm = *p++; uint8_t fm = *p++;
uint8_t sid = *p++; uint8_t sid = *p++;
uint8_t proto = *p++; uint8_t proto = *p++;
int ip_len = (fm == 4) ? 4 : 16; int ip_len = (fm == 4) ? 4 : 16;
if (p + ip_len + 2 > pl + len) break; if (p + ip_len + 2 > pl + len) { DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: WELCOME addr[%u] ip truncated node=0x%016llx fm=%u", CS_ID, j, (unsigned long long)node_id, fm); break; }
const uint8_t* ip = p; p += ip_len; const uint8_t* ip = p; p += ip_len;
uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2; uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2;
char sql[256]; snprintf(sql, sizeof(sql), char sql[256]; snprintf(sql, sizeof(sql),
"INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)" "INSERT OR REPLACE INTO node_addresses(node_id,family,protocol,address,port,addr_type,socket_id)"
" VALUES(?,?,?,?,?,0,?)"); " VALUES(?,?,?,?,?,0,?)");
sqlite3_stmt* stmt = NULL; sqlite3_stmt* stmt2 = NULL;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) { if (sqlite3_prepare_v2(db, sql, -1, &stmt2, NULL) == SQLITE_OK) {
sqlite3_bind_int64(stmt, 1, (sqlite3_int64)node_id); sqlite3_bind_int64(stmt2, 1, (sqlite3_int64)node_id);
sqlite3_bind_int(stmt, 2, fm); sqlite3_bind_int(stmt2, 2, fm);
sqlite3_bind_int(stmt, 3, (int)proto); sqlite3_bind_blob(stmt2, 3, ip, ip_len, SQLITE_STATIC);
sqlite3_bind_blob(stmt, 4, ip, ip_len, SQLITE_STATIC); sqlite3_bind_int(stmt2, 4, (int)port);
sqlite3_bind_int(stmt, 5, (int)port); sqlite3_bind_int(stmt2, 5, (int)sid);
sqlite3_bind_int(stmt, 6, (int)sid); sqlite3_step(stmt2); sqlite3_finalize(stmt2);
sqlite3_step(stmt); sqlite3_finalize(stmt); }
}
if (fm == 4) if (fm == 4)
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: [ADDR_SYNC] WELCOME INSERT node=0x%016llx sock=%d %d.%d.%d.%d:%d", DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: [ADDR_SYNC] WELCOME INSERT node=0x%016llx sock=%d %d.%d.%d.%d:%d",
CS_ID, (unsigned long long)node_id, sid, ip[0], ip[1], ip[2], ip[3], port); CS_ID, (unsigned long long)node_id, sid, ip[0], ip[1], ip[2], ip[3], port);
@ -1427,12 +1433,12 @@ static void cs_handle_peer_upsert(struct chat_sync* cs, uint64_t peer,
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: [ADDR_SYNC] PEER_UPSERT save addrs node=0x%016llx ac=%d", CS_ID, (unsigned long long)node_id, ac); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: [ADDR_SYNC] PEER_UPSERT save addrs node=0x%016llx ac=%d", CS_ID, (unsigned long long)node_id, ac);
for (uint8_t i = 0; i < ac; i++) { for (uint8_t i = 0; i < ac; i++) {
if (p + 2 > pl + len) break; if (p + 2 > pl + len) { DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: PEER_UPSERT addr[%u] header truncated node=0x%016llx", CS_ID, i, (unsigned long long)node_id); break; }
uint8_t fm = *p++; uint8_t fm = *p++;
uint8_t sid = *p++; uint8_t sid = *p++;
uint8_t proto = *p++; uint8_t proto = *p++;
int ip_len = (fm == 4) ? 4 : 16; int ip_len = (fm == 4) ? 4 : 16;
if (p + ip_len + 2 > pl + len) break; if (p + ip_len + 2 > pl + len) { DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: PEER_UPSERT addr[%u] ip truncated node=0x%016llx fm=%u", CS_ID, i, (unsigned long long)node_id, fm); break; }
const uint8_t* ip = p; p += ip_len; const uint8_t* ip = p; p += ip_len;
uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2; uint16_t port = ((uint16_t)p[0] << 8) | p[1]; p += 2;
@ -1509,7 +1515,8 @@ static void cs_handle_channel_invite(struct chat_sync* cs, uint64_t peer,
uint8_t inv_flags = *p++; uint8_t inv_flags = *p++;
const uint8_t* inviter_join_sig = NULL; uint64_t inviter_join_ts = 0; const uint8_t* inviter_join_sig = NULL; uint64_t inviter_join_ts = 0;
if (inv_flags & PEERS_FLAG_HAS_JOIN) { if (inv_flags & PEERS_FLAG_HAS_JOIN) {
if (p + 72 > pl + len) return; inviter_join_sig = p; p += 64; memcpy(&inviter_join_ts, p, 8); p += 8; } if (p + 72 > pl + len) { DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: CHANNEL_INVITE truncated at join_sig/ts from=%016llx", CS_ID, (unsigned long long)peer); return; }
inviter_join_sig = p; p += 64; memcpy(&inviter_join_ts, p, 8); p += 8; }
/* skip inviter_update_sig/ts/userinfo for now — verify channel sig only */ /* skip inviter_update_sig/ts/userinfo for now — verify channel sig only */
p += 64; uint64_t inviter_update_ts; memcpy(&inviter_update_ts, p, 8); p += 8; p += 64; uint64_t inviter_update_ts; memcpy(&inviter_update_ts, p, 8); p += 8;
uint8_t userinfo_len = *p++; p += userinfo_len; uint8_t userinfo_len = *p++; p += userinfo_len;
@ -1583,8 +1590,11 @@ static void cs_handle_channel_invite(struct chat_sync* cs, uint64_t peer,
/* ─── chat_sync_invite_to_channel: пригласить узел в наш канал ─── */ /* ─── chat_sync_invite_to_channel: пригласить узел в наш канал ─── */
void chat_sync_invite_to_channel(struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t target_node_id) { void chat_sync_invite_to_channel(struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t target_node_id) {
if (!g_cs || !inst || !ch_id || !ch_id[0]) return; if (!g_cs) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: invite_to_channel: g_cs=NULL, chat_sync not initialized", CS_ID); return; }
if (target_node_id == 0 || target_node_id == inst->node_id) return; if (!inst) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: invite_to_channel: inst=NULL", CS_ID); return; }
if (!ch_id || !ch_id[0]) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: invite_to_channel: ch_id NULL/empty", CS_ID); return; }
if (target_node_id == 0) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: invite_to_channel: target_node_id=0", CS_ID); return; }
if (target_node_id == inst->node_id) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: invite_to_channel: self-invite rejected self=0x%016llx", CS_ID, (unsigned long long)inst->node_id); return; }
uint64_t channel_id = strtoull(ch_id, NULL, 10); uint64_t channel_id = strtoull(ch_id, NULL, 10);
if (channel_id == 0) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: invite_to_channel invalid ch_id='%s'", CS_ID, ch_id); return; } if (channel_id == 0) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: invite_to_channel invalid ch_id='%s'", CS_ID, ch_id); return; }

33
tools/chatgui/src/invitedialog.cpp

@ -151,6 +151,39 @@ void InviteDialog::onSendInvite() {
} }
uint64_t targetNodeId = sc_derive_node_id_from_pubkey((const uint8_t*)d.pubkey.constData()); uint64_t targetNodeId = sc_derive_node_id_from_pubkey((const uint8_t*)d.pubkey.constData());
/* diagnostic: show decoded link info */
{
uint64_t myNodeId = m_node ? m_node->nodeIdHex().toULongLong(nullptr, 16) : 0;
QString pkHex = QString::fromLatin1(d.pubkey.toHex());
QString pkShort = pkHex.left(8) + ".." + pkHex.right(4);
QString addrInfo;
for (int i = 0; i < d.addrs.size() && i < 3; i++) {
if (i > 0) addrInfo += ", ";
uint32_t ip4 = 0;
if (d.addrs[i].family == 4 && d.addrs[i].address.size() >= 4) {
memcpy(&ip4, d.addrs[i].address.constData(), 4);
addrInfo += QString("%1.%2.%3.%4:%5")
.arg((ip4>>24)&0xFF).arg((ip4>>16)&0xFF).arg((ip4>>8)&0xFF).arg(ip4&0xFF)
.arg(d.addrs[i].port);
} else {
addrInfo += QString("v%1:%2").arg(d.addrs[i].family).arg(d.addrs[i].port);
}
}
if (d.addrs.size() > 3) addrInfo += QString(" +%1 more").arg(d.addrs.size() - 3);
QString diag = QString("Ссылка: узел 0x%1 ключ %2, %3 адр. (%4)")
.arg(targetNodeId, 16, 16, QChar('0'))
.arg(pkShort)
.arg(d.addrs.size())
.arg(addrInfo);
GUI_INFO("invite_by_link: %s", diag.toUtf8().constData());
if (myNodeId != 0 && myNodeId == targetNodeId) {
GUI_WARN("invite_by_link: self-invite rejected — link contains own pubkey, node=0x%016llx", (unsigned long long)myNodeId);
setInviteStatus("Ошибка: это ваша собственная ссылка (нельзя пригласить себя)", true);
return;
}
setInviteStatus(diag);
}
m_inviteSending = true; m_inviteSending = true;
m_inviteTargetNodeId = targetNodeId; m_inviteTargetNodeId = targetNodeId;
m_inviteSendBtn->setEnabled(false); m_inviteSendBtn->setEnabled(false);

Loading…
Cancel
Save