Skip to main content

rtc_turn/client/
relay.rs

1use log::{debug, warn};
2use std::collections::HashMap;
3use std::net::SocketAddr;
4use std::ops::Add;
5use std::time::{Duration, Instant};
6
7use stun::attributes::*;
8use stun::error_code::*;
9use stun::fingerprint::*;
10use stun::integrity::*;
11use stun::message::*;
12use stun::textattrs::*;
13
14use super::permission::*;
15use super::transaction::*;
16use crate::proto;
17
18use crate::client::binding::BindingState;
19use crate::client::{Client, Event, RelayedAddr};
20use shared::error::{Error, Result};
21
22const PERM_REFRESH_INTERVAL: Duration = Duration::from_secs(120);
23// https://datatracker.ietf.org/doc/html/rfc8656#name-permissions-2
24// The Permission Lifetime MUST be 300 seconds (= 5 minutes).
25const PERM_LIFETIME: Duration = Duration::from_secs(300);
26const MAX_RETRY_ATTEMPTS: u16 = 3;
27
28// RelayState is a set of params use by Relay
29pub(crate) struct RelayState {
30    pub(crate) relayed_addr: RelayedAddr,
31    pub(crate) integrity: MessageIntegrity,
32    pub(crate) nonce: Nonce,
33    pub(crate) lifetime: Duration,
34    perm_map: HashMap<SocketAddr, Permission>,
35    refresh_alloc_timer: Instant,
36    refresh_perms_timer: Instant,
37}
38
39impl RelayState {
40    pub(super) fn new(
41        relayed_addr: RelayedAddr,
42        integrity: MessageIntegrity,
43        nonce: Nonce,
44        lifetime: Duration,
45    ) -> Self {
46        debug!("initial lifetime: {} seconds", lifetime.as_secs());
47
48        Self {
49            relayed_addr,
50            integrity,
51            nonce,
52            lifetime,
53            perm_map: HashMap::new(),
54            refresh_alloc_timer: Instant::now().add(lifetime / 2),
55            refresh_perms_timer: Instant::now().add(PERM_REFRESH_INTERVAL),
56        }
57    }
58
59    pub(super) fn set_nonce_from_msg(&mut self, msg: &Message) {
60        // Update nonce
61        match Nonce::get_from_as(msg, ATTR_NONCE) {
62            Ok(nonce) => {
63                self.nonce = nonce;
64                debug!("refresh allocation: 438, got new nonce.");
65            }
66            Err(_) => warn!("refresh allocation: 438 but no nonce."),
67        }
68    }
69}
70
71/// A borrowed handle to one live allocation on the TURN server.
72///
73/// Obtained from [`Client::relay`](crate::client::Client::relay). Sending to a peer requires
74/// a permission for it first — see [`Self::create_permission`].
75pub struct Relay<'a> {
76    pub(crate) relayed_addr: RelayedAddr,
77    pub(crate) client: &'a mut Client,
78}
79
80impl Relay<'_> {
81    /// Asks the server to permit traffic to and from `peer_addr`.
82    ///
83    /// The relay silently drops data for peers with no permission, and permissions expire after
84    /// five minutes unless refreshed. Returns the transaction id to match against the resulting
85    /// [`Event`], or `None` if a permission is already in place.
86    ///
87    /// # Errors
88    ///
89    /// Fails if the allocation no longer exists or the request cannot be encoded.
90    pub fn create_permission(&mut self, peer_addr: SocketAddr) -> Result<Option<TransactionId>> {
91        if let Some(relay) = self.client.relays.get_mut(&self.relayed_addr) {
92            relay
93                .perm_map
94                .entry(peer_addr)
95                .or_insert_with(Permission::default);
96            if let Some(perm) = relay.perm_map.get(&peer_addr)
97                && perm.state() == PermState::Idle
98            {
99                return Ok(Some(
100                    self.create_permissions(&[peer_addr], Some(peer_addr))?,
101                ));
102            }
103            Ok(None)
104        } else {
105            Err(Error::ErrConnClosed)
106        }
107    }
108
109    pub(crate) fn poll_timeout(&self) -> Option<Instant> {
110        if let Some(relay) = self.client.relays.get(&self.relayed_addr) {
111            if relay.refresh_alloc_timer < relay.refresh_perms_timer {
112                Some(relay.refresh_alloc_timer)
113            } else {
114                Some(relay.refresh_perms_timer)
115            }
116        } else {
117            None
118        }
119    }
120
121    pub(crate) fn handle_timeout(&mut self, now: Instant) {
122        let (refresh_alloc_timer, refresh_perms_timer) = if let Some(relay) =
123            self.client.relays.get_mut(&self.relayed_addr)
124        {
125            let refresh_alloc_timer = if relay.refresh_alloc_timer <= now {
126                relay.refresh_alloc_timer = relay.refresh_alloc_timer.add(relay.lifetime / 2);
127                Some(relay.lifetime)
128            } else {
129                None
130            };
131
132            let refresh_perms_timer = if relay.refresh_perms_timer <= now {
133                relay.refresh_perms_timer = relay.refresh_perms_timer.add(PERM_REFRESH_INTERVAL);
134                true
135            } else {
136                false
137            };
138
139            (refresh_alloc_timer, refresh_perms_timer)
140        } else {
141            (None, false)
142        };
143
144        if let Some(lifetime) = refresh_alloc_timer {
145            let _ = self.refresh_allocation(lifetime);
146        }
147        if refresh_perms_timer {
148            let _ = self.refresh_permissions();
149        }
150    }
151
152    /// Sends `p` to `peer_addr` through the relay.
153    ///
154    /// Uses ChannelData framing if a channel is bound for that peer, otherwise a Data indication.
155    ///
156    /// # Errors
157    ///
158    /// Fails if the allocation is gone, or if no permission exists for `peer_addr`.
159    pub fn send_to(&mut self, p: &[u8], peer_addr: SocketAddr) -> Result<()> {
160        // check if we have a permission for the destination IP addr
161        let result = if let Some(relay) = self.client.relays.get_mut(&self.relayed_addr) {
162            if let Some(perm) = relay.perm_map.get_mut(&peer_addr) {
163                if perm.state() != PermState::Permitted {
164                    Err(Error::ErrNoPermission)
165                } else {
166                    Ok((relay.integrity.clone(), relay.nonce.clone()))
167                }
168            } else {
169                Err(Error::ErrNoPermission)
170            }
171        } else {
172            Err(Error::ErrConnClosed)
173        };
174
175        let (integrity, nonce) = result?;
176
177        self.send(p, peer_addr, integrity, nonce)
178    }
179
180    fn send(
181        &mut self,
182        p: &[u8],
183        peer_addr: SocketAddr,
184        integrity: MessageIntegrity,
185        nonce: Nonce,
186    ) -> Result<()> {
187        let channel_number = {
188            let (bind_st, bind_at, bind_number, bind_addr) = {
189                let b = if let Some(b) = self.client.binding_mgr.find_by_addr(&peer_addr) {
190                    b
191                } else {
192                    self.client
193                        .binding_mgr
194                        .create(peer_addr)
195                        .ok_or_else(|| Error::Other("Addr not found".to_owned()))?
196                };
197                (b.state(), b.refreshed_at(), b.number, b.addr)
198            };
199
200            if bind_st == BindingState::Idle
201                || bind_st == BindingState::Request
202                || bind_st == BindingState::Failed
203            {
204                // block only callers with the same binding until
205                // the binding transaction has been complete
206                // binding state may have been changed while waiting. check again.
207                if bind_st == BindingState::Idle {
208                    if let Some(b) = self.client.binding_mgr.get_by_addr(&bind_addr) {
209                        b.set_state(BindingState::Request);
210                    }
211                    self.channel_bind(self.relayed_addr, bind_addr, bind_number, nonce, integrity)?;
212                }
213
214                // send data using SendIndication
215                let mut msg = Message::new();
216                msg.build(&[
217                    Box::new(TransactionId::new()),
218                    Box::new(MessageType::new(METHOD_SEND, CLASS_INDICATION)),
219                    Box::new(proto::data::Data(p.to_vec())),
220                    Box::new(proto::peeraddr::PeerAddress {
221                        ip: peer_addr.ip(),
222                        port: peer_addr.port(),
223                    }),
224                    Box::new(FINGERPRINT),
225                ])?;
226
227                // indication has no transaction (fire-and-forget)
228                self.client
229                    .write_to(&msg.raw, self.client.turn_server_addr()?);
230                return Ok(());
231            }
232
233            // binding is ready
234            // check if the binding needs a refresh
235            if bind_st == BindingState::Ready
236                && Instant::now()
237                    .checked_duration_since(bind_at)
238                    .unwrap_or_else(|| Duration::from_secs(0))
239                    > PERM_LIFETIME
240            {
241                if let Some(b) = self.client.binding_mgr.get_by_addr(&bind_addr) {
242                    b.set_state(BindingState::Refresh);
243                }
244                self.channel_bind(self.relayed_addr, bind_addr, bind_number, nonce, integrity)?;
245            }
246
247            bind_number
248        };
249
250        // send via ChannelData
251        self.send_channel_data(p, channel_number)
252    }
253
254    // Close closes the connection.
255    // Any blocked ReadFrom or write_to operations will be unblocked and return errors.
256    /// Releases the allocation by refreshing it with a zero lifetime.
257    ///
258    /// # Errors
259    ///
260    /// Fails if the refresh request cannot be sent.
261    pub fn close(&mut self) -> Result<()> {
262        self.refresh_allocation(Duration::from_secs(0))
263    }
264
265    fn create_permissions(
266        &mut self,
267        peer_addrs: &[SocketAddr],
268        peer_addr_opt: Option<SocketAddr>,
269    ) -> Result<TransactionId> {
270        let (username, realm) = (self.client.username(), self.client.realm());
271        if let Some(relay) = self.client.relays.get_mut(&self.relayed_addr) {
272            let msg = {
273                let mut setters: Vec<Box<dyn Setter>> = vec![
274                    Box::new(TransactionId::new()),
275                    Box::new(MessageType::new(METHOD_CREATE_PERMISSION, CLASS_REQUEST)),
276                ];
277
278                for addr in peer_addrs {
279                    setters.push(Box::new(proto::peeraddr::PeerAddress {
280                        ip: addr.ip(),
281                        port: addr.port(),
282                    }));
283                }
284
285                setters.push(Box::new(username));
286                setters.push(Box::new(realm));
287                setters.push(Box::new(relay.nonce.clone()));
288                setters.push(Box::new(relay.integrity.clone()));
289                setters.push(Box::new(FINGERPRINT));
290
291                let mut msg = Message::new();
292                msg.build(&setters)?;
293                msg
294            };
295
296            Ok(self.client.perform_transaction(
297                &msg,
298                self.client.turn_server_addr()?,
299                TransactionType::CreatePermissionRequest(self.relayed_addr, peer_addr_opt),
300            ))
301        } else {
302            Err(Error::ErrConnClosed)
303        }
304    }
305
306    pub(super) fn handle_create_permission_response(
307        &mut self,
308        res: Message,
309        peer_addr_opt: Option<SocketAddr>,
310    ) -> Result<()> {
311        if let Some(relay) = self.client.relays.get_mut(&self.relayed_addr) {
312            if res.typ.class == CLASS_ERROR_RESPONSE {
313                let mut code = ErrorCodeAttribute::default();
314                let result = code.get_from(&res);
315                let err = if result.is_err() {
316                    Error::Other(format!("{}", res.typ))
317                } else if code.code == CODE_STALE_NONCE {
318                    relay.set_nonce_from_msg(&res);
319                    Error::ErrTryAgain
320                } else {
321                    Error::Other(format!("{} (error {})", res.typ, code))
322                };
323                if let Some(peer_addr) = peer_addr_opt {
324                    self.client
325                        .events
326                        .push_back(Event::CreatePermissionError(res.transaction_id, err));
327                    relay.perm_map.remove(&peer_addr);
328                }
329            } else if let Some(peer_addr) = peer_addr_opt
330                && let Some(perm) = relay.perm_map.get_mut(&peer_addr)
331            {
332                perm.set_state(PermState::Permitted);
333                self.client
334                    .events
335                    .push_back(Event::CreatePermissionResponse(
336                        res.transaction_id,
337                        peer_addr,
338                    ));
339            }
340
341            Ok(())
342        } else {
343            Err(Error::ErrConnClosed)
344        }
345    }
346
347    pub(super) fn refresh_allocation(&mut self, lifetime: Duration) -> Result<()> {
348        let (username, realm) = (self.client.username(), self.client.realm());
349        if let Some(relay) = self.client.relays.get_mut(&self.relayed_addr) {
350            let mut msg = Message::new();
351            msg.build(&[
352                Box::new(TransactionId::new()),
353                Box::new(MessageType::new(METHOD_REFRESH, CLASS_REQUEST)),
354                Box::new(proto::lifetime::Lifetime(lifetime)),
355                Box::new(username),
356                Box::new(realm),
357                Box::new(relay.nonce.clone()),
358                Box::new(relay.integrity.clone()),
359                Box::new(FINGERPRINT),
360            ])?;
361
362            let _ = self.client.perform_transaction(
363                &msg,
364                self.client.turn_server_addr()?,
365                TransactionType::RefreshRequest(self.relayed_addr),
366            );
367
368            Ok(())
369        } else {
370            Err(Error::ErrConnClosed)
371        }
372    }
373
374    pub(super) fn handle_refresh_allocation_response(&mut self, res: Message) -> Result<()> {
375        if let Some(relay) = self.client.relays.get_mut(&self.relayed_addr) {
376            if res.typ.class == CLASS_ERROR_RESPONSE {
377                let mut code = ErrorCodeAttribute::default();
378                let result = code.get_from(&res);
379                if result.is_err() {
380                    Err(Error::Other(format!("{}", res.typ)))
381                } else if code.code == CODE_STALE_NONCE {
382                    relay.set_nonce_from_msg(&res);
383                    //Error::ErrTryAgain
384                    Ok(())
385                } else {
386                    Err(Error::Other(format!("{} (error {})", res.typ, code)))
387                }
388            } else {
389                // Getting lifetime from response
390                let mut updated_lifetime = proto::lifetime::Lifetime::default();
391                updated_lifetime.get_from(&res)?;
392
393                relay.lifetime = updated_lifetime.0;
394                debug!("updated lifetime: {} seconds", relay.lifetime.as_secs());
395
396                Ok(())
397            }
398        } else {
399            Err(Error::ErrConnClosed)
400        }
401    }
402
403    pub(super) fn refresh_permissions(&mut self) -> Result<()> {
404        if let Some(relay) = self.client.relays.get_mut(&self.relayed_addr) {
405            #[allow(clippy::map_clone)]
406            let addrs: Vec<SocketAddr> = relay.perm_map.keys().map(|addr| *addr).collect();
407            if addrs.is_empty() {
408                debug!("no permission to refresh");
409                return Ok(());
410            }
411            let _ = self.create_permissions(&addrs, None)?;
412            Ok(())
413        } else {
414            Err(Error::ErrConnClosed)
415        }
416    }
417
418    fn channel_bind(
419        &mut self,
420        relayed_addr: RelayedAddr,
421        bind_addr: SocketAddr,
422        bind_number: u16,
423        nonce: Nonce,
424        integrity: MessageIntegrity,
425    ) -> Result<()> {
426        let (msg, turn_server_addr) = {
427            let setters: Vec<Box<dyn Setter>> = vec![
428                Box::new(TransactionId::new()),
429                Box::new(MessageType::new(METHOD_CHANNEL_BIND, CLASS_REQUEST)),
430                Box::new(proto::peeraddr::PeerAddress {
431                    ip: bind_addr.ip(),
432                    port: bind_addr.port(),
433                }),
434                Box::new(proto::channum::ChannelNumber(bind_number)),
435                Box::new(self.client.username()),
436                Box::new(self.client.realm()),
437                Box::new(nonce),
438                Box::new(integrity),
439                Box::new(FINGERPRINT),
440            ];
441
442            let mut msg = Message::new();
443            msg.build(&setters)?;
444
445            (msg, self.client.turn_server_addr()?)
446        };
447
448        debug!("UDPConn.bind call PerformTransaction 1");
449        let _ = self.client.perform_transaction(
450            &msg,
451            turn_server_addr,
452            TransactionType::ChannelBindRequest(relayed_addr, bind_addr),
453        );
454
455        Ok(())
456    }
457
458    pub(super) fn handle_channel_bind_response(
459        &mut self,
460        res: Message,
461        bind_addr: SocketAddr,
462    ) -> Result<()> {
463        if let Some(relay) = self.client.relays.get_mut(&self.relayed_addr) {
464            let result = if res.typ.class == CLASS_ERROR_RESPONSE {
465                let mut code = ErrorCodeAttribute::default();
466                let result = code.get_from(&res);
467                if result.is_err() {
468                    Err(Error::Other(format!("{}", res.typ)))
469                } else if code.code == CODE_STALE_NONCE {
470                    relay.set_nonce_from_msg(&res);
471                    Err(Error::ErrTryAgain)
472                } else {
473                    Err(Error::Other(format!("{} (error {})", res.typ, code)))
474                }
475            } else if res.typ != MessageType::new(METHOD_CHANNEL_BIND, CLASS_SUCCESS_RESPONSE) {
476                Err(Error::ErrUnexpectedResponse)
477            } else {
478                Ok(())
479            };
480
481            if let Err(err) = result {
482                if Error::ErrUnexpectedResponse != err {
483                    self.client.binding_mgr.delete_by_addr(&bind_addr);
484                } else if let Some(b) = self.client.binding_mgr.get_by_addr(&bind_addr) {
485                    b.set_state(BindingState::Failed);
486                }
487
488                // keep going...
489                warn!("bind() failed: {}", err);
490            } else if let Some(b) = self.client.binding_mgr.get_by_addr(&bind_addr) {
491                b.set_refreshed_at(Instant::now());
492                b.set_state(BindingState::Ready);
493                debug!("channel binding successful: {}", bind_addr);
494            }
495            Ok(())
496        } else {
497            Err(Error::ErrConnClosed)
498        }
499    }
500
501    fn send_channel_data(&mut self, data: &[u8], channel_number: u16) -> Result<()> {
502        let mut ch_data = proto::chandata::ChannelData {
503            data: data.to_vec(),
504            number: proto::channum::ChannelNumber(channel_number),
505            ..Default::default()
506        };
507        ch_data.encode();
508
509        self.client
510            .write_to(&ch_data.raw, self.client.turn_server_addr()?);
511
512        Ok(())
513    }
514}