---
url: /apranik/concepts/mux-cool.md
---
# Mux.Cool on the wire

Mux.Cool carries many sub-connections over one established stream, the main connection. It is implemented in `shared/muxcool`. All numbers are big endian.

## Frame

| Part | Size | Meaning |
| --- | --- | --- |
| LENGTH | 2 | Length of the metadata |
| METADATA | LENGTH | ID, status, options and extra fields, below |
| DATA-LENGTH | 2 | Only when the options say data follows |
| DATA | DATA-LENGTH | The payload |

## Metadata

| Part | Size | Meaning |
| --- | --- | --- |
| ID | 2 | The sub-connection |
| STATUS | 1 | 1 New, 2 Keep, 3 End, 4 KeepAlive |
| OPTIONS | 1 | Bit 0: data follows. Bit 1: error (on End) |
| EXTRA | | By status, below |

| Status | EXTRA |
| --- | --- |
| New | NETWORK(1: 1 TCP, 2 UDP), PORT(2), TYPE(1: 1 IPv4, 2 domain, 3 IPv6), ADDRESS. A UDP New with data may add GLOBAL ID(8) (XUDP) |
| Keep | Nothing. For UDP it may be NETWORK(1) = 2, PORT(2), TYPE(1), ADDRESS (XUDP) |
| End, KeepAlive | Nothing |

A domain ADDRESS is a length byte and then the name. The port-first layout is VMess's; SOCKS5 and Trojan use another.

## Flows

| Form | Client sends | Server sends |
| --- | --- | --- |
| TCP | New (network, destination); Keep + data; End | Keep + data; End |
| UDP | New (network, destination) + first datagram; Keep + datagram | Keep + datagram, no address |
| XUDP | New (UDP, first destination) + datagram; Keep (UDP, destination) + datagram | Keep (UDP, source) + datagram, once the client has named an address |

VLESS enters Mux.Cool with command 3, and Apranik uses it for XUDP only. A server never sends New. A refused New is answered with an End carrying the error bit, and the main connection stays. A New for
an ID that is open closes the main connection.
