Correct ETCP API callback and datagram ownership documentation

This commit is contained in:
evgeny committed 2026-10-24 00:06:00 +02:00
1 parent 74b63cc315
commit 299c613760
1 file changed
+45 -22
+45 -22
View File
@@ -8,7 +8,10 @@
Формат кодограммы (сырой пакет внутри ETCP): `<cmd 1 байт> <данные 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 (сырые, первый байт кодограммы)