# Протокол Mux.Cool

Протокол Mux.Cool - это мультиплексирующий транспортный протокол, используемый для передачи нескольких независимых потоков данных по одному установленному потоку данных.

## Версия

Текущая версия - 1 Beta.

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

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

Mux.Cool должен работать поверх установленного надежного потока данных.

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

Одно соединение Mux.Cool может передавать несколько подсоединений, каждое из которых имеет свой собственный идентификатор и состояние. Процесс передачи состоит из кадров (Frame), каждый из которых используется для передачи данных определенного подсоединения.

### Поведение клиента

Когда требуется соединение и нет доступного существующего соединения, клиент инициирует новое соединение с сервером, которое далее называется "главным соединением".

1. Одно главное соединение может использоваться для отправки нескольких подсоединений. Клиент может самостоятельно определять количество подсоединений, которое может нести главное соединение.
2. Для нового подсоединения клиент должен отправить состояние `New`, чтобы уведомить сервер о создании подсоединения, а затем использовать состояние `Keep` для передачи данных.
3. Когда подсоединение завершается, клиент отправляет состояние `End`, чтобы уведомить сервер о закрытии подсоединения.
4. Клиент может самостоятельно решать, когда закрыть главное соединение, но должен убедиться, что сервер также поддерживает соединение.
5. Клиент может использовать состояние KeepAlive, чтобы предотвратить закрытие главного соединения сервером.

### Поведение сервера

Когда сервер получает новое подсоединение, он должен обрабатывать его как обычное соединение.

1. При получении состояния `End` сервер может закрыть исходящее соединение с целевым адресом.
2. В ответе сервера для передачи данных подсоединения должен использоваться тот же идентификатор, что и в запросе.
3. Сервер не может использовать состояние `New`.
4. Сервер может использовать состояние KeepAlive, чтобы предотвратить закрытие главного соединения клиентом.

## Формат передачи

Mux.Cool использует симметричный формат передачи, то есть клиент и сервер отправляют и получают данные в одинаковом формате.

### Формат кадра

| 2 байта            | L байт     | X байт                |
| ------------------ | ---------- | --------------------- |
| Длина метаданных L | Метаданные | Дополнительные данные |

### Метаданные

Существует несколько типов метаданных. Все типы метаданных содержат поля ID и Opt, которые означают следующее:

- ID: уникальный идентификатор подсоединения
  - Для обычных подсоединений Mux ID начинается с 1 и увеличивается
  - Для [Single XUDP](https://github.com/XTLS/Xray-core/blob/main/common/xudp/xudp.go), реализованного в Xray, ID всегда равен 0
- Opt:
  - D(0x01): есть дополнительные данные

Если опция Opt(D) включена, формат дополнительных данных следующий:

| 2 байта   | X-2 байта |
| --------- | --------- |
| Длина X-2 | Данные    |

### Создание нового подсоединения (New)

| 2 байта | 1 байт | 1 байт    | 1 байт     | 2 байта | 1 байт       | A байт  | 8 байт           |
| ------- | ------ | --------- | ---------- | ------- | ------------ | ------- | ---------------- |
| ID      | 0x01   | Опция Opt | Тип сети N | Порт    | Тип адреса T | Адрес A | Global ID (XUDP) |

Где:

- Тип сети N:
  - 0x01: TCP, указывает, что трафик текущего подсоединения должен быть отправлен на целевой адрес по TCP.
  - 0x02: UDP, указывает, что трафик текущего подсоединения должен быть отправлен на целевой адрес по UDP.
- Тип адреса T:
  - 0x01: IPv4
  - 0x02: доменное имя
  - 0x03: IPv6
- Адрес A:
  - Если T = 0x01, A - это 4-байтовый адрес IPv4;
  - Если T = 0x02, A - это 1 байт длины (L) + L байт доменного имени;
  - Если T = 0x03, A - это 16-байтовый адрес IPv6;
- Global ID (XUDP):
  - Клиент вычисляет глобально уникальный идентификатор исходного кортежа UDP, который сервер использует, чтобы гарантировать, что при переподключении XUDP будет использоваться тот же порт для связи с целевым адресом.

При создании нового подсоединения, если Opt(D) включена, данные, переносимые этим кадром, должны быть отправлены на целевой хост.

### Поддержание подсоединения (Keep)

TCP

| 2 байта | 1 байт | 1 байт    |
| ------- | ------ | --------- |
| ID      | 0x02   | Опция Opt |

UDP

| 2 байта | 1 байт | 1 байт    | 1 байт     | 2 байта | 1 байт       | A байт  |
| ------- | ------ | --------- | ---------- | ------- | ------------ | ------- |
| ID      | 0x02   | Опция Opt | Тип сети N | Порт    | Тип адреса T | Адрес A |

При поддержании подсоединения, если Opt(D) включена, данные, переносимые этим кадром, должны быть отправлены на целевой хост.
XUDP добавляет адрес UDP после Opt(D) в том же формате, что и при создании нового подсоединения, но без Global ID.

### Закрытие подсоединения (End)

| 2 байта | 1 байт | 1 байт    |
| ------- | ------ | --------- |
| ID      | 0x03   | Опция Opt |

При поддержании подсоединения, если Opt(D) включена, данные, переносимые этим кадром, должны быть отправлены на целевой хост.

### Поддержание соединения (KeepAlive)

| 2 байта | 1 байт | 1 байт    |
| ------- | ------ | --------- |
| ID      | 0x04   | Опция Opt |

При поддержании соединения:

- Если Opt(D) включена, данные, переносимые этим кадром, должны быть отброшены.
- ID может быть случайным значением.

## Применение

Протокол Mux.Cool не зависит от базового протокола и теоретически может использовать любое надежное потоковое соединение для передачи данных протокола Mux.Cool.

В протоколах, ориентированных на целевой адрес, таких как Shadowsocks и VMess, при установлении соединения должен быть указан целевой адрес.
Для обеспечения совместимости протокол Mux.Cool определяет адрес "v1.mux.cool". То есть, если целевой адрес главного соединения совпадает с этим адресом, пересылка осуществляется в режиме Mux.Cool, в противном случае пересылка осуществляется традиционным способом. (Примечание: это внутренняя метка программы, VMess и VLESS не отправляют адрес "v1.mux.cool" в пакетах данных).
