Browse Source

fix: wall-clock timestamps + merkle_sync timeout + build script

- Replace get_time_us() with utun_gettimeofday() for PUSH message timestamps
  (db_sync.c, chat_core.c) — monotonic clocks differ across Linux/Windows
- Fix merkle_sync: restart session timer in _handle_request to prevent
  double-sided timeout when both nodes start member_sync simultaneously
- Fix INIT_RESP short-format: don't mark synced when my_count > peer_count
- Add db_sync_get_last_timestamp() to avoid duplicate timestamp generation
  between db_sync and chat_core on_db_sync_insert
- Fix db_sync_stub to generate timestamps consistently
- build.sh: auto-rebuild chatgui via CMake after utun build
topo_upd
Evgeny 3 months ago
parent
commit
5fc621690a
  1. 9
      build.sh
  2. 6
      src/db_sync.c
  3. 1
      src/db_sync.h
  4. 2
      tools/chatgui/transport/chat_core.c
  5. 7
      tools/chatgui/transport/chat_sync.c
  6. 8
      tools/chatgui/transport/db_sync_stub.c
  7. 9
      tools/chatgui/transport/merkle_sync.c

9
build.sh

@ -180,6 +180,15 @@ if [ $BUILD_SUCCESS -eq 1 ]; then
echo ""
echo "Build completed successfully!"
echo "Binary: utun"
# Rebuild chatgui (CMake project) if transport sources changed
if [ -f tools/chatgui/build/CMakeCache.txt ] && command -v cmake &> /dev/null; then
echo ""
echo "======================================"
echo "Rebuilding chatgui (CMake)"
echo "======================================"
(cd tools/chatgui/build && cmake --build . -j4 2>&1) || echo "WARNING: chatgui build failed"
fi
else
echo ""
echo "ERROR: Build failed!"

6
src/db_sync.c

@ -351,7 +351,9 @@ int db_sync_insert_len(struct DB_SYNC_INSTANCE* si, const char* json_data, size_
int db_sync_insert_signed(struct DB_SYNC_INSTANCE* si, const char* json_data, size_t len, const uint8_t* sig, size_t sig_len) {
if (!si||!si->enabled||!json_data||len==0) { DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC,"insert invalid args"); return -1; }
uint64_t dh=db_datahash((const uint8_t*)json_data,len), nu=get_time_us(); if (nu<=si->last_timestamp_us) nu=si->last_timestamp_us+1; si->last_timestamp_us=nu; uint64_t ts=nu, id=si->next_id;
struct timeval tv; utun_gettimeofday(&tv, NULL); uint64_t nu=(uint64_t)tv.tv_sec*1000000ULL+(uint64_t)tv.tv_usec;
if (nu<=si->last_timestamp_us) nu=si->last_timestamp_us+1; si->last_timestamp_us=nu;
uint64_t dh=db_datahash((const uint8_t*)json_data,len), ts=nu, id=si->next_id;
int ret=db_record_insert(si,id,ts,dh,json_data,len,sig,sig_len); if (ret!=0) return ret;
if (si->on_insert) si->on_insert(si,json_data,len,si->db_sync->inst->node_id,si->on_insert_arg);
// Build PUSH: [DB_MSG_PUSH][id:8][ts:8][dh:8][dlen:4][data][sig_len:1][sig]
@ -370,6 +372,8 @@ uint32_t db_sync_count(struct DB_SYNC_INSTANCE* si) { if (!si||!si->enabled) ret
void db_sync_set_insert_cb(struct DB_SYNC_INSTANCE* si, db_sync_insert_cb cb, void* arg) { if (!si) return; si->on_insert=cb; si->on_insert_arg=arg; }
uint64_t db_sync_get_last_timestamp(struct DB_SYNC_INSTANCE* si) { return si ? si->last_timestamp_us : 0; }
int db_sync_select(struct DB_SYNC_INSTANCE* si, uint32_t offset, uint32_t limit, db_sync_select_cb cb, void* arg) {
if (!si||!si->enabled||!cb) return 0; sqlite3_stmt* stmt;
if (si_prep(si,&stmt,"SELECT id,timestamp,author,data,author_signature,delivered_peers,delivery_chain FROM \"%s\" ORDER BY timestamp,datahash LIMIT ? OFFSET ?")!=SQLITE_OK) return 0;

1
src/db_sync.h

@ -85,6 +85,7 @@ int db_sync_insert(struct DB_SYNC_INSTANCE* si, const char* json_data);
int db_sync_insert_signed(struct DB_SYNC_INSTANCE* si, const char* json_data, size_t len,
const uint8_t* sig, size_t sig_len);
uint32_t db_sync_count(struct DB_SYNC_INSTANCE* si);
uint64_t db_sync_get_last_timestamp(struct DB_SYNC_INSTANCE* si);
// Select: iterate records ordered by (timestamp, datahash), starting at offset, max limit (0=unlimited).
// Returns number of records passed to callback.

2
tools/chatgui/transport/chat_core.c

@ -1025,7 +1025,7 @@ static void on_db_sync_insert(struct DB_SYNC_INSTANCE* si, const char* data, siz
if (!jd_start) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: on_db_sync_insert JSON parse fail: no '\"d\"' field ch=%s", CC_ID, ch_id); return; }
uint64_t dh; compute_datahash((const uint8_t*)jd_start, jd_len, &dh);
uint64_t ts = get_time_us();
uint64_t ts = db_sync_get_last_timestamp(si);
char tbl[80]; msg_table_name(ch_id, tbl, sizeof(tbl));
uint8_t prev_ch[32]; get_last_chain_hash(ch_id, prev_ch);
uint8_t chain_h[32]; compute_chain_hash(prev_ch, (int64_t)ts, dh, chain_h);

7
tools/chatgui/transport/chat_sync.c

@ -189,9 +189,12 @@ static void cs_handle_init_resp(struct chat_sync* cs, uint64_t peer,
cs_send(cs, ch_id, peer, snd, 7);
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: INIT_RESP peer ahead (peer=%u my=%u), request from=%u",
CS_ID, peer_count, my_count, from);
} else {
} else if (peer_count == my_count) {
if (ch) ch->synced = CS_SYNC_DONE;
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: INIT_RESP synced (peer=%u <= my=%u)",
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: INIT_RESP synced (peer=%u == my=%u)",
CS_ID, peer_count, my_count);
} else {
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: INIT_RESP peer behind (peer=%u < my=%u), waiting for peer SEND_DATA",
CS_ID, peer_count, my_count);
}
}

8
tools/chatgui/transport/db_sync_stub.c

@ -21,6 +21,7 @@
struct DB_SYNC_INSTANCE {
struct DB_SYNC* db_sync;
uint8_t enabled;
uint64_t last_timestamp_us;
db_sync_insert_cb on_insert;
void* on_insert_arg;
};
@ -117,6 +118,8 @@ int db_sync_insert_signed(struct DB_SYNC_INSTANCE* si, const char* json_data,
size_t len, const uint8_t* sig, size_t sig_len) {
(void)sig; (void)sig_len;
if (!si || !si->enabled || !json_data || len == 0) return -1;
struct timeval tv; utun_gettimeofday(&tv, NULL);
si->last_timestamp_us = (uint64_t)tv.tv_sec * 1000000ULL + (uint64_t)tv.tv_usec;
if (si->on_insert)
si->on_insert(si, json_data, len, si->db_sync->inst->node_id, si->on_insert_arg);
return 0;
@ -152,3 +155,8 @@ void db_sync_set_insert_cb(struct DB_SYNC_INSTANCE* si, db_sync_insert_cb cb, vo
if (si->on_insert_arg) u_free(si->on_insert_arg);
si->on_insert_arg = arg;
}
uint64_t db_sync_get_last_timestamp(struct DB_SYNC_INSTANCE* si) {
if (!si) return 0;
return si->last_timestamp_us;
}

9
tools/chatgui/transport/merkle_sync.c

@ -417,7 +417,14 @@ static void _handle_request(struct merkle_sync* ms, uint64_t peer, const char* n
buckets[bc].level = lvl; buckets[bc].prefix_bytes = pb_i; buckets[bc].prefix = pr; bc++;
off++; /* skip is_terminal byte */
}
if (bc > 0) _send_batch(ms, peer, ns, buckets, bc);
if (bc > 0) {
_send_batch(ms, peer, ns, buckets, bc);
struct ms_session* s = _session_find(ms, peer, ns);
if (s && s->active) {
if (s->timer) { uasync_cancel_timeout(ms->inst->ua, s->timer); s->timer = NULL; }
_session_start_timer(s);
}
}
}
static void _handle_batch(struct merkle_sync* ms, uint64_t peer, const char* ns,

Loading…
Cancel
Save