simple_ssdp_client/
mod.rs

1use std::net::{Ipv4Addr, SocketAddr, UdpSocket};
2use std::str;
3mod parser;
4
5pub struct ResponseHeaders {
6    pub server: String,
7    pub location: String,
8}
9
10fn create_socket(add: &str) -> UdpSocket {
11    match UdpSocket::bind(add) {
12        Ok(s) => return s,
13        Err(e) => panic!("couldn't bind socket: {}", e)
14    };
15}
16
17pub struct SimpleServiceDiscoveryClient {
18    socket: UdpSocket,
19}
20
21pub const SSDP_SEARCH_PAYLOAD: &'static str = "\
22            M-SEARCH * HTTP/1.1\n\
23            Host: 239.255.255.250:1900\n\
24            Man: \"ssdp:discover\"\n\
25            ST: ssdp:all\n\
26            MX: 5";
27
28impl SimpleServiceDiscoveryClient {
29
30    fn broadcast_search(&self) {
31
32        match self.socket.send_to(SSDP_SEARCH_PAYLOAD.as_bytes(), SocketAddr::from(([239, 255, 255, 250], 1900))) {
33            Ok(_) => {
34//                println!("sent: {}", count)
35            }
36
37            Err(error) => {
38                println!("woops {}", error)
39            }
40        }
41    }
42
43    fn join_multicast_v4(&self, multiaddr: &Ipv4Addr) {
44        self.socket.join_multicast_v4(multiaddr, &Ipv4Addr::new(0, 0, 0, 0)).expect("to join multicast");
45    }
46
47
48    fn listen(&self, mut f: impl FnMut(&ResponseHeaders)) {
49
50        let mut buf = [0; 9000];
51        loop {
52            match self.socket.recv_from(&mut buf) {
53                Ok((_smt, _src)) => {
54                    let body = str::from_utf8(&buf).unwrap_or("").trim();
55
56                    let lines = body.split("\r\n");
57                    let mut server= String::new();
58                    let mut location= String::new();
59                    for line in lines {
60                        match parser::extract(line, "Server: ") {
61                            Some(result) => {
62                                server = result
63                            }
64                            None => {}
65                        }
66                        match parser::extract(line, "Location: ") {
67                            Some(result) => {
68                                location = result
69                            }
70                            None => {}
71                        }
72                    }
73                    let response_headers = ResponseHeaders {server, location };
74                    f(&response_headers);
75
76                },
77                Err(e) => {
78                    println!("couldn't recieve a datagram: {}", e);
79                }
80            }
81        }
82    }
83}
84
85pub fn create_client() -> SimpleServiceDiscoveryClient {
86    let client = SimpleServiceDiscoveryClient {
87        socket: create_socket("0.0.0.0:1900")
88    };
89    return client;
90}
91
92pub fn listen(f: impl FnMut(&ResponseHeaders)) {
93    let client = create_client();
94    client.broadcast_search();
95    client.join_multicast_v4(&Ipv4Addr::new(239, 255, 255, 250));
96    client.listen(f);
97}