Формат кодограммы: ------------------ Каждая кодограмма состоит из обязательного заголовка и опциональных секций: 1. Обязательный заголовок всего пакета (2 байта) добавляется при передаче, есть во всех пакетах: [Timestamp high][Timestamp low] - Timestamp: время отправки в единицах 0.1 мс (циклическое). при переповторах время обновляется штфруется строго ВСЁ включая ВСЕ заголовки (кроме INIT+publickey). timestamp вставляется ВСЕГДА ВО ВСЕ КОДОГРАММЫ 2. Опциональные секции (одна или несколько) добавляются в etcp.c: а) Подтверждения (ACK) - заголовок 0x01: [0x01][count][(id_hi,id_lo,ts_hi,ts_lo)×count][last_delivered_hi,lo][last_rx_hi,lo] - count: количество пар ID+timestamp (1-32) - last_delivered_id: последний ID, доставленный получателю - last_rx_id: последний полученный ID (для синхронизации прогресса) б) Запросы ретрансмиссии - заголовок 0x10-0x2F: [0x10+(count-1)][(id_hi,id_lo)×count][last_delivered_hi,lo][last_rx_hi,lo] - count: (заголовок & 0x0F) + 1 (1-32) - last_delivered_id, last_rx_id: для синхронизации состояния в) channel timestamp (добавляется после выбора канала передачи): [0x0F] [RET_Timestamp high][RET_Timestamp low] [RECV_Timestamp high][RECV_Timestamp low] - RET_Timestamp: это timestamp последнего принятого пакета по этому каналу ETCP_LINK плюс разница времени между принятием этого пакета и текущим временем. т.е. приёмная сторона по этому timestamp (и зная своё время) может просчитать время в пути туда + обратно - RECV_Timestamp: это timestamp времени приёма (т.е. отправляем время "когда мы получили этот пакет по локальном урмени") - по нему другая сторона сможет просчитать относительное время задержки в одну сторону (время туда без обратно). если последний пакет по этому каналу принят сильно давно (прошло более 30000 единиц времени) то channel timestamp не добавляем. 3. Полезная нагрузка - заголовок 0x00 (одна секция и всегда последняя): [0x00] [ID high][ID low] [данные...] - Данные пакета - ID: 16-битный циклический номер пакета. Пакет может содержать несколько опциональных секций (например, ACK + данные). Установка подключения для канала (реализщуется в etcp_connections): когда etcp пытается отправить пакет через линк, то если в линке не инициализировано подключение и он клиент - то он отбрасывает этот пакет и запускает процесс установки соединения. также процесс установки соединения инициируется при добавлении канала (в etcp_link_new) если это client. процесс установки соединения: - отправляем init запрос и выставляем таймаут (сохраняем его в struct ETCP_LINK) - по таймауту повторяем init запросы, ведем счетчик запросов init. - когда получаем init подтверждение (отправляется в etcp_connections_read_callback) снимаем таймаут и выставляем флаг struct ETCP_LINK initialized=1 Кодограммы с этими секциями обрабатываются в etcp_connections (в этих кодограммах всегда только одна секция). в обязательном заголовке ID не используется, при передаче для порядка =0: г) Init запрос - заголовок 0x02 (со сбросом etcp сессии) или 0x04 (бес сброса): [0x02/0x04] [my_node_id 64bit] [my mtu high] [my mty low] [keepalive high] [keepalive low] [my publick key (64 байта, не шифруется)] - Инициирует новый connection для tcp instance. если tcp instance нет (первое подключение) - создаёт. Между нодами только одно подключение, но можно добавлять каналы. - Публичный ключ отправляется в конце пакета без шифрования, чтобы получатель мог установить его и расшифровать остальную часть пакета д) Init подтверждение - заголовок 0x03: [0x03] [my_node_id 64bit] [my mtu high] [my mty low] - Подтверждение инициализации При получении init получатель пакета должен: - reset ETCP_LINK с этим ip_port если он есть - создать новый ETCP_CONN с этим node_id. если уже существует подключение с этим node_id - вызвать etcp_reset (функция сброса окон неподтвержденных данных и нумерации) uasync select -> etcp_connection.c etcp_connections_read_callback: memory_pool_alloc, decrypt (or init) -> etcp_conn_input (сборка, дефрагментация в ETCP_CONN output_queue) ETCP_CONN output_queue ->