Browse Source

fix segfault in ca_ready_cb: ca_state owns all ca_ctx, single cleanup point

- Added struct ca_ctx** ctxs to ca_state (parallel array)
- ca_cleanup now frees all ctxs[i] and the ctxs array
- ca_ready_cb: removed u_free(ctx), added etcp_conn_remove_ready_cbk before cleanup
- ca_timeout_cb: removed u_free(ctx) — ctx lives until ca_cleanup
- All error paths set ctxs[i]=NULL for ca_cleanup safety
topo_upd
Evgeny 3 months ago
parent
commit
f7d88e5532
  1. 19
      tools/chatgui/transport/chat_core.c

19
tools/chatgui/transport/chat_core.c

@ -896,6 +896,7 @@ struct ca_state {
uint64_t node_id;
struct ETCP_CONN** conns;
void** timers;
struct ca_ctx** ctxs;
void (*result_cb)(int result, uint64_t node_id, void* arg);
void* result_arg;
uint8_t pubkey[SC_PUBKEY_SIZE];
@ -903,6 +904,7 @@ struct ca_state {
static void ca_cleanup(struct ca_state* st) {
if (!st) return;
if (st->ctxs) { for (int i = 0; i < st->addr_count; i++) u_free(st->ctxs[i]); u_free(st->ctxs); }
u_free(st->conns);
u_free(st->timers);
u_free(st);
@ -911,7 +913,7 @@ static void ca_cleanup(struct ca_state* st) {
static void ca_ready_cb(struct ETCP_CONN* conn, void* arg) {
struct ca_ctx* ctx = (struct ca_ctx*)arg;
struct ca_state* st = ctx->state;
if (st->delivered || st->cancelled) { u_free(ctx); return; }
if (st->delivered || st->cancelled) return;
st->delivered = 1;
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: auto_connect SUCCESS idx=%d peer=0x%016llx",
CC_ID, ctx->addr_index, (unsigned long long)st->node_id);
@ -919,7 +921,7 @@ static void ca_ready_cb(struct ETCP_CONN* conn, void* arg) {
if (st->timers[i]) { uasync_cancel_timeout(st->inst->ua, st->timers[i]); st->timers[i] = NULL; }
if (st->conns[i] && i != ctx->addr_index) { etcp_connection_close(st->conns[i]); st->conns[i] = NULL; }
}
u_free(ctx);
etcp_conn_remove_ready_cbk(conn, ca_ready_cb, ctx);
st->result_cb(CONN_MGR_OK, st->node_id, st->result_arg);
ca_cleanup(st);
}
@ -927,7 +929,7 @@ static void ca_ready_cb(struct ETCP_CONN* conn, void* arg) {
static void ca_timeout_cb(void* arg) {
struct ca_ctx* ctx = (struct ca_ctx*)arg;
struct ca_state* st = ctx->state;
if (st->delivered || st->cancelled) { u_free(ctx); return; }
if (st->delivered || st->cancelled) return;
st->timers[ctx->addr_index] = NULL;
st->pending_count--;
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: auto_connect TIMEOUT idx=%d pending=%d/%d peer=0x%016llx",
@ -936,7 +938,6 @@ static void ca_timeout_cb(void* arg) {
st->delivered = 1;
st->result_cb(CONN_MGR_ERR_TIMEOUT, st->node_id, st->result_arg);
}
u_free(ctx);
}
void chat_core_connect_auto_cancel(void* state) {
@ -1033,7 +1034,8 @@ void chat_core_connect_auto(uint64_t node_id,
memcpy(pst->pubkey, pubkey, SC_PUBKEY_SIZE);
pst->conns = u_calloc(addr_count, sizeof(struct ETCP_CONN*));
pst->timers = u_calloc(addr_count, sizeof(void*));
if (!pst->conns || !pst->timers) { ca_cleanup(pst); cb(CONN_MGR_ERR_INTERNAL, node_id, arg); return; }
pst->ctxs = u_calloc(addr_count, sizeof(struct ca_ctx*));
if (!pst->conns || !pst->timers || !pst->ctxs) { ca_cleanup(pst); cb(CONN_MGR_ERR_INTERNAL, node_id, arg); return; }
for (int i = 0; i < addr_count; i++) {
struct sockaddr_in sin;
@ -1046,7 +1048,7 @@ void chat_core_connect_auto(uint64_t node_id,
struct ETCP_CONN* conn = etcp_connection_create(g_cc.inst, NULL);
if (!conn) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: auto_connect etcp_connection_create failed idx=%d", CC_ID, i);
pst->conns[i] = NULL; pst->timers[i] = NULL; pst->pending_count--; continue;
pst->conns[i] = NULL; pst->timers[i] = NULL; pst->ctxs[i] = NULL; pst->pending_count--; continue;
}
sc_init_ctx(&conn->crypto_ctx, &g_cc.inst->my_keys);
sc_set_peer_public_key(&conn->crypto_ctx, pubkey, 0);
@ -1056,15 +1058,16 @@ void chat_core_connect_auto(uint64_t node_id,
g_cc.inst->connections_count++;
struct ca_ctx* pctx = u_calloc(1, sizeof(struct ca_ctx));
if (!pctx) { etcp_connection_close(conn); pst->conns[i] = NULL; pst->timers[i] = NULL; pst->pending_count--; continue; }
if (!pctx) { etcp_connection_close(conn); pst->conns[i] = NULL; pst->timers[i] = NULL; pst->ctxs[i] = NULL; pst->pending_count--; continue; }
pctx->state = pst; pctx->addr_index = i;
pst->ctxs[i] = pctx;
etcp_conn_set_ready_cbk(conn, ca_ready_cb, pctx);
if (!etcp_link_new(conn, best_socket, &sa, 0)) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: auto_connect etcp_link_new failed idx=%d", CC_ID, i);
u_free(pctx); etcp_connection_close(conn);
pst->conns[i] = NULL; pst->timers[i] = NULL; pst->pending_count--; continue;
pst->conns[i] = NULL; pst->timers[i] = NULL; pst->ctxs[i] = NULL; pst->pending_count--; continue;
}
pst->conns[i] = conn;
pst->timers[i] = uasync_set_timeout(g_cc.inst->ua, CA_CONNECT_TIMEOUT_MS * 10,

Loading…
Cancel
Save