Skip to main content

rtc_ice/agent/
agent_proto.rs

1use super::*;
2use mdns::{MDNS_PORT, MdnsEvent};
3
4impl sansio::Protocol<TaggedBytesMut, (), ()> for Agent {
5    type Rout = TaggedBytesMut;
6    type Wout = TaggedBytesMut;
7    type Eout = TaggedEvent;
8    type Error = Error;
9    type Time = Instant;
10
11    fn handle_read(&mut self, msg: TaggedBytesMut) -> Result<()> {
12        // demuxing mDNS packet from STUN packet whether peer addr port is MDNS_PORT
13        if msg.transport.peer_addr.port() == MDNS_PORT {
14            let remote_candidates = if let Some(mdns_conn) = &mut self.mdns {
15                mdns_conn.handle_read(msg)?;
16
17                let mut remote_candidates = vec![];
18                // After mdns handle_read, check any query result
19                while let Some(event) = mdns_conn.poll_event() {
20                    match event {
21                        MdnsEvent::QueryAnswered(id, addr) => {
22                            if let Some(mut c) = self.mdns_queries.remove(&id)
23                                && c.set_ip(&addr).is_ok()
24                            {
25                                debug!(
26                                    "mDNS query id {} answered Candidate {} with resolved_addr {} is added into remote candidates",
27                                    id,
28                                    c,
29                                    c.addr()
30                                );
31                                remote_candidates.push(c);
32                            }
33                        }
34                        MdnsEvent::QueryTimeout(id) => {
35                            if let Some(c) = self.mdns_queries.remove(&id) {
36                                error!("mDNS Query {} timed out for {}", id, c.address());
37                            }
38                        }
39                        _ => {}
40                    }
41                }
42                remote_candidates
43            } else {
44                vec![]
45            };
46
47            self.trigger_request_connectivity_check(remote_candidates);
48
49            Ok(())
50        } else if let Some(local_index) =
51            self.find_local_candidate(msg.transport.local_addr, msg.transport.transport_protocol)
52        {
53            self.handle_inbound_candidate_msg(local_index, msg)
54        } else {
55            warn!(
56                "[{}]: Discarded message, not a valid local candidate from {:?}:{}",
57                self.get_name(),
58                msg.transport.transport_protocol,
59                msg.transport.local_addr,
60            );
61            Err(Error::ErrUnhandledStunpacket)
62        }
63    }
64
65    fn poll_read(&mut self) -> Option<Self::Rout> {
66        None
67    }
68
69    fn handle_write(&mut self, _msg: ()) -> std::result::Result<(), Self::Error> {
70        Ok(())
71    }
72
73    fn poll_write(&mut self) -> Option<Self::Wout> {
74        if let Some(mdns_conn) = &mut self.mdns {
75            while let Some(msg) = mdns_conn.poll_write() {
76                self.write_outs.push_back(msg);
77            }
78        }
79
80        self.write_outs.pop_front()
81    }
82
83    fn handle_event(&mut self, _evt: ()) -> std::result::Result<(), Self::Error> {
84        Ok(())
85    }
86
87    fn poll_event(&mut self) -> Option<Self::Eout> {
88        self.event_outs.pop_front()
89    }
90
91    fn handle_timeout(&mut self, now: Self::Time) -> std::result::Result<(), Self::Error> {
92        let remote_candidates = if let Some(mdns_conn) = &mut self.mdns {
93            let _ = mdns_conn.handle_timeout(now);
94
95            let mut remote_candidates = vec![];
96            // After mdns handle_timeout, check any query result
97            while let Some(event) = mdns_conn.poll_event() {
98                match event {
99                    MdnsEvent::QueryAnswered(id, addr) => {
100                        if let Some(mut c) = self.mdns_queries.remove(&id)
101                            && c.set_ip(&addr).is_ok()
102                        {
103                            debug!(
104                                "mDNS query id {} answered Candidate {} with resolved_addr {} is added into remote candidates",
105                                id,
106                                c,
107                                c.addr()
108                            );
109                            remote_candidates.push(c);
110                        }
111                    }
112                    MdnsEvent::QueryTimeout(id) => {
113                        if let Some(c) = self.mdns_queries.remove(&id) {
114                            error!("mDNS Query {} timed out for {}", id, c.address());
115                        }
116                    }
117                    _ => {}
118                }
119            }
120            remote_candidates
121        } else {
122            vec![]
123        };
124        self.trigger_request_connectivity_check(remote_candidates);
125
126        if self.ufrag_pwd.remote_credentials.is_some()
127            && (self.force_candidate_contact
128                || self.last_checking_time + self.get_timeout_interval() <= now)
129        {
130            self.contact(now);
131        }
132        Ok(())
133    }
134
135    fn poll_timeout(&mut self) -> Option<Self::Time> {
136        let mdns_timeout = if let Some(mdns_conn) = &mut self.mdns {
137            mdns_conn.poll_timeout()
138        } else {
139            None
140        };
141
142        let ice_timeout = if self.ufrag_pwd.remote_credentials.is_some()
143            && !matches!(
144                self.connection_state,
145                ConnectionState::Failed | ConnectionState::Closed
146            ) {
147            if self.force_candidate_contact {
148                // A connectivity check was requested; ask the driver to call
149                // `handle_timeout` as soon as possible. `last_checking_time` is in the
150                // past, so the resulting deadline is immediate.
151                Some(self.last_checking_time)
152            } else {
153                Some(self.last_checking_time + self.get_timeout_interval())
154            }
155        } else {
156            None
157        };
158
159        // This treats the two options as a collection and picks the minimum
160        [mdns_timeout, ice_timeout].into_iter().flatten().min()
161    }
162
163    fn close(&mut self) -> std::result::Result<(), Self::Error> {
164        self.set_selected_pair(None, None);
165        self.delete_all_candidates(false);
166        self.update_connection_state(None, ConnectionState::Closed);
167        if let Some(mdns_conn) = &mut self.mdns {
168            mdns_conn.close()?;
169        }
170        Ok(())
171    }
172}