# Протокол mKCP

mKCP - это потоковый транспортный протокол, основанный на [протоколе KCP](https://github.com/skywind3000/kcp), который может передавать любые потоки данных по порядку.

## Версия

Протокол mKCP не имеет номера версии, совместимость между версиями не гарантируется.

## Зависимости

### Базовый протокол

mKCP - это протокол, основанный на UDP, все коммуникации осуществляются по UDP.

### Функции

- fnv: хэш-функция [FNV-1a](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function)
  - Входные данные: строка произвольной длины;
  - Выходные данные: 32-битное беззнаковое целое число;

## Процесс коммуникации

1. mKCP разбивает поток данных на несколько пакетов для отправки. Каждый поток данных имеет уникальный идентификатор, который используется для различения разных потоков данных. Каждый пакет данных в потоке данных несет один и тот же идентификатор.
2. У mKCP нет процесса рукопожатия. При получении пакета данных определяется, является ли это новым вызовом или текущим вызовом, на основе идентификатора потока данных, который он несет.
3. Каждый пакет данных содержит несколько сегментов (Segment), которые делятся на три типа: данные (Data), подтверждение (ACK) и пульс (Ping). Каждый сегмент обрабатывается отдельно.

## Формат данных

### Пакет данных

| 4 байта                         | 2 байта        | L байт           |
| ------------------------------- | -------------- | ---------------- |
| Информация для аутентификации A | Длина данных L | Сегментная часть |

Где:

- Информация для аутентификации A = fnv(сегментная часть), big endian;
- Сегментная часть может содержать несколько сегментов;

### Сегмент данных

| 2 байта            | 1 байт      | 1 байт    | 4 байта            | 4 байта             | 4 байта                               | 2 байта   | Len байт |
| ------------------ | ----------- | --------- | ------------------ | ------------------- | ------------------------------------- | --------- | -------- |
| Идентификатор Conv | Команда Cmd | Опция Opt | Временная метка Ts | Порядковый номер Sn | Неподтвержденный порядковый номер Una | Длина Len | Данные   |

Где:

- Идентификатор Conv: идентификатор потока данных mKCP
- Команда Cmd: константа 0x01
- Опция Opt: возможные значения:
  - 0x00: пустая опция
  - 0x01: другая сторона отправила все данные
- Временная метка Ts: время отправки текущего сегмента с удаленной стороны, big endian
- Порядковый номер Sn: позиция сегмента данных в потоке данных, порядковый номер начального сегмента равен 0, каждый последующий сегмент увеличивается на 1
- Неподтвержденный порядковый номер Una: минимальный Sn, который отправляется удаленным хостом и еще не получил подтверждение

### Сегмент подтверждения

| 2 байта            | 1 байт      | 1 байт    | 4 байта  | 4 байта                                  | 4 байта            | 2 байта   | Len \* 4 байта                   |
| ------------------ | ----------- | --------- | -------- | ---------------------------------------- | ------------------ | --------- | -------------------------------- |
| Идентификатор Conv | Команда Cmd | Опция Opt | Окно Wnd | Следующий порядковый номер для приема Sn | Временная метка Ts | Длина Len | Подтвержденные порядковые номера |

Где:

- Идентификатор Conv: идентификатор потока данных mKCP
- Команда Cmd: константа 0x00
- Опция Opt: как указано выше
- Окно Wnd: максимальный порядковый номер, который может принять удаленный хост
- Следующий порядковый номер для приема Sn: минимальный порядковый номер сегмента данных, который не получил удаленный хост
- Временная метка Ts: временная метка последнего полученного сегмента данных удаленным хостом, может использоваться для расчета задержки
- Подтвержденные порядковые номера: каждые 4 байта указывают, что данные с этим порядковым номером получены и подтверждены

Комментарий:

- Удаленный хост ожидает получения данных с порядковыми номерами в диапазоне [Sn, Wnd)

### Сегмент пульса

| 2 байта            | 1 байт      | 1 байт    | 4 байта                               | 4 байта                                  | 4 байта      |
| ------------------ | ----------- | --------- | ------------------------------------- | ---------------------------------------- | ------------ |
| Идентификатор Conv | Команда Cmd | Опция Opt | Неподтвержденный порядковый номер Una | Следующий порядковый номер для приема Sn | Задержка Rto |

Где:

- Идентификатор Conv: идентификатор потока данных mKCP
- Команда Cmd: возможные значения:
  - 0x02: удаленный хост принудительно завершает сеанс
  - 0x03: обычный пульс
- Опция Opt: как указано выше
- Неподтвержденный порядковый номер Una: тот же, что и Una в сегменте данных
- Следующий порядковый номер для приема Sn: тот же, что и Sn в сегменте подтверждения
- Задержка Rto: задержка, рассчитанная самим удаленным хостом
