Return NULL when callbacks cancel ETCP connection creation
This commit is contained in:
1 parent
2ea4fb94ab
commit
a51c080407
2 files changed
+45
-6
No files matched your search
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user