Skip to content

Commit 29ea574

Browse files
author
jrd
committed
docs/JAMULUS_PROTOCOL.md: message reference, directory flows, small fixes
1 parent 55e0d62 commit 29ea574

1 file changed

Lines changed: 105 additions & 26 deletions

File tree

docs/JAMULUS_PROTOCOL.md

Lines changed: 105 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,17 @@ GNU General Public License for more details.
4242
You should have received a copy of the GNU General Public License
4343
along with this program. If not, see [<https://www.gnu.org/licenses/>](https://www.gnu.org/licenses/).
4444

45-
# The Jamulus Audio Protocol
45+
# The Jamulus audio protocol
4646

47-
Jamulus uses connectionless UDP packets to communicate between the client and server, and additionally for directory server registration. The `src/protocol.cpp` file contains much of the details of the packets themselves, whereas this document is intended to form a higher-level view of the protocol interactions.
48-
Some of the messages need to be acknowledged, some do not. If a message ID is less than 1000, the message must be acknowledged in under `SEND_MESS_TIMEOUT_MS` ms.
47+
Jamulus uses UDP to communicate between the Client and Server, and additionally for registration with a Directory. The `src/protocol.cpp` file contains much of the details of the packets themselves, whereas this document is intended to form a higher-level view of the protocol interactions.
4948

50-
All of this information can be discovered from reading the code, but hopefully is quicker to digest when available in one location. There is a wireshark dissector available too, [here](https://github.com/softins/jamulus-wireshark), if you would like to inspect the packet flow.
49+
UDP offers no delivery guarantee and no notion of a connection, so Jamulus layers its own session and reliability semantics on top of it. A Client and Server count as *connected* once the Client is sending valid audio packets and the Server has assigned it a channel. The two message classes below are named relative to that session, not to anything at the transport level.
50+
51+
Messages with an ID below 1000 are connection-based: they apply to an established session, and each is acknowledged by an `ACKN (1)` message carrying the same sequence counter. Until that acknowledgement arrives, the sender retransmits the message every `SEND_MESS_TIMEOUT_MS` (400) ms. The protocol layer sets no retry limit: retransmission ends when the message is acknowledged, or when the channel clears the send queue via `CProtocol::Reset()` — on disconnect, on channel time-out, or when the protocol is disabled.
52+
53+
Messages with an ID from 1000 to 1999 (`CLM_*`) are connectionless: they need no established session and are never acknowledged.
54+
55+
All of this information can be discovered from reading the code, but hopefully is quicker to digest when available in one location. There is a Wireshark dissector available too, [here](https://github.com/softins/jamulus-wireshark), if you would like to inspect the packet flow.
5156

5257
---
5358

@@ -68,6 +73,10 @@ LENgth of the data precedes the data and is followed by a CRC for the packet.
6873

6974
Data is sent little-endian, i.e. not network byte-order.
7075

76+
The CRC is 16 bits, generator polynomial x¹⁶ + x¹² + x⁵ + 1 (CCITT), initial state all ones, calculated over the entire message and transmitted inverted.
77+
78+
Audio and protocol messages share one UDP port. A receiver classifies every incoming datagram by attempting to parse it as a protocol frame — zero TAG bytes, consistent length, valid CRC. Anything that fails this parse is treated as an audio packet (see `CSocket::ProcessPacket()` in `src/socket.cpp`).
79+
7180
Where a message will not fit into the maximum packet size before fragmentation, a split message container is used.
7281

7382
```
@@ -83,32 +92,91 @@ DATA is the fragment data to be re-assembled
8392

8493
This forms the data component of the packet above.
8594

86-
## Client Session with a Server
95+
## Message reference
96+
97+
Connection-based messages (acknowledged; `PROTMESSID_` prefix omitted). Full payload layouts are in the header comment of `src/protocol.cpp`.
98+
99+
| ID | Name | Purpose |
100+
|---|---|---|
101+
| 1 | `ACKN` | Acknowledges the message ID/counter it carries |
102+
| 10 | `JITT_BUF_SIZE` | Set Jitter Buffer size |
103+
| 11 | `REQ_JITT_BUF_SIZE` | Request Jitter Buffer size |
104+
| 13 | `CHANNEL_GAIN` | Set a Channel's gain in your mix |
105+
| 16 | `REQ_CONN_CLIENTS_LIST` | Request list of connected Clients |
106+
| 18 | `CHAT_TEXT` | Chat text |
107+
| 20 | `NETW_TRANSPORT_PROPS` | Audio transport properties |
108+
| 21 | `REQ_NETW_TRANSPORT_PROPS` | Request audio transport properties |
109+
| 23 | `REQ_CHANNEL_INFOS` | Request Channel info (name, instrument, …) |
110+
| 24 | `CONN_CLIENTS_LIST` | Channel info of all connected Clients |
111+
| 25 | `CHANNEL_INFOS` | Set own Channel info |
112+
| 26 | `OPUS_SUPPORTED` | OPUS codec is supported |
113+
| 27 | `LICENCE_REQUIRED` | Server requires licence agreement |
114+
| 29 | `VERSION_AND_OS` | Version and operating system |
115+
| 30 | `CHANNEL_PAN` | Set a Channel's pan in your mix |
116+
| 31 | `MUTE_STATE_CHANGED` | Your signal was (un)muted at another Client |
117+
| 32 | `CLIENT_ID` | Your Channel ID on the Server |
118+
| 33 | `RECORDER_STATE` | Jam recorder state |
119+
| 34 | `REQ_SPLIT_MESS_SUPPORT` | Request split-message support |
120+
| 35 | `SPLIT_MESS_SUPPORTED` | Split messages are supported |
121+
| 36 | `RAWAUDIO_SUPPORTED` | Raw (uncompressed) audio is supported |
122+
123+
IDs 12, 14, 15, 17, 19, 22 and 28 are legacy messages no longer sent (28, `REQ_CHANNEL_LEVEL_LIST`, is still understood for compatibility with Servers 3.4.6–3.5.12).
124+
125+
`SPECIAL_SPLIT_MESSAGE (2001)` sits outside both ID ranges because it is not a message in its own right: it is the transport container for the fragments of an oversized connection-based message (see the split message container above), with the original message ID carried inside the container. Each fragment frame has its own sequence counter and is acknowledged and retransmitted like any connection-based message.
126+
127+
Connectionless messages (never acknowledged):
128+
129+
| ID | Name | Purpose |
130+
|---|---|---|
131+
| 1001 | `CLM_PING_MS` | Ping time measurement |
132+
| 1002 | `CLM_PING_MS_WITHNUMCLIENTS` | Ping plus number of connected Clients |
133+
| 1003 | `CLM_SERVER_FULL` | Server is full |
134+
| 1004 | `CLM_REGISTER_SERVER` | Register with a Directory |
135+
| 1005 | `CLM_UNREGISTER_SERVER` | Unregister from a Directory |
136+
| 1006 | `CLM_SERVER_LIST` | Full Server list |
137+
| 1007 | `CLM_REQ_SERVER_LIST` | Request Server list |
138+
| 1008 | `CLM_SEND_EMPTY_MESSAGE` | Ask recipient to send `CLM_EMPTY_MESSAGE` to the carried address |
139+
| 1009 | `CLM_EMPTY_MESSAGE` | Empty message (NAT hole punching) |
140+
| 1010 | `CLM_DISCONNECTION` | Disconnect from Server |
141+
| 1011 | `CLM_VERSION_AND_OS` | Version and operating system |
142+
| 1012 | `CLM_REQ_VERSION_AND_OS` | Request version and operating system |
143+
| 1013 | `CLM_CONN_CLIENTS_LIST` | Connected Clients info |
144+
| 1014 | `CLM_REQ_CONN_CLIENTS_LIST` | Request connected Clients info |
145+
| 1015 | `CLM_CHANNEL_LEVEL_LIST` | Channel level list |
146+
| 1016 | `CLM_REGISTER_SERVER_RESP` | Registration result |
147+
| 1017 | `CLM_REGISTER_SERVER_EX` | Register with extended information |
148+
| 1018 | `CLM_RED_SERVER_LIST` | Reduced Server list (less UDP fragmentation) |
149+
| 1019 | `CLM_SERVER_FEATURES` | Server features |
150+
| 1020 | `CLM_REQ_SERVER_FEATURES` | Request Server features |
151+
| 1021 | `CLM_WELCOME_MESSAGE` | Server welcome message |
152+
| 1022 | `CLM_REQ_WELCOME_MESSAGE` | Request Server welcome message |
153+
154+
## Client session with a Server
87155

88156
As the protocol is connectionless, the message flow at session start up can happen out of order.
89-
When a client starts a session with a server, it sends valid audio packets to the server port, to which the server will respond with the audio mix for that client.
157+
When a Client starts a session with a Server, it sends valid audio packets to the Server port, to which the Server will respond with the audio mix for that Client.
90158

91-
The server on a new client connection will:
159+
The Server on a new Client connection will:
92160

93-
- Tell the client connection its ID, with a `CLIENT_ID (32, 0x2000)` message.
94-
- Reset the connected client list with a `CONN_CLIENTS_LIST (24, 0x1800)` message.
95-
- Determine if the client supports split messages, with a `REQ_SPLIT_MESSAGE_SUPPORT (34, 0x2200)` message.
96-
- Request the details of the audio packets from the client with a `REQ_NETW_TRANSPORT_PROPS (21, 0x1500)` message,
97-
- Request the number of jitter buffer value to use, with a `REQ_JITT_BUF_SIZE (11, 0x0B00)` message.
98-
- Request the details of the channel info, with a `REQ_CHANNELS_INFOS (23, 0x1700)` message.
99-
- Send the version and OS of the server, with a `VERSION_AND_OS (29, 0x1d00)` message.
161+
- Tell the Client connection its ID, with a `CLIENT_ID (32, 0x2000)` message.
162+
- Send the Client an empty connected Client list with a `CONN_CLIENTS_LIST (24, 0x1800)` message.
163+
- Determine if the Client supports split messages, with a `REQ_SPLIT_MESSAGE_SUPPORT (34, 0x2200)` message.
164+
- Request the details of the audio packets from the Client with a `REQ_NETW_TRANSPORT_PROPS (21, 0x1500)` message,
165+
- Request the Jitter Buffer value to use, with a `REQ_JITT_BUF_SIZE (11, 0x0B00)` message.
166+
- Request the details of the Channel info, with a `REQ_CHANNEL_INFOS (23, 0x1700)` message.
167+
- Send the version and OS of the Server, with a `VERSION_AND_OS (29, 0x1d00)` message.
100168

101169
This is defined in `CServer::OnNewConnection()`
102170

103-
The client on a new connection will:
171+
The Client on a new connection will:
104172

105-
- Send its channel info with a `CHANNELS_INFO (25, 0x1900)` message
106-
- Request the list of connected clients with a `REQ_CONN_CLIENT_LIST (16, 0x1000)` message
107-
- Set the server-side jitter buffer value with a `JITT_BUF_SIZE (10, 0x0a00)` message
173+
- Send its Channel info with a `CHANNEL_INFOS (25, 0x1900)` message
174+
- Request the list of connected Clients with a `REQ_CONN_CLIENTS_LIST (16, 0x1000)` message
175+
- Set the Server-side Jitter Buffer value with a `JITT_BUF_SIZE (10, 0x0a00)` message
108176

109177
This is defined in `CClient::OnNewConnection()`
110178

111-
At the end of the session, the client calls the `CLM_DISCONNECTION (1010, 0xf203)` message, until the server stops streaming audio to it.
179+
At the end of the session, the Client repeatedly sends a `CLM_DISCONNECTION (1010, 0xf203)` message, until the Server stops streaming audio to it.
112180

113181
A typical flow would be:
114182

@@ -156,8 +224,8 @@ A typical flow would be:
156224
ACK(RECORDER_STATE) ------------------->
157225
158226
159-
REQ_CONNECTED_CLIENTS_LIST (16, 0x1000) ---->
160-
<------------------------------------ ACK(REQ_CONNECTED_CLIENTS_LIST)
227+
REQ_CONN_CLIENTS_LIST (16, 0x1000) -------->
228+
<------------------------------------ ACK(REQ_CONN_CLIENTS_LIST)
161229
162230
REQ_CHANNEL_LEVEL_LIST (28, 0x1c00) -------->
163231
@@ -175,7 +243,7 @@ A typical flow would be:
175243
ACK(CONN_CLIENTS_LIST) ---------------->
176244
```
177245

178-
## General Streaming Messages
246+
## General streaming messages
179247

180248
During streaming, some control messages are used.
181249
Some typical messages could be:
@@ -205,18 +273,29 @@ Some typical messages could be:
205273

206274
---
207275

208-
## Audio Packet Structure
276+
## Directory registration and Server lists
277+
278+
A Directory is a Jamulus Server acting as a registry (implemented in `src/serverlist.cpp`, both roles). All Directory traffic uses connectionless messages:
279+
280+
- A Server registers with `CLM_REGISTER_SERVER_EX (1017)` (older versions: `CLM_REGISTER_SERVER (1004)`) and receives `CLM_REGISTER_SERVER_RESP (1016)` carrying the result (registered, list full, version too old, requirements not fulfilled). If no response arrives, registration is retried every 500 ms, up to 5 times.
281+
- Registration is refreshed every 15 minutes; the Directory drops a Server it has not heard from for 33 minutes. `CLM_UNREGISTER_SERVER (1005)` removes the entry immediately at shutdown or when changing Directory through the Server UI.
282+
- A Client requests the list with `CLM_REQ_SERVER_LIST (1007)`. The Directory answers with both `CLM_RED_SERVER_LIST (1018)` (a shorter form that reduces UDP fragmentation) and `CLM_SERVER_LIST (1006)` (the full information). The Client then pings each listed Server with `CLM_PING_MS_WITHNUMCLIENTS (1002)` to display latency and occupancy.
283+
- NAT hole punching: when it answers a list request, the Directory also sends every registered Server a `CLM_SEND_EMPTY_MESSAGE (1008)` carrying the Client's public address; each Server responds by sending `CLM_EMPTY_MESSAGE (1009)` to that address, in order to open its own NAT/firewall for the Client's subsequent packets. It doesn't matter whether the Client receives this message, as it will ignore it. The Directory and its registered Servers also ping each other about once a minute to keep their NAT mappings alive.
284+
285+
---
286+
287+
## Audio packet structure
209288

210289
The OPUS codec is used to compress the audio over the network and the packets are documented [here](https://datatracker.ietf.org/doc/html/rfc6716).
211290

212-
Jamulus uses a custom OPUS encoder / decoder, giving some different frame sizes, but always uses a 48kHz sample rate. OPUS and OPUS64 codecs are the only supported options currently.
291+
Jamulus uses a custom OPUS encoder / decoder, giving some different frame sizes, but always uses a 48 kHz sample rate. OPUS and OPUS64 codecs are the standard options; a Server can also accept raw (uncompressed 16-bit PCM) audio instead of OPUS-encoded audio, advertised via the `FS_RAW_AUDIO` bit in `CLM_SERVER_FEATURES` and disabled with the Server's `--noraw` option. A raw audio packet isn't tagged with a distinct message type — since the Server already learns the Client's chosen frame size via `NETW_TRANSPORT_PROPS`, it tells raw audio apart from OPUS by comparing the received packet's size against the exact byte count raw PCM would produce for that frame size and channel count.
213292

214293
The packet size will vary based on:
215294

216295
- Stereo vs mono
217296
- Buffer size (64/128/256 samples)
218297
- Use of frame sequence number (from v3.6.0 onwards)
219298

220-
These values are wrapped up into the `NETW_TRANSPORT_PROPS` messages, which the client sends to the server to tell it which values to use.
299+
These values are wrapped up into the `NETW_TRANSPORT_PROPS` messages, which the Client sends to the Server to tell it which values to use.
221300

222-
Both client and server use a jitter buffer for received audio data to prevent audio drop-out. This is configurable.
301+
Both Client and Server use a Jitter Buffer for received audio data to prevent audio drop-out. This is configurable.

0 commit comments

Comments
 (0)