1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use std::net::{Ipv4Addr, SocketAddr, UdpSocket};
use std::str;
mod parser;

pub struct ResponseHeaders {
    pub server: String,
    pub location: String,
}

fn create_socket(add: &str) -> UdpSocket {
    match UdpSocket::bind(add) {
        Ok(s) => return s,
        Err(e) => panic!("couldn't bind socket: {}", e)
    };
}

pub struct SimpleServiceDiscoveryClient {
    socket: UdpSocket,
}

pub const SSDP_SEARCH_PAYLOAD: &'static str = "\
            M-SEARCH * HTTP/1.1\n\
            Host: 239.255.255.250:1900\n\
            Man: \"ssdp:discover\"\n\
            ST: ssdp:all\n\
            MX: 5";

impl SimpleServiceDiscoveryClient {

    fn broadcast_search(&self) {

        match self.socket.send_to(SSDP_SEARCH_PAYLOAD.as_bytes(), SocketAddr::from(([239, 255, 255, 250], 1900))) {
            Ok(_) => {
//                println!("sent: {}", count)
            }

            Err(error) => {
                println!("woops {}", error)
            }
        }
    }

    fn join_multicast_v4(&self, multiaddr: &Ipv4Addr) {
        self.socket.join_multicast_v4(multiaddr, &Ipv4Addr::new(0, 0, 0, 0)).expect("to join multicast");
    }


    fn listen(&self, mut f: impl FnMut(&ResponseHeaders)) {

        let mut buf = [0; 9000];
        loop {
            match self.socket.recv_from(&mut buf) {
                Ok((_smt, _src)) => {
                    let body = str::from_utf8(&buf).unwrap_or("").trim();

                    let lines = body.split("\r\n");
                    let mut server= String::new();
                    let mut location= String::new();
                    for line in lines {
                        match parser::extract(line, "Server: ") {
                            Some(result) => {
                                server = result
                            }
                            None => {}
                        }
                        match parser::extract(line, "Location: ") {
                            Some(result) => {
                                location = result
                            }
                            None => {}
                        }
                    }
                    let response_headers = ResponseHeaders {server, location };
                    f(&response_headers);

                },
                Err(e) => {
                    println!("couldn't recieve a datagram: {}", e);
                }
            }
        }
    }
}

pub fn create_client() -> SimpleServiceDiscoveryClient {
    let client = SimpleServiceDiscoveryClient {
        socket: create_socket("0.0.0.0:1900")
    };
    return client;
}

pub fn listen(f: impl FnMut(&ResponseHeaders)) {
    let client = create_client();
    client.broadcast_search();
    client.join_multicast_v4(&Ipv4Addr::new(239, 255, 255, 250));
    client.listen(f);
}