Return NULL when callbacks cancel ETCP connection creation

This commit is contained in:
evgeny committed 2026-10-23 22:34:46 +02:00
1 parent 2ea4fb94ab
commit a51c080407
2 files changed
+45 -6

No files matched your search

+15 -5
View File
@@ -250,12 +250,22 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* n
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] connection initialized. ETCP=%p mtu=%d, next_tx_id=%u state=pending",
etcp->log_name, etcp, etcp->mtu, etcp->next_tx_id);
// Вызываем callback для нового соединения если установлен
if (instance) {
struct etcp_inst_cbk_entry* cbe = instance->new_conn_cbks;
while (cbe) { struct etcp_inst_cbk_entry* n = cbe->next; cbe->fn(etcp, cbe->arg); cbe = n; }
/* Конструктор удерживает ресурсы до завершения уведомлений; отмена не возвращает закрытый объект. */
etcp->callbacks_running++;
struct etcp_inst_cbk_entry* cbe = instance->new_conn_cbks;
while (cbe) {
struct etcp_inst_cbk_entry* next = cbe->next;
cbe->fn(etcp, cbe->arg);
if (etcp->close_requested) break;
cbe = next;
}
if (!etcp->close_requested) etcp_fire_conn_status(etcp, ETCP_CONN_STATUS_NEW);
etcp->callbacks_running--;
if (etcp->close_requested) {
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] connection creation cancelled by callback", etcp->log_name);
etcp_connection_close(etcp);
return NULL;
}
etcp_fire_conn_status(etcp, ETCP_CONN_STATUS_NEW);
return etcp;
}
+30 -1
View File
@@ -142,6 +142,35 @@ static void ncd_late_up_case(struct UTUN_INSTANCE* inst) {
CHECK(!inst->ncd_registry && !inst->connections->count);
puts("PASS NCD late UP after timeout and subsequent reconnect");
}
struct create_close_case { unsigned created, published, deleted, status; };
static void cancel_created_connection(struct ETCP_CONN *conn, void *arg) {
struct create_close_case *test = arg;
test->created++;
etcp_connection_close(conn);
CHECK(conn->close_requested && !conn->delete_complete);
}
static void observe_created_connection(struct ETCP_CONN *conn, int status, void *arg) {
struct create_close_case *test = arg;
if (status == ETCP_CONN_STATUS_DELETE) test->deleted++;
if (status != ETCP_CONN_STATUS_NEW) return;
test->published++;
if (test->status) etcp_connection_close(conn);
}
static void constructor_close_cases(struct UTUN_INSTANCE *inst) {
for (unsigned status = 0; status < 2; status++) {
struct create_close_case test = {.status = status};
if (!status) etcp_add_new_conn_cbk(inst, cancel_created_connection, &test);
etcp_add_conn_status_cbk(inst, observe_created_connection, &test);
CHECK(etcp_connection_create(inst, "cancel creation") == NULL);
CHECK(test.deleted == 1 && test.created == !status && test.published == status);
CHECK(!inst->connections->count);
if (!status) etcp_remove_new_conn_cbk(inst, cancel_created_connection, &test);
etcp_remove_conn_status_cbk(inst, observe_created_connection, &test);
uasync_drain_immediate(inst->ua); uasync_poll(inst->ua, 0);
printf("PASS connection creation cancelled from %s callback\n", status ? "NEW status" : "new connection");
}
}
struct link_close_case { struct ETCP_LINK *neighbor; unsigned events, nested; };
static void close_neighbor(struct ETCP_CONN *conn, struct ETCP_LINK *link, int old_state, int old_status, void *arg) {
(void)conn; (void)old_state; (void)old_status;
@@ -202,7 +231,7 @@ int main(void) {
uasync_poll(inst.ua,0); CHECK(inst.connections->count == 0);
printf("PASS lifecycle scenario %d\n",scenario+1);
}
ncd_cases(&inst); ncd_late_up_case(&inst); recovery_cases(&inst); neighbor_close_case(&inst);
ncd_cases(&inst); ncd_late_up_case(&inst); recovery_cases(&inst); neighbor_close_case(&inst); constructor_close_cases(&inst);
queue_free(inst.connections); uasync_poll(inst.ua,0);
CHECK(inst.ua->timer_alloc_count == inst.ua->timer_free_count);
uasync_destroy(inst.ua,0); CHECK(u_get_allocated_count() == baseline);