mumble_server_runtime_protocol/
messages.rs

1//! Protobuf message types for the Mumble protocol, generated at build time from
2//! the vendored `.proto` (see `build.rs`); never hand-transcribed (R1).
3//!
4//! REF: references/vendored/Mumble.proto (package MumbleProto) — TCP control messages.
5//! REF: references/vendored/MumbleUDP.proto (package MumbleUDP) — UDP audio/ping envelope.
6//!
7//! Note the `UDPTunnel` message defined in Mumble.proto is "Not used" on the wire:
8//! a TCP frame of type `UdpTunnel` carries raw audio bytes, not this message. That
9//! special case lives in the UDP envelope handling, not here.
10
11/// TCP control-channel messages (proto2, `package MumbleProto`).
12pub mod tcp {
13    include!(concat!(env!("OUT_DIR"), "/mumble_proto.rs"));
14}
15
16/// UDP voice-plane messages (proto3, `package MumbleUDP`).
17pub mod udp {
18    include!(concat!(env!("OUT_DIR"), "/mumble_udp.rs"));
19}
20
21#[cfg(test)]
22mod tests {
23    // See framing.rs for why the test module allows expect_used under -D warnings.
24    #![allow(clippy::expect_used)]
25
26    use super::*;
27    use prost::Message;
28
29    #[test]
30    fn tcp_version_roundtrips() {
31        let original = tcp::Version {
32            version_v1: Some(0x0001_0500),
33            version_v2: Some(0x0000_0001_0005_0000),
34            release: Some("mumble-server-runtime-test".to_string()),
35            os: Some("linux".to_string()),
36            os_version: Some("6.1".to_string()),
37        };
38        let bytes = original.encode_to_vec();
39        let decoded = tcp::Version::decode(&bytes[..]).expect("decode Version");
40        assert_eq!(decoded, original);
41    }
42
43    #[test]
44    fn tcp_empty_message_roundtrips() {
45        // An all-unset proto2 message must survive an encode/decode cycle.
46        let original = tcp::Version::default();
47        let bytes = original.encode_to_vec();
48        let decoded = tcp::Version::decode(&bytes[..]).expect("decode empty Version");
49        assert_eq!(decoded, original);
50        assert!(bytes.is_empty());
51    }
52
53    #[test]
54    fn udp_audio_roundtrips_with_oneof_header() {
55        let original = udp::Audio {
56            header: Some(udp::audio::Header::Target(31)),
57            sender_session: 42,
58            frame_number: 7,
59            opus_data: vec![1, 2, 3, 4],
60            positional_data: vec![1.0, 2.0, 3.0],
61            volume_adjustment: 0.5,
62            is_terminator: true,
63        };
64        let bytes = original.encode_to_vec();
65        let decoded = udp::Audio::decode(&bytes[..]).expect("decode Audio");
66        assert_eq!(decoded, original);
67    }
68
69    #[test]
70    fn udp_audio_context_variant_roundtrips() {
71        // The other arm of the oneof must be preserved too.
72        let original = udp::Audio {
73            header: Some(udp::audio::Header::Context(2)),
74            sender_session: 1,
75            frame_number: 0,
76            opus_data: vec![],
77            positional_data: vec![],
78            volume_adjustment: 0.0,
79            is_terminator: false,
80        };
81        let bytes = original.encode_to_vec();
82        let decoded = udp::Audio::decode(&bytes[..]).expect("decode Audio");
83        assert_eq!(decoded, original);
84        assert_eq!(decoded.header, Some(udp::audio::Header::Context(2)));
85    }
86
87    #[test]
88    fn udp_ping_roundtrips() {
89        let original = udp::Ping {
90            timestamp: 123_456_789,
91            request_extended_information: true,
92            server_version_v2: 0x0000_0001_0005_0000,
93            user_count: 3,
94            max_user_count: 100,
95            max_bandwidth_per_user: 128_000,
96        };
97        let bytes = original.encode_to_vec();
98        let decoded = udp::Ping::decode(&bytes[..]).expect("decode Ping");
99        assert_eq!(decoded, original);
100    }
101}