xref: /webrtc/turn/src/server/mod.rs (revision 8b68b472)
1 #[cfg(test)]
2 mod server_test;
3 
4 pub mod config;
5 pub mod request;
6 
7 use crate::{
8     allocation::{allocation_manager::*, five_tuple::FiveTuple, AllocationInfo},
9     auth::AuthHandler,
10     error::*,
11     proto::lifetime::DEFAULT_LIFETIME,
12 };
13 use config::*;
14 use request::*;
15 
16 use std::{collections::HashMap, sync::Arc};
17 
18 use tokio::{
19     sync::{
20         broadcast::{self, error::RecvError},
21         mpsc, oneshot, Mutex,
22     },
23     time::{Duration, Instant},
24 };
25 use util::Conn;
26 
27 const INBOUND_MTU: usize = 1500;
28 
29 /// Server is an instance of the TURN Server
30 pub struct Server {
31     auth_handler: Arc<dyn AuthHandler + Send + Sync>,
32     realm: String,
33     channel_bind_timeout: Duration,
34     pub(crate) nonces: Arc<Mutex<HashMap<String, Instant>>>,
35     command_tx: Mutex<Option<broadcast::Sender<Command>>>,
36 }
37 
38 impl Server {
39     /// creates the TURN server
40     pub async fn new(config: ServerConfig) -> Result<Self> {
41         config.validate()?;
42 
43         let (command_tx, _) = broadcast::channel(16);
44         let mut s = Server {
45             auth_handler: config.auth_handler,
46             realm: config.realm,
47             channel_bind_timeout: config.channel_bind_timeout,
48             nonces: Arc::new(Mutex::new(HashMap::new())),
49             command_tx: Mutex::new(Some(command_tx.clone())),
50         };
51 
52         if s.channel_bind_timeout == Duration::from_secs(0) {
53             s.channel_bind_timeout = DEFAULT_LIFETIME;
54         }
55 
56         for p in config.conn_configs.into_iter() {
57             let nonces = Arc::clone(&s.nonces);
58             let auth_handler = Arc::clone(&s.auth_handler);
59             let realm = s.realm.clone();
60             let channel_bind_timeout = s.channel_bind_timeout;
61             let handle_rx = command_tx.subscribe();
62             let conn = p.conn;
63             let allocation_manager = Arc::new(Manager::new(ManagerConfig {
64                 relay_addr_generator: p.relay_addr_generator,
65             }));
66 
67             tokio::spawn(Server::read_loop(
68                 conn,
69                 allocation_manager,
70                 nonces,
71                 auth_handler,
72                 realm,
73                 channel_bind_timeout,
74                 handle_rx,
75             ));
76         }
77 
78         Ok(s)
79     }
80 
81     /// Deletes all existing [`crate::allocation::Allocation`]s by the provided `username`.
82     pub async fn delete_allocations_by_username(&self, username: String) -> Result<()> {
83         let tx = {
84             let command_tx = self.command_tx.lock().await;
85             command_tx.clone()
86         };
87         if let Some(tx) = tx {
88             let (closed_tx, closed_rx) = mpsc::channel(1);
89             tx.send(Command::DeleteAllocations(username, Arc::new(closed_rx)))
90                 .map_err(|_| Error::ErrClosed)?;
91 
92             closed_tx.closed().await;
93 
94             Ok(())
95         } else {
96             Err(Error::ErrClosed)
97         }
98     }
99 
100     /// Get information of [`Allocation`]s by specified [`FiveTuple`]s.
101     ///
102     /// If `five_tuples` is:
103     /// - [`None`]:               It returns information about the all
104     ///                           [`Allocation`]s.
105     /// - [`Some`] and not empty: It returns information about
106     ///                           the [`Allocation`]s associated with
107     ///                           the specified [`FiveTuples`].
108     /// - [`Some`], but empty:    It returns an empty [`HashMap`].
109     ///
110     /// [`Allocation`]: crate::allocation::Allocation
111     pub async fn get_allocations_info(
112         &self,
113         five_tuples: Option<Vec<FiveTuple>>,
114     ) -> Result<HashMap<FiveTuple, AllocationInfo>> {
115         if let Some(five_tuples) = &five_tuples {
116             if five_tuples.is_empty() {
117                 return Ok(HashMap::new());
118             }
119         }
120 
121         let tx = {
122             let command_tx = self.command_tx.lock().await;
123             command_tx.clone()
124         };
125         if let Some(tx) = tx {
126             let (infos_tx, mut infos_rx) = mpsc::channel(1);
127             tx.send(Command::GetAllocationsInfo(five_tuples, infos_tx))
128                 .map_err(|_| Error::ErrClosed)?;
129 
130             let mut info: HashMap<FiveTuple, AllocationInfo> = HashMap::new();
131 
132             for _ in 0..tx.receiver_count() {
133                 info.extend(infos_rx.recv().await.ok_or(Error::ErrClosed)?);
134             }
135 
136             Ok(info)
137         } else {
138             Err(Error::ErrClosed)
139         }
140     }
141 
142     async fn read_loop(
143         conn: Arc<dyn Conn + Send + Sync>,
144         allocation_manager: Arc<Manager>,
145         nonces: Arc<Mutex<HashMap<String, Instant>>>,
146         auth_handler: Arc<dyn AuthHandler + Send + Sync>,
147         realm: String,
148         channel_bind_timeout: Duration,
149         mut handle_rx: broadcast::Receiver<Command>,
150     ) {
151         let mut buf = vec![0u8; INBOUND_MTU];
152 
153         let (mut close_tx, mut close_rx) = oneshot::channel::<()>();
154 
155         tokio::spawn({
156             let allocation_manager = Arc::clone(&allocation_manager);
157 
158             async move {
159                 loop {
160                     match handle_rx.recv().await {
161                         Ok(Command::DeleteAllocations(name, _)) => {
162                             allocation_manager
163                                 .delete_allocations_by_username(name.as_str())
164                                 .await;
165                             continue;
166                         }
167                         Ok(Command::GetAllocationsInfo(five_tuples, tx)) => {
168                             let infos = allocation_manager.get_allocations_info(five_tuples).await;
169                             let _ = tx.send(infos).await;
170 
171                             continue;
172                         }
173                         Err(RecvError::Closed) | Ok(Command::Close(_)) => {
174                             close_rx.close();
175                             break;
176                         }
177                         Err(RecvError::Lagged(n)) => {
178                             log::warn!("Turn server has lagged by {} messages", n);
179                             continue;
180                         }
181                     }
182                 }
183             }
184         });
185 
186         loop {
187             let (n, addr) = tokio::select! {
188                 v = conn.recv_from(&mut buf) => {
189                     match v {
190                         Ok(v) => v,
191                         Err(err) => {
192                             log::debug!("exit read loop on error: {}", err);
193                             break;
194                         }
195                     }
196                 },
197                 _ = close_tx.closed() => break
198             };
199 
200             let mut r = Request {
201                 conn: Arc::clone(&conn),
202                 src_addr: addr,
203                 buff: buf[..n].to_vec(),
204                 allocation_manager: Arc::clone(&allocation_manager),
205                 nonces: Arc::clone(&nonces),
206                 auth_handler: Arc::clone(&auth_handler),
207                 realm: realm.clone(),
208                 channel_bind_timeout,
209             };
210 
211             if let Err(err) = r.handle_request().await {
212                 log::error!("error when handling datagram: {}", err);
213             }
214         }
215 
216         let _ = allocation_manager.close().await;
217         let _ = conn.close().await;
218     }
219 
220     /// Close stops the TURN Server. It cleans up any associated state and closes all connections it is managing
221     pub async fn close(&self) -> Result<()> {
222         let tx = {
223             let mut command_tx = self.command_tx.lock().await;
224             command_tx.take()
225         };
226 
227         if let Some(tx) = tx {
228             if tx.receiver_count() == 0 {
229                 return Ok(());
230             }
231 
232             let (closed_tx, closed_rx) = mpsc::channel(1);
233             let _ = tx.send(Command::Close(Arc::new(closed_rx)));
234             closed_tx.closed().await
235         }
236 
237         Ok(())
238     }
239 }
240 
241 /// The protocol to communicate between the [`Server`]'s public methods
242 /// and the tasks spawned in the [`read_loop`] method.
243 #[derive(Clone)]
244 enum Command {
245     /// Command to delete [`crate::allocation::Allocation`] by provided
246     /// `username`.
247     DeleteAllocations(String, Arc<mpsc::Receiver<()>>),
248 
249     /// Command to get information of [`Allocation`]s by provided [`FiveTuple`]s.
250     ///
251     /// [`Allocation`]: [`crate::allocation::Allocation`]
252     GetAllocationsInfo(
253         Option<Vec<FiveTuple>>,
254         mpsc::Sender<HashMap<FiveTuple, AllocationInfo>>,
255     ),
256 
257     /// Command to close the [`Server`].
258     Close(Arc<mpsc::Receiver<()>>),
259 }
260