clia_turn/relay/
relay_range.rs

1use std::net::IpAddr;
2
3use async_trait::async_trait;
4use util::vnet::net::*;
5
6use super::*;
7use crate::error::*;
8
9/// `RelayAddressGeneratorRanges` can be used to only allocate connections inside a defined port range.
10pub struct RelayAddressGeneratorRanges {
11    /// `relay_address` is the IP returned to the user when the relay is created.
12    pub relay_address: IpAddr,
13
14    /// `min_port` the minimum port to allocate.
15    pub min_port: u16,
16
17    /// `max_port` the maximum (inclusive) port to allocate.
18    pub max_port: u16,
19
20    /// `max_retries` the amount of tries to allocate a random port in the defined range.
21    pub max_retries: u16,
22
23    /// `address` is passed to Listen/ListenPacket when creating the Relay.
24    pub address: String,
25
26    pub net: Arc<Net>,
27}
28
29#[async_trait]
30impl RelayAddressGenerator for RelayAddressGeneratorRanges {
31    fn validate(&self) -> Result<()> {
32        if self.min_port == 0 {
33            Err(Error::ErrMinPortNotZero)
34        } else if self.max_port == 0 {
35            Err(Error::ErrMaxPortNotZero)
36        } else if self.max_port < self.min_port {
37            Err(Error::ErrMaxPortLessThanMinPort)
38        } else if self.address.is_empty() {
39            Err(Error::ErrListeningAddressInvalid)
40        } else {
41            Ok(())
42        }
43    }
44
45    async fn allocate_conn(
46        &self,
47        use_ipv4: bool,
48        requested_port: u16,
49    ) -> Result<(Arc<dyn Conn + Send + Sync>, SocketAddr)> {
50        let max_retries = if self.max_retries == 0 {
51            10
52        } else {
53            self.max_retries
54        };
55
56        if requested_port != 0 {
57            let addr = self
58                .net
59                .resolve_addr(use_ipv4, &format!("{}:{}", self.address, requested_port))
60                .await?;
61            let conn = self.net.bind(addr).await?;
62            let mut relay_addr = conn.local_addr()?;
63            relay_addr.set_ip(self.relay_address);
64            return Ok((conn, relay_addr));
65        }
66
67        for _ in 0..max_retries {
68            let port = self.min_port + rand::random::<u16>() % (self.max_port - self.min_port + 1);
69            let addr = self
70                .net
71                .resolve_addr(use_ipv4, &format!("{}:{}", self.address, port))
72                .await?;
73            let conn = match self.net.bind(addr).await {
74                Ok(conn) => conn,
75                Err(_) => continue,
76            };
77
78            let mut relay_addr = conn.local_addr()?;
79            relay_addr.set_ip(self.relay_address);
80            return Ok((conn, relay_addr));
81        }
82
83        Err(Error::ErrMaxRetriesExceeded)
84    }
85}