etcp - extended transmission control protocol Протокол для передачи-приёма, пободный TCP, реализованый отдельным модулем (etcp.c/h). Задача протокола: - передать пакеты через UDP (учитывая его особенности - потери, негарантированный порядок), восстанавливая порядок и потери. - пакеты уже предварительно подогнаны под размер чтобы вмещались доп. заголовки и служебные фреймы. - На приёмной стороне создаются две очереди. первая - сортированный linked-list - в нее добавляются принятые пакеты, но отсеиваются дубликаты и вставляются в нужное место. и перемещаются в выходную очередь когда все нужные пакеты дошли. при получении принятого пакета он сразу парсится, для всех hdr!=0 вызываем static upd_metric_for_transmitter(epkt*, buf*, size) - и он разгребает метрики, обновляя: - rtt_last (roud-trip delay) для последнего пакета - rtt average last 10 - rtt average last 100 - jitter как усредненное: jitter+=(abs(rtt_last_10-rtt_last)-jitter)*0.1f - для retransmission request - если timestamp последней попытки передачи этого пакета больше rtt_last_10*1.2+jitter*2 то отправляем сейчас при отправке также ограничиваем полосу пропускания: суммируем сколько байт отправлено всего (uint32_t), обновляем timestamp и расчетное число байт которое может быть отправлено на момент этого timestamp. и формируем таймер для отправки следующего пакета. вторая - ll_queue - выходная осчередь с пакетами в строгом порядке (строгий инкремент по id). struct epkt* = etcp_init() - инициализирует новый instance и выделяет под него память etcp_free(struct epkt*) etcp_rx_input(struct epkt*,uint8_t* pkt, uint16_t len) - принятый пакет на обработку rx_output - через механизм ll_queue, функция не нужна. новый пакет на передачу отправляется в очередь передачи ll_queue. используй callback для обработки очереди. для передачи сформированных пакетов по udp: etcp_set_callback(epkt*, &cbk) -> etcp_tx_output(struct epkt*,uint8_t* pkt, uint16_t len) - callback в управляющей структуре (отправка пакета в udp сокет) внутренняя структура передачи: при готовности отправить очередной пакет из очереди ll_queue пакеты перемещаются в linked_list (как отправленные но неподтвержденные), и освобождаются при получении подтверждения (ack). int etcp_tx_queue_size(epkt*) - должна быть функция которая возвращает общее кол-во пакетов на передачу в очередях (входящей и рабочей) Формат udp пакета: [ metrics] id - uint16_t циклический порядковый номер пакета (при передаче следующего пакета инкрементируется). при ретрансмиссии передается с этим же id и payload, но с обновленными остальными полями timestamp - uint16_t текущий timestamp (циклическое, 16 бит, timebase = 0.1mS) hdr - 1 байт: payload - передаваемые полезные данные metrics - опциональное поле для передачи служебных фреймов (ack, retransmission request, statistic reply) hdr: 0x00 - hdr для payload (от следующего байта до конца пакета) 0x01 - hdr для отчета о timestamp (время приёма) принятого пакета, 4 байта: - передаётся при очередной передаче пакета, для формирования статичтики на приёмной стороне. отчеты передаются для всех новых принятых пакетов с момента последней передачи. т.е. накапливаем timestamp-ы и передаём их. если пакет потерялся - не страшно. 0x10-0x2f - hdr для перезапроса пакетов (передачу каких пакетов надо повторить. значение определяет количество записей (номеров пакетов) от 1 до 32, если больше - 32 самых старых), далее по 2 байта идут ID пакетов. и в конце - 2 байта номер последнего пакета который ушел в выходную очередь (т.е. последний номер для успешно собранной цепочки) если что-то еще надо можно добавить. Если данных нет (очередь на передачу пустая) и нужно передать только метрику, то передаётся пакет с id=0 и без . на приёмной стороне он определяется по отсутствию записи с hdr=0