mubleping_rs/
lib.rs

1use std::time::{SystemTime, UNIX_EPOCH};
2use std::net::UdpSocket;
3use bincode::{Decode, Encode};
4
5#[derive(Debug,Encode,Decode)]
6#[repr(C)]
7pub struct Pong {
8    server_version: u32,
9    ident: u64,
10    connected_users: u32,
11    max_users: u32,
12    bandwidth: u32
13}
14
15
16/*
17Width 	    Data type 	Value 	Comment
184 bytes 	int 	    0 	    Denotes the request type
198 bytes 	long long 	ident 	Used to identify the reponse.
20*/
21#[derive(Debug,Encode,Decode)]
22#[repr(C)]
23pub struct Ping {
24    ping: u32,
25    identifier: u64
26}
27
28
29pub fn get_mumble_data(mumble_remote: &str) -> Pong{
30
31    // create "client" udp socket on a OS choosen port
32    let socket = UdpSocket::bind("127.0.0.1:0").expect("Failed to bind to address");
33
34    let identifier: u64 = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
35
36    let ping = Ping {
37        ping: 0,
38        identifier
39    };
40
41    let mut slice = [0u8; 12];
42
43    // struct to binary :)
44    let length = bincode::encode_into_slice(
45        ping,
46        &mut slice,
47        bincode::config::standard()
48    ).unwrap();
49
50    let slice = &slice[..length];
51
52    // time to send ping
53    socket.send_to(&slice, &mumble_remote).expect("couldn't send data");
54
55    // receive pong
56    //get request from socket
57    let mut buf = [0; 24];
58    socket.recv_from(&mut buf).expect("Failed to receive data");
59
60    /*
61        server_version: u32,
62    last_update: u64,
63    connected_users: u32,
64    max_users: u32,
65    bandwidth: u32
66     */
67
68    let (server_version, ident, connected_users, max_users, bandwidth): (u32, u64, u32, u32, u32) = bincode::decode_from_slice(&buf, bincode::config::standard().with_big_endian()).unwrap().0;
69
70    let pong = Pong {
71        server_version,
72        ident,
73        connected_users,
74        max_users,
75        bandwidth
76    };
77
78    return pong;
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    fn test_server() {
86
87        let socket = UdpSocket::bind("127.0.0.1:64738").expect("Failed to bind to address");
88
89        //get request from socket
90        let mut buf = [0; 12];
91        let (size, source) = socket.recv_from(&mut buf).expect("Failed to receive data");
92
93        let (ping, identifier): (u32, u64) = bincode::decode_from_slice(&buf, bincode::config::standard().with_big_endian()).unwrap().0;
94
95        /*
96        The response will then contain the following data:
97        Width 	    Data type 	Value 	Comment
98        4 bytes 	int 	Version 	e.g., \x0\x1\x2\x3 for 1.2.3. Can be interpreted as one single int or four signed chars.
99        8 bytes 	long long 	ident 	the ident value sent with the request
100        4 bytes 	int 	Currently connected users count
101        4 bytes 	int 	Maximum users (slot count)
102        4 bytes 	int 	Allowed bandwidth
103         */
104
105        let pong = Pong {
106            server_version: 123,
107            ident: identifier,
108            max_users: 12,
109            connected_users: 2,
110            bandwidth: 312
111        };
112
113        let mut slice = [0u8; 24];
114
115        let length = bincode::encode_into_slice(
116            &pong,
117            &mut slice,
118            bincode::config::standard().with_big_endian()
119        ).unwrap();
120
121        let slice = &slice[..length];
122
123        // send Pong
124        socket.send_to(&slice, source).expect("couldn't send data");
125    }
126
127    #[test]
128    fn it_works() {
129        let mumble_remote = "127.0.0.1:64738";
130
131        // create "server" port for test
132        thread::spawn(|| {
133            test_server();
134        });
135
136        let result = get_mumble_data(mumble_remote);
137
138        let max_users: u32 = 12;
139
140        assert_eq!(&result.max_users, &max_users);
141    }
142}