Skip to main content

serenity_voice_model/
payload.rs

1//! Message bodies used in gateway event-handling.
2
3use std::net::IpAddr;
4
5use serde::{Deserialize, Serialize};
6
7use crate::id::*;
8use crate::protocol_data::ProtocolData;
9use crate::speaking_state::SpeakingState;
10use crate::util::json_safe_u64;
11
12/// Message indicating that another user has connected to the voice channel.
13///
14/// Acts as a source of UserId+SSRC identification.
15#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
16pub struct ClientConnect {
17    /// SSRC of any audio packets sent by this newly joined user.
18    pub audio_ssrc: u32,
19    /// ID of the connecting user.
20    pub user_id: UserId,
21    /// SSRC of any audio packets sent by this newly joined user.
22    ///
23    /// Bots should not see any packets with this SSRC.
24    pub video_ssrc: u32,
25}
26/// Message indicating that another user has disconnected from the voice channel.
27#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
28pub struct ClientDisconnect {
29    /// Id of the disconnected user.
30    pub user_id: UserId,
31}
32
33/// List of user IDs currently in the voice channel.
34#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
35pub struct ClientsConnect {
36    /// List of user IDs in the voice channel.
37    pub user_ids: Vec<UserId>,
38}
39
40/// Video stream information (opcode 10, unused by bots).
41#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
42pub struct Video {
43    /// SSRC for the video stream.
44    #[serde(default)]
45    pub audio_ssrc: u32,
46    /// Video SSRC.
47    #[serde(default)]
48    pub video_ssrc: u32,
49    /// User ID of the video sender.
50    #[serde(default)]
51    pub user_id: Option<UserId>,
52}
53
54/// Media sink wants update (opcode 14, unused by bots).
55#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
56pub struct MediaSinkWants {
57    /// Any value - structure unknown.
58    #[serde(default)]
59    pub any: Option<u32>,
60}
61
62/// Voice backend version (opcode 15, unused by bots).
63#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
64pub struct VoiceBackendVersion {
65    /// Voice backend version string.
66    #[serde(default)]
67    pub voice: String,
68    /// RTC worker version string.
69    #[serde(default)]
70    pub rtc_worker: String,
71}
72
73/// Channel options update (opcode 16, unused by bots).
74#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
75pub struct ChannelOptionsUpdate {
76    /// Any value - structure unknown.
77    #[serde(default)]
78    pub any: Option<u32>,
79}
80
81/// User flags in voice (muted, deafened, etc.).
82#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
83pub struct Flags {
84    /// User ID whose flags changed.
85    pub user_id: UserId,
86    /// Flags bitfield. Is None for bot users.
87    pub flags: Option<u32>,
88}
89
90/// Platform information for a user.
91#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
92pub struct Platform {
93    /// User ID.
94    pub user_id: UserId,
95    /// Platform code (0 = desktop, 1 = mobile, 2 = web, etc.). Is None for
96    /// bot users.
97    pub platform: Option<u32>,
98}
99
100/// Used to keep the websocket connection alive.
101#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
102#[serde(transparent)]
103pub struct Heartbeat {
104    /// Random number generated by the client, to be mirrored by the server.
105    pub nonce: u64,
106}
107
108/// Heartbeat ACK, received by the client to show the server's receipt of a heartbeat.
109#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
110#[serde(transparent)]
111pub struct HeartbeatAck {
112    /// Random 64-bit number previously generated by the client, mirrored by the server.
113    #[serde(with = "json_safe_u64")]
114    pub nonce: u64,
115}
116
117/// Used to determine how often the client must send a heartbeat.
118#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
119pub struct Hello {
120    /// Number of milliseconds to wait between sending heartbeat messages.
121    pub heartbeat_interval: f64,
122}
123
124/// Used to begin a voice websocket connection.
125#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
126pub struct Identify {
127    /// GuildId which the target voice channel belongs to.
128    pub server_id: GuildId,
129    /// Authentication session received from Discord's main gateway as part of a
130    /// `"VOICE_STATE_UPDATE"` message.
131    pub session_id: String,
132    /// Authentication token received from Discord's main gateway as part of a
133    /// `"VOICE_SERVER_UPDATE"` message.
134    pub token: String,
135    /// UserId of the client who is connecting.
136    pub user_id: UserId,
137    /// Maximum DAVE protocol version supported by the client.
138    ///
139    /// Signals to Discord that the bot supports end-to-end encryption.
140    /// If omitted, the client does not support DAVE.
141    #[serde(skip_serializing_if = "Option::is_none")]
142    pub max_dave_protocol_version: Option<u16>,
143}
144
145/// RTP server's connection offer and supported encryption modes.
146#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
147pub struct Ready {
148    /// IP address of the call's allocated RTP server.
149    pub ip: IpAddr,
150    /// Set of voice encryption modes offered by the server.
151    pub modes: Vec<String>,
152    /// Destination port on the call's allocated RTP server.
153    pub port: u16,
154    /// RTP synchronisation source assigned by the server to the client.
155    pub ssrc: u32,
156}
157
158/// Sent by the client after a disconnect to attempt to resume a session.
159#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
160pub struct Resume {
161    /// GuildId which the target voice channel belongs to.
162    pub server_id: GuildId,
163    /// Authentication session received from Discord's main gateway as part of a
164    /// `"VOICE_STATE_UPDATE"` message.
165    pub session_id: String,
166    /// Authentication token received from Discord's main gateway as part of a
167    /// `"VOICE_SERVER_UPDATE"` message.
168    pub token: String,
169}
170
171/// Used to select the voice protocol and encryption mechanism.
172#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
173pub struct SelectProtocol {
174    /// Client's response to encryption/connection negotiation.
175    pub data: ProtocolData,
176    /// Transport protocol.
177    ///
178    /// Currently, `"udp"` is the only known accepted value.
179    pub protocol: String,
180}
181
182/// Server's confirmation of a negotiated encryption scheme.
183#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
184pub struct SessionDescription {
185    /// The negotiated encryption mode.
186    pub mode: String,
187    /// Key used for encryption of RTP payloads using the chosen mode.
188    pub secret_key: Vec<u8>,
189    /// The DAVE protocol version used.
190    pub dave_protocol_version: u16,
191}
192
193/// Used to indicate which users are speaking, or to inform Discord that the client is now
194/// speaking.
195#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
196pub struct Speaking {
197    /// Function currently unknown.
198    ///
199    /// Docs suggest setting to `Some(0)` when sending this message as a client.
200    pub delay: Option<u32>,
201    /// How/whether a user has started/stopped speaking.
202    pub speaking: SpeakingState,
203    /// RTP synchronisation source of the speaker.
204    pub ssrc: u32,
205    /// User ID of the speaker, included in messages *received from* the server.
206    ///
207    /// Used alongside the SSRC to map individual packets to their sender.
208    pub user_id: Option<UserId>,
209}
210
211/// DAVE protocol version field in the Identify payload.
212///
213/// Signals to Discord that the bot supports end-to-end encryption
214/// and which protocol version(s) it supports.
215#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
216#[serde(transparent)]
217pub struct MaxDaveProtocolVersion(pub u16);
218
219impl MaxDaveProtocolVersion {
220    /// Protocol version 1 - Current DAVE protocol version
221    pub const V1: Self = Self(1);
222}
223
224impl Default for MaxDaveProtocolVersion {
225    fn default() -> Self {
226        Self::V1
227    }
228}
229
230/// External sender package for DAVE MLS group creation.
231///
232/// Received from the server (Opcode 25) containing the voice gateway's
233/// credential and signature public key for the MLS group's external_senders extension.
234///
235/// **Note:** This opcode uses binary WebSocket frames, not JSON.
236/// Binary format: `[opcode: u8][external_sender: Vec<u8>]`
237#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
238pub struct DaveMlsExternalSender {
239    /// Serialized ExternalSender containing signature_key and credential.
240    pub external_sender: Vec<u8>,
241}
242
243/// Key package for DAVE MLS group participation.
244///
245/// Sent to the server (Opcode 26) during the join handshake.
246/// The basic credential identity is the big-endian 64-bit user ID.
247///
248/// **Note:** This opcode uses binary WebSocket frames, not JSON.
249/// Binary format: `[opcode: u8][key_package: Vec<u8>]` (no sequence number)
250#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
251pub struct DaveMlsKeyPackage {
252    /// Serialized MLSMessage containing the KeyPackage (see RFC 9420).
253    pub key_package: Vec<u8>,
254}
255
256/// Operation type for MLS proposals.
257#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
258#[serde(rename_all = "snake_case")]
259#[repr(u8)]
260pub enum DaveMlsProposalsOperationType {
261    /// Append proposals to the pending proposal list.
262    Append = 0,
263    /// Revoke previously sent proposals by their reference.
264    Revoke = 1,
265}
266
267/// Proposals for group member changes.
268///
269/// Received from the server (Opcode 27) for add/remove operations.
270/// Contains either proposals to append or proposal refs to revoke.
271///
272/// **Note:** This opcode uses binary WebSocket frames, not JSON.
273/// Binary format: `[opcode: u8][operation_type: u8][proposals: Vec<u8>]`
274#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
275pub struct DaveMlsProposals {
276    /// The type of operation (append or revoke).
277    pub operation_type: DaveMlsProposalsOperationType,
278    /// Serialized proposal data.
279    /// For append: serialized MLSMessage proposal messages.
280    /// For revoke: serialized ProposalRef values.
281    pub proposals: Vec<u8>,
282}
283
284/// Commit with optional welcome message for group transitions.
285///
286/// Sent by the client (Opcode 28) after processing proposals.
287/// When at least one add proposal is handled, the welcome message MUST be included.
288///
289/// **Note:** This opcode uses binary WebSocket frames, not JSON.
290/// Binary format: `[opcode: u8][commit: Vec<u8>][welcome: Option<Vec<u8>>]` (no sequence number)
291#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
292pub struct DaveMlsCommitWelcome {
293    /// Serialized MLS commit message (see RFC 9420 MLSMessage and Commit definitions).
294    pub commit: Vec<u8>,
295    /// Optional MLS Welcome message for new members (see RFC 9420 Welcome definition).
296    /// Required when the commit includes one or more add proposals.
297    #[serde(skip_serializing_if = "Option::is_none")]
298    pub welcome: Option<Vec<u8>>,
299}
300
301/// Welcome message for new members joining the group.
302///
303/// Received from the server (Opcode 30) as confirmation of successful join.
304/// Includes the transition ID for the group transition.
305///
306/// **Note:** This opcode uses binary WebSocket frames, not JSON.
307/// Binary format: `[opcode: u8][transition_id: u16][welcome: Vec<u8>]`
308#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
309pub struct DaveMlsWelcome {
310    /// The transition ID for this group transition.
311    pub transition_id: u16,
312    /// Serialized MLS Welcome message (see RFC 9420 Welcome definition).
313    pub welcome: Vec<u8>,
314}
315
316/// Prepare epoch notification before group transition.
317///
318/// Received from the server (Opcode 24) to signal an upcoming epoch change.
319/// When `epoch` is 1, this indicates a new MLS group is to be created.
320#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
321pub struct DavePrepareEpoch {
322    /// The protocol version for the upcoming epoch.
323    pub protocol_version: u16,
324    /// The new epoch number after the transition.
325    pub epoch: u64,
326}
327
328/// Transition ready confirmation.
329///
330/// Sent by the client (Opcode 23) to confirm it's ready for a previously announced transition.
331/// The client sends this after processing a commit or preparing receive-side decryptors.
332#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
333pub struct DaveTransitionReady {
334    /// The transition ID the client is ready to execute.
335    pub transition_id: u16,
336    /// The protocol version for the transition.
337    pub protocol_version: u16,
338}
339
340/// Prepare protocol transition notification.
341///
342/// Received from the server (Opcode 21) to announce an upcoming protocol transition.
343#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
344pub struct DavePrepareTransition {
345    /// The protocol version for the transition.
346    pub protocol_version: u16,
347    /// The transition ID for this transition.
348    pub transition_id: u16,
349}
350
351/// Execute protocol transition notification.
352///
353/// Received from the server (Opcode 22) to execute a previously prepared transition.
354#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
355pub struct DaveExecuteTransition {
356    /// The transition ID for this transition.
357    pub transition_id: u16,
358}
359
360/// Announce commit for group transition.
361///
362/// Received from the server (Opcode 29) to broadcast an MLS commit for moving to the next epoch.
363/// The commit is one received from a group member via dave_mls_commit_welcome (Opcode 28).
364///
365/// **Note:** This opcode uses binary WebSocket frames, not JSON.
366/// Binary format: `[opcode: u8][transition_id: u16][commit_message: Vec<u8>]`
367#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
368pub struct DaveMlsAnnounceCommitTransition {
369    /// The transition ID for this group epoch change.
370    pub transition_id: u16,
371    /// Serialized MLS commit message (see RFC 9420 MLSMessage and Commit definitions).
372    pub commit_message: Vec<u8>,
373}
374
375/// Invalid commit or welcome report.
376///
377/// Sent to the server (Opcode 31) to report an invalid commit or welcome message.
378/// This asks the voice gateway to remove and re-add the member to recover.
379#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
380pub struct DaveMlsInvalidCommitWelcome {
381    /// The transition ID in which the invalid Commit or Welcome was received.
382    pub transition_id: u16,
383}