Skip to content

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 ​

PartSizeMeaning
LENGTH2Length of the metadata
METADATALENGTHID, status, options and extra fields, below
DATA-LENGTH2Only when the options say data follows
DATADATA-LENGTHThe payload

Metadata ​

PartSizeMeaning
ID2The sub-connection
STATUS11 New, 2 Keep, 3 End, 4 KeepAlive
OPTIONS1Bit 0: data follows. Bit 1: error (on End)
EXTRABy status, below
StatusEXTRA
NewNETWORK(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)
KeepNothing. For UDP it may be NETWORK(1) = 2, PORT(2), TYPE(1), ADDRESS (XUDP)
End, KeepAliveNothing

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

Flows ​

FormClient sendsServer sends
TCPNew (network, destination); Keep + data; EndKeep + data; End
UDPNew (network, destination) + first datagram; Keep + datagramKeep + datagram, no address
XUDPNew (UDP, first destination) + datagram; Keep (UDP, destination) + datagramKeep (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.