chat_join: модуль join-протокола, invite-ссылки v2, синхронизация мемберов
This commit is contained in:
1 parent
a01a4ddba4
commit
75e39d2fee
41 files changed
+2206
-471
No files matched your search
+168
-14
@@ -41,6 +41,7 @@ static void _compute_member_hash(uint64_t node_id, const uint8_t* x25519,
|
||||
const uint8_t* join_sig, uint64_t join_ts,
|
||||
const uint8_t* update_sig, uint64_t update_ts,
|
||||
const char* adm_tags, const uint8_t* adm_tags_sig,
|
||||
uint64_t signed_by, const uint8_t* signature,
|
||||
uint8_t hash_out[MT_HASH_SIZE]) {
|
||||
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
|
||||
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
|
||||
@@ -57,6 +58,9 @@ static void _compute_member_hash(uint64_t node_id, const uint8_t* x25519,
|
||||
if (atl) EVP_DigestUpdate(ctx, adm_tags, atl);
|
||||
if (adm_tags_sig) EVP_DigestUpdate(ctx, adm_tags_sig, 64); else { static const uint8_t z64[64]; EVP_DigestUpdate(ctx, z64, 64); }
|
||||
|
||||
EVP_DigestUpdate(ctx, &signed_by, 8);
|
||||
if (signature) EVP_DigestUpdate(ctx, signature, 64); else { static const uint8_t zsig[64]; EVP_DigestUpdate(ctx, zsig, 64); }
|
||||
|
||||
EVP_DigestFinal_ex(ctx, hash_out, NULL);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
}
|
||||
@@ -119,7 +123,7 @@ static int _member_update_bucket_hash(void* ctx, const char* ns, uint8_t level,
|
||||
|
||||
char sql[512]; snprintf(sql, sizeof(sql),
|
||||
"SELECT node_id, x25519_pubkey, ed25519_pubkey,"
|
||||
" join_sig, join_ts, update_sig, update_ts, adm_tags, adm_tags_sig, source"
|
||||
" join_sig, join_ts, update_sig, update_ts, adm_tags, adm_tags_sig, signed_by, signature, source"
|
||||
" FROM \"%s\""
|
||||
" WHERE (node_id & %lld) == %lld ORDER BY node_id ASC",
|
||||
peers_tbl, (long long)mask, (long long)prefix64);
|
||||
@@ -138,11 +142,13 @@ static int _member_update_bucket_hash(void* ctx, const char* ns, uint8_t level,
|
||||
uint64_t uts = (uint64_t)sqlite3_column_int64(stmt, 6);
|
||||
const char* atags = (const char*)sqlite3_column_text(stmt, 7);
|
||||
const uint8_t* atsig = (const uint8_t*)sqlite3_column_blob(stmt, 8);
|
||||
int src = sqlite3_column_int(stmt, 9);
|
||||
uint64_t sb = (uint64_t)sqlite3_column_int64(stmt, 9);
|
||||
const uint8_t* sgn = (const uint8_t*)sqlite3_column_blob(stmt, 10);
|
||||
int src = sqlite3_column_int(stmt, 11);
|
||||
if (!x25 || !ed || src != 0) continue;
|
||||
|
||||
uint8_t mh[MT_HASH_SIZE];
|
||||
_compute_member_hash(nid, x25, ed, sig, jts, usig, uts, atags, atsig, mh);
|
||||
_compute_member_hash(nid, x25, ed, sig, jts, usig, uts, atags, atsig, sb, sgn, mh);
|
||||
EVP_DigestUpdate(sha_ctx, mh, MT_HASH_SIZE);
|
||||
count++;
|
||||
}
|
||||
@@ -164,7 +170,8 @@ static int _member_get_items(void* ctx, const char* ns, uint8_t level,
|
||||
|
||||
char sql[512]; snprintf(sql, sizeof(sql),
|
||||
"SELECT node_id, x25519_pubkey, ed25519_pubkey,"
|
||||
" join_sig, join_ts, update_sig, update_ts, userinfo, adm_tags, adm_tags_sig, source"
|
||||
" join_sig, join_ts, update_sig, update_ts, userinfo, adm_tags, adm_tags_sig,"
|
||||
" signed_by, signature, source"
|
||||
" FROM \"%s\""
|
||||
" WHERE (node_id & %lld) == %lld ORDER BY node_id ASC",
|
||||
peers_tbl, (long long)mask, (long long)prefix);
|
||||
@@ -187,13 +194,15 @@ static int _member_get_items(void* ctx, const char* ns, uint8_t level,
|
||||
const char* nm = (const char*)sqlite3_column_text(stmt, 7);
|
||||
const char* atags = (const char*)sqlite3_column_text(stmt, 8);
|
||||
const uint8_t* atsig = (const uint8_t*)sqlite3_column_blob(stmt, 9);
|
||||
int src = sqlite3_column_int(stmt, 10);
|
||||
uint64_t sb = (uint64_t)sqlite3_column_int64(stmt, 10);
|
||||
const uint8_t* sgn = (const uint8_t*)sqlite3_column_blob(stmt, 11);
|
||||
int src = sqlite3_column_int(stmt, 12);
|
||||
if (!x25 || !ed || src != 0) continue;
|
||||
uint8_t nl = nm ? (uint8_t)strnlen(nm, 255) : 0;
|
||||
uint8_t atl = atags ? (uint8_t)strnlen(atags, 255) : 0;
|
||||
|
||||
uint8_t flags = (sig && jts) ? PEERS_FLAG_HAS_JOIN : 0;
|
||||
size_t need = 8 + 32 + 32 + 1 + (flags ? 72ULL : 0ULL) + 64 + 8 + 1 + (size_t)nl + 1 + (size_t)atl + 64;
|
||||
size_t need = 8 + 32 + 32 + 1 + (flags ? 72ULL : 0ULL) + 64 + 8 + 1 + (size_t)nl + 1 + (size_t)atl + 64 + 8 + 64;
|
||||
if (off + need > *len) { sqlite3_finalize(stmt); return -2; }
|
||||
memcpy(buf + off, &nid, 8); off += 8;
|
||||
memcpy(buf + off, x25, 32); off += 32;
|
||||
@@ -216,6 +225,9 @@ static int _member_get_items(void* ctx, const char* ns, uint8_t level,
|
||||
if (atl) { memcpy(buf + off, atags, atl); off += atl; }
|
||||
if (atsig && sqlite3_column_bytes(stmt, 9) >= 64) { memcpy(buf + off, atsig, 64); off += 64; }
|
||||
else { memset(buf + off, 0, 64); off += 64; }
|
||||
memcpy(buf + off, &sb, 8); off += 8;
|
||||
if (sgn && sqlite3_column_bytes(stmt, 11) >= 64) { memcpy(buf + off, sgn, 64); off += 64; }
|
||||
else { memset(buf + off, 0, 64); off += 64; }
|
||||
(*cnt)++;
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
@@ -257,6 +269,40 @@ void member_sync_remove_props_cbk(node_props_changed_fn fn, void* arg) {
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Коллбэк применения рекорда мембера (ready-хендлинг join на connection-узле) ── */
|
||||
|
||||
struct ms_apply_cbk { member_apply_cbk_fn fn; void* arg; struct ms_apply_cbk* next; };
|
||||
static struct ms_apply_cbk* g_apply_cbks = NULL;
|
||||
|
||||
static void _fire_apply_cbk(const char* ch_id, uint64_t node_id,
|
||||
const uint8_t* x25519, uint64_t signed_by,
|
||||
const uint8_t* signature) {
|
||||
struct ms_apply_cbk* ac = g_apply_cbks;
|
||||
while (ac) { ac->fn(ch_id, node_id, x25519, signed_by, signature, ac->arg); ac = ac->next; }
|
||||
}
|
||||
|
||||
void member_sync_add_apply_cbk(member_apply_cbk_fn fn, void* arg) {
|
||||
if (!fn) return;
|
||||
struct ms_apply_cbk* e = u_malloc(sizeof(*e));
|
||||
if (!e) return;
|
||||
e->fn = fn; e->arg = arg;
|
||||
e->next = g_apply_cbks;
|
||||
g_apply_cbks = e;
|
||||
}
|
||||
|
||||
void member_sync_remove_apply_cbk(member_apply_cbk_fn fn, void* arg) {
|
||||
if (!fn) return;
|
||||
struct ms_apply_cbk** p = &g_apply_cbks;
|
||||
while (*p) {
|
||||
if ((*p)->fn == fn && (*p)->arg == arg) {
|
||||
struct ms_apply_cbk* r = *p;
|
||||
*p = r->next; u_free(r);
|
||||
return;
|
||||
}
|
||||
p = &(*p)->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── BGP node event callback: BGP сообщает member_sync об обновлении адресов/классификации.
|
||||
Классификацию node_type/storage пересчитывает сам BGP (nodeinfo_updated);
|
||||
member_sync только рассылает node_props_changed потребителям. ── */
|
||||
@@ -316,6 +362,60 @@ static int _verify_join_sig(sqlite3* db, const char* ch_id, const struct ms_memb
|
||||
return ok ? 1 : 0;
|
||||
}
|
||||
|
||||
/* ── Дерево приглашений: подпись pubkey узла ── */
|
||||
|
||||
int member_sync_build_sign_msg(const uint8_t* x25519, uint8_t* out, int out_sz) {
|
||||
if (!x25519 || !out || out_sz < MEMBER_SIGN_MSG_SIZE) return -1;
|
||||
memcpy(out, x25519, SC_PUBKEY_SIZE);
|
||||
memcpy(out + SC_PUBKEY_SIZE, MEMBER_SIGN_SUFFIX, MEMBER_SIGN_SUFFIX_LEN);
|
||||
return MEMBER_SIGN_MSG_SIZE;
|
||||
}
|
||||
|
||||
int member_sync_sign_pubkey(const uint8_t* signer_ed_priv, const uint8_t* x25519, uint8_t sig[64]) {
|
||||
if (!signer_ed_priv || !x25519 || !sig) return -1;
|
||||
uint8_t msg[MEMBER_SIGN_MSG_SIZE];
|
||||
if (member_sync_build_sign_msg(x25519, msg, (int)sizeof(msg)) < 0) return -1;
|
||||
if (sc_ed25519_sign(signer_ed_priv, msg, sizeof(msg), sig) != SC_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: sign_pubkey — sc_ed25519_sign FAILED", MS_ID);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int member_sync_verify_signature(sqlite3* db, const char* ch_id, const struct ms_member_rec* m) {
|
||||
if (!db || !ch_id || !m || !m->x25519 || !m->signature || _sig_is_zero64(m->signature)) return 0;
|
||||
uint8_t msg[MEMBER_SIGN_MSG_SIZE];
|
||||
if (member_sync_build_sign_msg(m->x25519, msg, (int)sizeof(msg)) < 0) return -1;
|
||||
|
||||
uint8_t signer_pub[32];
|
||||
if (m->signed_by == 0) {
|
||||
if (topo_node_sqlite_channel_get(db, ch_id, NULL, 0, NULL, NULL, signer_pub, NULL) != 0) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_MEMBER_SYNC, "%s: verify_signature — no channel key ns=%s (defer)", MS_ID, ch_id);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (topo_node_sqlite_get_ed25519_pubkey(db, m->signed_by, signer_pub) != 0) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_MEMBER_SYNC, "%s: verify_signature — no ed25519 pubkey for signed_by=0x%016llx ns=%s (defer)", MS_ID, (unsigned long long)m->signed_by, ch_id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int ok = sc_ed25519_verify(signer_pub, msg, sizeof(msg), m->signature) == SC_OK;
|
||||
if (!ok)
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: verify_signature FAIL nid=0x%016llx signed_by=0x%016llx ns=%s",
|
||||
MS_ID, (unsigned long long)m->node_id, (unsigned long long)m->signed_by, ch_id);
|
||||
return ok ? 1 : 0;
|
||||
}
|
||||
|
||||
int member_sync_validate_pubkey(struct UTUN_INSTANCE* inst, const char* ch_id,
|
||||
const uint8_t* x25519_pubkey) {
|
||||
if (!inst || !ch_id || !x25519_pubkey) return 0;
|
||||
sqlite3* db = _db(inst); if (!db) return 0;
|
||||
uint64_t node_id = sc_derive_node_id_from_pubkey(x25519_pubkey);
|
||||
if (node_id == 0) return 0;
|
||||
return topo_node_sqlite_member_in_channel(db, ch_id, node_id);
|
||||
}
|
||||
|
||||
int member_sync_apply_record(struct UTUN_INSTANCE* inst, const char* ch_id,
|
||||
uint64_t from_peer, const struct ms_member_rec* m) {
|
||||
if (!inst || !ch_id || !m || !m->x25519 || !m->ed25519) {
|
||||
@@ -336,10 +436,12 @@ int member_sync_apply_record(struct UTUN_INSTANCE* inst, const char* ch_id,
|
||||
uint8_t local_join_sig[64] = {0}; uint64_t local_join_ts = 0;
|
||||
uint64_t local_update_ts = 0;
|
||||
char local_tags[256] = "";
|
||||
uint64_t local_signed_by = 0;
|
||||
uint8_t local_signature[64] = {0};
|
||||
{
|
||||
sqlite3_stmt* st = NULL;
|
||||
char sql[512]; snprintf(sql, sizeof(sql),
|
||||
"SELECT join_sig, join_ts, update_ts, adm_tags FROM \"%s\" WHERE node_id=?", peers_tbl);
|
||||
"SELECT join_sig, join_ts, update_ts, adm_tags, signed_by, signature FROM \"%s\" WHERE node_id=?", peers_tbl);
|
||||
if (sqlite3_prepare_v2(db, sql, -1, &st, NULL) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(st, 1, (sqlite3_int64)m->node_id);
|
||||
if (sqlite3_step(st) == SQLITE_ROW) {
|
||||
@@ -350,6 +452,9 @@ int member_sync_apply_record(struct UTUN_INSTANCE* inst, const char* ch_id,
|
||||
local_update_ts = (uint64_t)sqlite3_column_int64(st, 2);
|
||||
const char* tags = (const char*)sqlite3_column_text(st, 3);
|
||||
if (tags) snprintf(local_tags, sizeof(local_tags), "%s", tags);
|
||||
local_signed_by = (uint64_t)sqlite3_column_int64(st, 4);
|
||||
const uint8_t* ls = (const uint8_t*)sqlite3_column_blob(st, 5);
|
||||
if (ls && sqlite3_column_bytes(st, 5) >= 64) memcpy(local_signature, ls, 64);
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
}
|
||||
@@ -371,6 +476,15 @@ int member_sync_apply_record(struct UTUN_INSTANCE* inst, const char* ch_id,
|
||||
identity_ok = 0;
|
||||
}
|
||||
}
|
||||
/* подпись дерева приглашений: -1 = родитель ещё не пришёл (defer до verify_local), 0 = явная подделка */
|
||||
if (identity_ok && m->signature && !_sig_is_zero64(m->signature)) {
|
||||
int sv = member_sync_verify_signature(db, ch_id, m);
|
||||
if (sv == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: apply_record invalid tree-signature (forgery) nid=0x%016llx signed_by=0x%016llx ns=%s",
|
||||
MS_ID, (unsigned long long)m->node_id, (unsigned long long)m->signed_by, ch_id);
|
||||
identity_ok = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int block_a_ok = 0;
|
||||
@@ -462,9 +576,12 @@ int member_sync_apply_record(struct UTUN_INSTANCE* inst, const char* ch_id,
|
||||
/* ── запись изменённых блоков ── */
|
||||
if (block_a_changed) {
|
||||
const uint8_t* jsig = m->join_sig ? m->join_sig : (has_local ? local_join_sig : NULL);
|
||||
/* дерево приглашений: если в обновлении подписи нет — сохраняем локальную (set один раз при join/create) */
|
||||
uint64_t w_signed_by = m->signature ? m->signed_by : local_signed_by;
|
||||
const uint8_t* w_signature = m->signature ? m->signature : (has_local ? local_signature : NULL);
|
||||
if (topo_node_sqlite_member_block_put(db, ch_id, m->node_id, jsig, m->join_ts,
|
||||
m->update_sig, m->update_ts, m->x25519, m->ed25519,
|
||||
m->userinfo ? m->userinfo : "", NULL) != 0) {
|
||||
m->userinfo ? m->userinfo : "", NULL, w_signed_by, w_signature) != 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: apply_record block_put FAILED ch=%s nid=0x%016llx", MS_ID, ch_id, (unsigned long long)m->node_id);
|
||||
return -1;
|
||||
}
|
||||
@@ -572,6 +689,17 @@ int member_sync_verify_local_record(struct sqlite3* db, const char* ch_id, const
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* дерево приглашений: подпись есть и невалидна (подписант резолвится) — битая запись.
|
||||
-1 = родитель ещё не пришёл — не трогаем (не битая). */
|
||||
if (m->signature && !_sig_is_zero64(m->signature)) {
|
||||
int sv = member_sync_verify_signature(db, ch_id, m);
|
||||
if (sv == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: verify_local — invalid tree-signature nid=0x%016llx signed_by=0x%016llx ns=%s",
|
||||
MS_ID, (unsigned long long)m->node_id, (unsigned long long)m->signed_by, ch_id);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -584,7 +712,8 @@ int member_sync_verify_and_purge(struct UTUN_INSTANCE* inst, const char* ch_id)
|
||||
sqlite3_stmt* st = NULL;
|
||||
char sql[512]; snprintf(sql, sizeof(sql),
|
||||
"SELECT node_id, x25519_pubkey, ed25519_pubkey,"
|
||||
" join_sig, join_ts, update_sig, update_ts, userinfo, adm_tags, adm_tags_sig, source"
|
||||
" join_sig, join_ts, update_sig, update_ts, userinfo, adm_tags, adm_tags_sig,"
|
||||
" signed_by, signature, source"
|
||||
" FROM \"%s\" ORDER BY node_id ASC", peers_tbl);
|
||||
if (sqlite3_prepare_v2(db, sql, -1, &st, NULL) != SQLITE_OK) return 0;
|
||||
|
||||
@@ -600,7 +729,9 @@ int member_sync_verify_and_purge(struct UTUN_INSTANCE* inst, const char* ch_id)
|
||||
const char* nm = (const char*)sqlite3_column_text(st, 7);
|
||||
const char* atags = (const char*)sqlite3_column_text(st, 8);
|
||||
const uint8_t* atsig = (const uint8_t*)sqlite3_column_blob(st, 9);
|
||||
int src = sqlite3_column_int(st, 10);
|
||||
uint64_t sb = (uint64_t)sqlite3_column_int64(st, 10);
|
||||
const uint8_t* sgn = (const uint8_t*)sqlite3_column_blob(st, 11);
|
||||
int src = sqlite3_column_int(st, 12);
|
||||
if (!x25 || !ed) continue;
|
||||
if (src != 0) continue; /* плейсхолдер topo_group — не верифицируем */
|
||||
|
||||
@@ -612,6 +743,7 @@ int member_sync_verify_and_purge(struct UTUN_INSTANCE* inst, const char* ch_id)
|
||||
m.update_sig = usig; m.update_ts = uts;
|
||||
m.userinfo = nm;
|
||||
m.adm_tags = atags; m.adm_tags_sig = atsig;
|
||||
m.signed_by = sb; m.signature = sgn;
|
||||
|
||||
if (!member_sync_verify_local_record(db, ch_id, &m)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: verify_and_purge — PURGE broken record nid=0x%016llx ns=%s",
|
||||
@@ -688,6 +820,8 @@ static int _member_apply_items(void* ctx, const char* ns, uint64_t from_peer,
|
||||
const uint8_t* atsig = NULL;
|
||||
if (atl && mrem >= atl) { memcpy(atags, mp, atl); atags[atl] = '\0'; mp += atl; mrem -= atl; }
|
||||
if (mrem >= 64) { atsig = mp; mp += 64; mrem -= 64; }
|
||||
uint64_t sb = 0; const uint8_t* sgn = NULL;
|
||||
if (mrem >= 72) { memcpy(&sb, mp, 8); mp += 8; mrem -= 8; sgn = mp; mp += 64; mrem -= 64; }
|
||||
|
||||
struct ms_member_rec m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
@@ -698,6 +832,7 @@ static int _member_apply_items(void* ctx, const char* ns, uint64_t from_peer,
|
||||
m.userinfo = nm;
|
||||
m.adm_tags = atags[0] ? atags : NULL;
|
||||
m.adm_tags_sig = atsig;
|
||||
m.signed_by = sb; m.signature = sgn;
|
||||
|
||||
int r = member_sync_apply_record(inst, ns, from_peer, &m);
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_MEMBER_SYNC, "%s: member_sync recv ns=%s nid=0x%016llx r=%d", MS_ID, ns, (unsigned long long)nid, r);
|
||||
@@ -710,6 +845,8 @@ static int _member_apply_items(void* ctx, const char* ns, uint64_t from_peer,
|
||||
const char* tags_final = atags[0] ? atags : NULL;
|
||||
while (pc) { pc->fn(nid, tags_final, ns, pc->arg); pc = pc->next; }
|
||||
}
|
||||
/* fire apply callbacks (ready-хендлинг join на connection-узле) */
|
||||
_fire_apply_cbk(ns, nid, x25, sb, sgn);
|
||||
}
|
||||
if (r & MS_APPLY_STALE) {
|
||||
/* у нас версия новее — отправить наш полный рекорд автору */
|
||||
@@ -721,11 +858,19 @@ static int _member_apply_items(void* ctx, const char* ns, uint64_t from_peer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _member_validate_peer(void* ctx, const char* ns, uint64_t peer) {
|
||||
struct UTUN_INSTANCE* inst = (struct UTUN_INSTANCE*)ctx;
|
||||
sqlite3* db = _db(inst);
|
||||
if (!db) return 0;
|
||||
return topo_node_sqlite_member_in_channel(db, ns, peer);
|
||||
}
|
||||
|
||||
static const struct merkle_sync_data_ops g_member_ops = {
|
||||
.update_bucket_hash = _member_update_bucket_hash,
|
||||
.get_items = _member_get_items,
|
||||
.apply_items = _member_apply_items,
|
||||
.apply_update = NULL, /* online-статус больше не рассылается через merkle */
|
||||
.validate_peer = _member_validate_peer,
|
||||
};
|
||||
|
||||
/* ── Public API ── */
|
||||
@@ -828,7 +973,8 @@ static int _serialize_member(struct UTUN_INSTANCE* inst, const char* ch_id, uint
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
char sql[512]; snprintf(sql, sizeof(sql),
|
||||
"SELECT node_id, x25519_pubkey, ed25519_pubkey,"
|
||||
" join_sig, join_ts, update_sig, update_ts, userinfo, adm_tags, adm_tags_sig"
|
||||
" join_sig, join_ts, update_sig, update_ts, userinfo, adm_tags, adm_tags_sig,"
|
||||
" signed_by, signature"
|
||||
" FROM \"%s\" WHERE node_id=?", peers_tbl);
|
||||
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: serialize_member — query failed ch=%s nid=0x%016llx", MS_ID, ch_id, (unsigned long long)member_id);
|
||||
@@ -847,13 +993,15 @@ static int _serialize_member(struct UTUN_INSTANCE* inst, const char* ch_id, uint
|
||||
const char* nm = (const char*)sqlite3_column_text(stmt, 7);
|
||||
const char* atags = (const char*)sqlite3_column_text(stmt, 8);
|
||||
const uint8_t* atsig = (const uint8_t*)sqlite3_column_blob(stmt, 9);
|
||||
uint64_t sb = (uint64_t)sqlite3_column_int64(stmt, 10);
|
||||
const uint8_t* sgn = (const uint8_t*)sqlite3_column_blob(stmt, 11);
|
||||
if (!x25 || !ed) { sqlite3_finalize(stmt); return -1; }
|
||||
uint8_t nl = nm ? (uint8_t)strnlen(nm, 255) : 0;
|
||||
uint8_t atl = atags ? (uint8_t)strnlen(atags, 255) : 0;
|
||||
|
||||
uint8_t flags = (sig && jts) ? PEERS_FLAG_HAS_JOIN : 0;
|
||||
size_t need = 2 + 8 + 32 + 32 + 1 + (flags & PEERS_FLAG_HAS_JOIN ? 72 : 0)
|
||||
+ 72 + 1 + (size_t)nl + 1 + (size_t)atl + 64;
|
||||
+ 72 + 1 + (size_t)nl + 1 + (size_t)atl + 64 + 8 + 64;
|
||||
if (need > buf_sz) { sqlite3_finalize(stmt); return -1; }
|
||||
size_t off = 0;
|
||||
uint16_t wcnt = 1; memcpy(buf, &wcnt, 2); off += 2;
|
||||
@@ -869,6 +1017,10 @@ static int _serialize_member(struct UTUN_INSTANCE* inst, const char* ch_id, uint
|
||||
if (atsig && sqlite3_column_bytes(stmt, 9) >= 64) { memcpy(buf + off, atsig, 64); }
|
||||
else { memset(buf + off, 0, 64); }
|
||||
off += 64;
|
||||
memcpy(buf + off, &sb, 8); off += 8;
|
||||
if (sgn && sqlite3_column_bytes(stmt, 11) >= 64) { memcpy(buf + off, sgn, 64); }
|
||||
else { memset(buf + off, 0, 64); }
|
||||
off += 64;
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
*out_len = off;
|
||||
@@ -896,9 +1048,10 @@ int member_sync_put(struct UTUN_INSTANCE* inst, const char* ch_id,
|
||||
const uint8_t* join_sig, uint64_t join_ts,
|
||||
const uint8_t* update_sig, uint64_t update_ts,
|
||||
const char* userinfo,
|
||||
const char* adm_tags, const uint8_t* adm_tags_sig, int storage) {
|
||||
const char* adm_tags, const uint8_t* adm_tags_sig, int storage,
|
||||
uint64_t signed_by, const uint8_t* signature) {
|
||||
if (!inst || !ch_id) { DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: put — inst=%p ch_id=%s", MS_ID, (void*)inst, ch_id ? ch_id : "(null)"); return -1; }
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_MEMBER_SYNC, "%s: put ch=%s nid=%016llx userinfo=%s adm_tags=%s storage=%d", MS_ID, ch_id, (unsigned long long)member_id, userinfo ? userinfo : "", adm_tags ? adm_tags : "", storage);
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_MEMBER_SYNC, "%s: put ch=%s nid=%016llx userinfo=%s adm_tags=%s storage=%d signed_by=%016llx", MS_ID, ch_id, (unsigned long long)member_id, userinfo ? userinfo : "", adm_tags ? adm_tags : "", storage, (unsigned long long)signed_by);
|
||||
|
||||
struct ms_member_rec m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
@@ -908,6 +1061,7 @@ int member_sync_put(struct UTUN_INSTANCE* inst, const char* ch_id,
|
||||
m.update_sig = update_sig; m.update_ts = update_ts;
|
||||
m.userinfo = userinfo;
|
||||
m.adm_tags = adm_tags; m.adm_tags_sig = adm_tags_sig; m.storage = storage;
|
||||
m.signed_by = signed_by; m.signature = signature;
|
||||
|
||||
return member_sync_apply_record(inst, ch_id, inst->node_id, &m);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user