diff --git a/src/transport_layer/etcp_api_doc.md b/src/transport_layer/etcp_api_doc.md index bbc9dabe..2b20368f 100644 --- a/src/transport_layer/etcp_api_doc.md +++ b/src/transport_layer/etcp_api_doc.md @@ -8,7 +8,10 @@ Формат кодограммы (сырой пакет внутри ETCP): ` <данные N байт>`. -Модуль **тонкий**: отправка — просто `queue_data_put` в очередь normalizer'а, приём — выбор обработчика по ID из массива `ETCP_BINDINGS`. +Все вызовы выполняются в uasync-потоке instance. Для отправки нужен UP-транспорт и свободная +`send_input_q`; владелец прямого соединения удерживает NCD handle. Принятие кодограммы +в очередь и транспортный ACK не подтверждают завершение операции сервиса: REINIT +отбрасывает прежний поток, и сервис завершает или повторяет свои операции. ## 2. Как пользоваться @@ -31,28 +34,48 @@ void my_data_recv_callback(struct ETCP_CONN* conn, struct ll_entry* entry) { ### Отправка пакета ```c -struct ll_entry* e = queue_entry_new_from_pool(inst->data_pool); -memcpy(e->dgram, &my_cmd, 1); +struct ll_entry* e = ll_alloc_lldgram(1 + payload_len); +if (!e) { + DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Cannot allocate service datagram"); + return -1; +} +e->dgram[0] = my_cmd; memcpy(e->dgram + 1, payload, payload_len); e->len = 1 + payload_len; -etcp_send(conn, e); // ownership entry передаётся +if (etcp_send(conn, e) < 0) { + queue_dgram_free(e); queue_entry_free(e); + return -1; +} +// При успехе e уже может быть обработан и освобождён синхронно: больше его не читаем. ``` +`ll_alloc_lldgram` выделяет и entry, и dgram. При ошибке `etcp_send` оба блока +остаются вызывающему; при успехе владение передаётся normalizer. + ### Коллбэки состояния соединения ```c -// Срабатывает после INIT-handshake, можно слать данные -etcp_conn_set_ready_cbk(conn, on_conn_ready, my_data); +void on_conn_event(struct ETCP_CONN* conn, int event, void* arg); +void on_new_conn(struct ETCP_CONN* conn, void* arg); -// Срабатывает при поднятии/падении соединения -etcp_conn_set_up_cbk(conn, on_conn_up, my_data); -etcp_conn_set_down_cbk(conn, on_conn_down, my_data); +etcp_conn_add_cbk(conn, on_conn_event, my_data, + ETCP_CBK_EVENT_INIT | ETCP_CBK_EVENT_UP | ETCP_CBK_EVENT_DOWN | + ETCP_CBK_EVENT_REINIT | ETCP_CBK_EVENT_DELETE); +etcp_add_new_conn_cbk(instance, on_new_conn, my_data); -// На уровне instance — при создании нового входящего соединения -etcp_set_new_conn_cbk(instance, on_new_conn, my_data); +// Снять именно свою подписку; fn и arg идентифицируют запись. +etcp_conn_remove_cbk(conn, on_conn_event, my_data); +etcp_remove_new_conn_cbk(instance, on_new_conn, my_data); ``` -**Важно:** коллбэки `set_*` заменяют всю цепочку одним обработчиком; `add_*`/`remove_*` добавляют/убирают обработчик в связном списке из нескольких коллбэков. +`INIT` означает первую готовность потока, `UP/DOWN` — доступность транспорта, +`REINIT` — подтверждённую новую сессию. `DELETE` — терминальное событие, единственное +допустимое при `state==2`. Callback может закрыть соединение или снять подписку; +новые подписки не участвуют в уже начатом обходе. + +Instance callback создания вызывается для входящих и исходящих объектов, ещё до +handshake: peer_node_id может быть неизвестен. Он не означает UP. Для общей +диагностики доступны `etcp_add_conn_status_cbk` и `etcp_add_link_status_cbk`. ### Сервисные ID @@ -82,8 +105,10 @@ etcp_set_new_conn_cbk(instance, on_new_conn, my_data); | Тип | Сигнатура | Назначение | |-----|-----------|-----------| | `etcp_recv_fn` | `void(conn, entry)` | Приём пакета — **обязан** освободить entry/dgram | -| `etcp_cbk_fn` | `void(conn, arg)` | События ready/up/down/new_conn | -| `etcp_connect_callback_t` | `void(arg, conn, type)` | Результат фонового подключения | +| `etcp_cbk_fn` | `void(conn, event, arg)` | События соединения по маске `ETCP_CBK_EVENT_*` | +| `etcp_inst_cbk_fn` | `void(conn, arg)` | Создание объекта соединения | +| `etcp_conn_status_fn` | `void(conn, status, arg)` | Статусы `ETCP_CONN_STATUS_*` на instance | +| `etcp_link_status_cbk_fn` | `void(conn, link, old_state, old_status, arg)` | Изменения физического линка | ### Функции @@ -91,16 +116,14 @@ etcp_set_new_conn_cbk(instance, on_new_conn, my_data); |---------|-----------| | `etcp_bind(inst, id, fn)` | Подписаться на пакеты с cmd=`id` | | `etcp_unbind(inst, id)` | Отписаться | -| `etcp_send(conn, entry)` | Отправить пакет (забирает ownership entry) | +| `etcp_send(conn, entry)` | Отправить пакет; владение entry/dgram передаётся только при результате 0 | | `etcp_int_recv(queue, arg)` | **Внутренняя:** диспетчер из очереди normalizer'а, вызывает bound-коллбэк по cmd | -| `etcp_conn_set_ready_cbk(conn, fn, arg)` | Установить одиночный коллбэк готовности (заменяет существующие) | -| `etcp_conn_set_up_cbk(conn, fn, arg)` | Установить коллбэк поднятия соединения | -| `etcp_conn_set_down_cbk(conn, fn, arg)` | Установить коллбэк падения соединения | -| `etcp_conn_add_ready_cbk/remove_ready_cbk` | Добавить/убрать из цепочки ready-коллбэков | -| `etcp_conn_add_up_cbk/remove_up_cbk` | Аналогично для up | -| `etcp_conn_add_down_cbk/remove_down_cbk` | Аналогично для down | -| `etcp_set_new_conn_cbk(inst, fn, arg)` | Установить коллбэк на входящее соединение | +| `etcp_conn_add_cbk(conn, fn, arg, mask)` | Подписка на выбранные события соединения | +| `etcp_conn_remove_cbk(conn, fn, arg)` | Снять свою подписку | +| `etcp_conn_update_cbk_mask(conn, fn, arg, mask)` | Изменить маску существующей подписки | | `etcp_add_new_conn_cbk/remove_new_conn_cbk` | Добавить/убрать из цепочки new_conn | +| `etcp_add_conn_status_cbk/remove_conn_status_cbk` | Добавить/снять instance-подписку на статусы соединений | +| `etcp_add_link_status_cbk/remove_link_status_cbk` | Добавить/снять instance-подписку на состояния линков | ### Командные ID (сырые, первый байт кодограммы)