xref: /webrtc/turn/src/server/request.rs (revision 5b79f08a)
1ffe74184SMartin Algesten #[cfg(test)]
2ffe74184SMartin Algesten mod request_test;
3ffe74184SMartin Algesten 
4ffe74184SMartin Algesten use crate::allocation::allocation_manager::*;
5ffe74184SMartin Algesten use crate::allocation::channel_bind::ChannelBind;
6ffe74184SMartin Algesten use crate::allocation::five_tuple::*;
7ffe74184SMartin Algesten use crate::allocation::permission::Permission;
8ffe74184SMartin Algesten use crate::auth::*;
9ffe74184SMartin Algesten use crate::error::*;
10ffe74184SMartin Algesten use crate::proto::chandata::ChannelData;
11ffe74184SMartin Algesten use crate::proto::channum::ChannelNumber;
12ffe74184SMartin Algesten use crate::proto::data::Data;
13ffe74184SMartin Algesten use crate::proto::evenport::EvenPort;
14ffe74184SMartin Algesten use crate::proto::lifetime::*;
15ffe74184SMartin Algesten use crate::proto::peeraddr::PeerAddress;
16ffe74184SMartin Algesten use crate::proto::relayaddr::RelayedAddress;
17ffe74184SMartin Algesten use crate::proto::reqtrans::RequestedTransport;
18ffe74184SMartin Algesten use crate::proto::rsrvtoken::ReservationToken;
19ffe74184SMartin Algesten use crate::proto::*;
20ffe74184SMartin Algesten 
21ffe74184SMartin Algesten use stun::agent::*;
22ffe74184SMartin Algesten use stun::attributes::*;
23ffe74184SMartin Algesten use stun::error_code::*;
24ffe74184SMartin Algesten use stun::fingerprint::*;
25ffe74184SMartin Algesten use stun::integrity::*;
26ffe74184SMartin Algesten use stun::message::*;
27ffe74184SMartin Algesten use stun::textattrs::*;
28ffe74184SMartin Algesten use stun::uattrs::*;
29ffe74184SMartin Algesten use stun::xoraddr::*;
30ffe74184SMartin Algesten 
31ffe74184SMartin Algesten use util::Conn;
32ffe74184SMartin Algesten 
33ffe74184SMartin Algesten use std::collections::HashMap;
34ffe74184SMartin Algesten use std::marker::{Send, Sync};
35ffe74184SMartin Algesten use std::net::SocketAddr;
3626682c3dSlogist322 #[cfg(feature = "metrics")]
3726682c3dSlogist322 use std::sync::atomic::Ordering;
38ffe74184SMartin Algesten use std::sync::Arc;
39ffe74184SMartin Algesten use std::time::SystemTime;
40ffe74184SMartin Algesten use tokio::sync::Mutex;
41ffe74184SMartin Algesten use tokio::time::{Duration, Instant};
42ffe74184SMartin Algesten 
43ffe74184SMartin Algesten use md5::{Digest, Md5};
44ffe74184SMartin Algesten 
45ffe74184SMartin Algesten pub(crate) const MAXIMUM_ALLOCATION_LIFETIME: Duration = Duration::from_secs(3600); // https://tools.ietf.org/html/rfc5766#section-6.2 defines 3600 seconds recommendation
46ffe74184SMartin Algesten pub(crate) const NONCE_LIFETIME: Duration = Duration::from_secs(3600); // https://tools.ietf.org/html/rfc5766#section-4
47ffe74184SMartin Algesten 
48ffe74184SMartin Algesten // Request contains all the state needed to process a single incoming datagram
49ffe74184SMartin Algesten pub struct Request {
50ffe74184SMartin Algesten     // Current Request State
51ffe74184SMartin Algesten     pub conn: Arc<dyn Conn + Send + Sync>,
52ffe74184SMartin Algesten     pub src_addr: SocketAddr,
53ffe74184SMartin Algesten     pub buff: Vec<u8>,
54ffe74184SMartin Algesten 
55ffe74184SMartin Algesten     // Server State
56ffe74184SMartin Algesten     pub allocation_manager: Arc<Manager>,
57ffe74184SMartin Algesten     pub nonces: Arc<Mutex<HashMap<String, Instant>>>,
58ffe74184SMartin Algesten 
59ffe74184SMartin Algesten     // User Configuration
60ffe74184SMartin Algesten     pub auth_handler: Arc<dyn AuthHandler + Send + Sync>,
61ffe74184SMartin Algesten     pub realm: String,
62ffe74184SMartin Algesten     pub channel_bind_timeout: Duration,
63ffe74184SMartin Algesten }
64ffe74184SMartin Algesten 
65ffe74184SMartin Algesten impl Request {
new( conn: Arc<dyn Conn + Send + Sync>, src_addr: SocketAddr, allocation_manager: Arc<Manager>, auth_handler: Arc<dyn AuthHandler + Send + Sync>, ) -> Self66ffe74184SMartin Algesten     pub fn new(
67ffe74184SMartin Algesten         conn: Arc<dyn Conn + Send + Sync>,
68ffe74184SMartin Algesten         src_addr: SocketAddr,
69ffe74184SMartin Algesten         allocation_manager: Arc<Manager>,
70ffe74184SMartin Algesten         auth_handler: Arc<dyn AuthHandler + Send + Sync>,
71ffe74184SMartin Algesten     ) -> Self {
72ffe74184SMartin Algesten         Request {
73ffe74184SMartin Algesten             conn,
74ffe74184SMartin Algesten             src_addr,
75ffe74184SMartin Algesten             buff: vec![],
76ffe74184SMartin Algesten             allocation_manager,
77ffe74184SMartin Algesten             nonces: Arc::new(Mutex::new(HashMap::new())),
78ffe74184SMartin Algesten             auth_handler,
79ffe74184SMartin Algesten             realm: String::new(),
80ffe74184SMartin Algesten             channel_bind_timeout: Duration::from_secs(0),
81ffe74184SMartin Algesten         }
82ffe74184SMartin Algesten     }
83ffe74184SMartin Algesten 
84ffe74184SMartin Algesten     // handle_request processes the give Request
handle_request(&mut self) -> Result<()>85ffe74184SMartin Algesten     pub async fn handle_request(&mut self) -> Result<()> {
86ffe74184SMartin Algesten         /*log::debug!(
87ffe74184SMartin Algesten             "received {} bytes of udp from {} on {}",
88ffe74184SMartin Algesten             self.buff.len(),
89ffe74184SMartin Algesten             self.src_addr,
90ffe74184SMartin Algesten             self.conn.local_addr().await?
91ffe74184SMartin Algesten         );*/
92ffe74184SMartin Algesten 
93ffe74184SMartin Algesten         if ChannelData::is_channel_data(&self.buff) {
94ffe74184SMartin Algesten             self.handle_data_packet().await
95ffe74184SMartin Algesten         } else {
96ffe74184SMartin Algesten             self.handle_turn_packet().await
97ffe74184SMartin Algesten         }
98ffe74184SMartin Algesten     }
99ffe74184SMartin Algesten 
handle_data_packet(&mut self) -> Result<()>100ffe74184SMartin Algesten     async fn handle_data_packet(&mut self) -> Result<()> {
101ffe74184SMartin Algesten         log::debug!("received DataPacket from {}", self.src_addr);
102ffe74184SMartin Algesten         let mut c = ChannelData {
103ffe74184SMartin Algesten             raw: self.buff.clone(),
104ffe74184SMartin Algesten             ..Default::default()
105ffe74184SMartin Algesten         };
106ffe74184SMartin Algesten         c.decode()?;
107ffe74184SMartin Algesten         self.handle_channel_data(&c).await
108ffe74184SMartin Algesten     }
109ffe74184SMartin Algesten 
handle_turn_packet(&mut self) -> Result<()>110ffe74184SMartin Algesten     async fn handle_turn_packet(&mut self) -> Result<()> {
111ffe74184SMartin Algesten         log::debug!("handle_turn_packet");
112ffe74184SMartin Algesten         let mut m = Message {
113ffe74184SMartin Algesten             raw: self.buff.clone(),
114ffe74184SMartin Algesten             ..Default::default()
115ffe74184SMartin Algesten         };
116ffe74184SMartin Algesten         m.decode()?;
117ffe74184SMartin Algesten 
118ffe74184SMartin Algesten         self.process_message_handler(&m).await
119ffe74184SMartin Algesten     }
120ffe74184SMartin Algesten 
process_message_handler(&mut self, m: &Message) -> Result<()>121ffe74184SMartin Algesten     async fn process_message_handler(&mut self, m: &Message) -> Result<()> {
122ffe74184SMartin Algesten         if m.typ.class == CLASS_INDICATION {
123ffe74184SMartin Algesten             match m.typ.method {
124ffe74184SMartin Algesten                 METHOD_SEND => self.handle_send_indication(m).await,
125ffe74184SMartin Algesten                 _ => Err(Error::ErrUnexpectedClass),
126ffe74184SMartin Algesten             }
127ffe74184SMartin Algesten         } else if m.typ.class == CLASS_REQUEST {
128ffe74184SMartin Algesten             match m.typ.method {
129ffe74184SMartin Algesten                 METHOD_ALLOCATE => self.handle_allocate_request(m).await,
130ffe74184SMartin Algesten                 METHOD_REFRESH => self.handle_refresh_request(m).await,
131ffe74184SMartin Algesten                 METHOD_CREATE_PERMISSION => self.handle_create_permission_request(m).await,
132ffe74184SMartin Algesten                 METHOD_CHANNEL_BIND => self.handle_channel_bind_request(m).await,
133ffe74184SMartin Algesten                 METHOD_BINDING => self.handle_binding_request(m).await,
134ffe74184SMartin Algesten                 _ => Err(Error::ErrUnexpectedClass),
135ffe74184SMartin Algesten             }
136ffe74184SMartin Algesten         } else {
137ffe74184SMartin Algesten             Err(Error::ErrUnexpectedClass)
138ffe74184SMartin Algesten         }
139ffe74184SMartin Algesten     }
140ffe74184SMartin Algesten 
authenticate_request( &mut self, m: &Message, calling_method: Method, ) -> Result<Option<(Username, MessageIntegrity)>>141ffe74184SMartin Algesten     pub(crate) async fn authenticate_request(
142ffe74184SMartin Algesten         &mut self,
143ffe74184SMartin Algesten         m: &Message,
144ffe74184SMartin Algesten         calling_method: Method,
145c4e6ecf8Slogist322     ) -> Result<Option<(Username, MessageIntegrity)>> {
146ffe74184SMartin Algesten         if !m.contains(ATTR_MESSAGE_INTEGRITY) {
147ffe74184SMartin Algesten             self.respond_with_nonce(m, calling_method, CODE_UNAUTHORIZED)
148ffe74184SMartin Algesten                 .await?;
149ffe74184SMartin Algesten             return Ok(None);
150ffe74184SMartin Algesten         }
151ffe74184SMartin Algesten 
152ffe74184SMartin Algesten         let mut nonce_attr = Nonce::new(ATTR_NONCE, String::new());
153ffe74184SMartin Algesten         let mut username_attr = Username::new(ATTR_USERNAME, String::new());
154ffe74184SMartin Algesten         let mut realm_attr = Realm::new(ATTR_REALM, String::new());
155ffe74184SMartin Algesten         let bad_request_msg = build_msg(
156ffe74184SMartin Algesten             m.transaction_id,
157ffe74184SMartin Algesten             MessageType::new(calling_method, CLASS_ERROR_RESPONSE),
158ffe74184SMartin Algesten             vec![Box::new(ErrorCodeAttribute {
159ffe74184SMartin Algesten                 code: CODE_BAD_REQUEST,
160ffe74184SMartin Algesten                 reason: vec![],
161ffe74184SMartin Algesten             })],
162ffe74184SMartin Algesten         )?;
163ffe74184SMartin Algesten 
164ffe74184SMartin Algesten         if let Err(err) = nonce_attr.get_from(m) {
165ffe74184SMartin Algesten             build_and_send_err(&self.conn, self.src_addr, bad_request_msg, err.into()).await?;
166ffe74184SMartin Algesten             return Ok(None);
167ffe74184SMartin Algesten         }
168ffe74184SMartin Algesten 
169ffe74184SMartin Algesten         let to_be_deleted = {
170ffe74184SMartin Algesten             // Assert Nonce exists and is not expired
171ffe74184SMartin Algesten             let mut nonces = self.nonces.lock().await;
172ffe74184SMartin Algesten 
173ffe74184SMartin Algesten             let to_be_deleted = if let Some(nonce_creation_time) = nonces.get(&nonce_attr.text) {
174ffe74184SMartin Algesten                 Instant::now()
175ffe74184SMartin Algesten                     .checked_duration_since(*nonce_creation_time)
176ffe74184SMartin Algesten                     .unwrap_or_else(|| Duration::from_secs(0))
177ffe74184SMartin Algesten                     >= NONCE_LIFETIME
178ffe74184SMartin Algesten             } else {
179ffe74184SMartin Algesten                 true
180ffe74184SMartin Algesten             };
181ffe74184SMartin Algesten 
182ffe74184SMartin Algesten             if to_be_deleted {
183ffe74184SMartin Algesten                 nonces.remove(&nonce_attr.text);
184ffe74184SMartin Algesten             }
185ffe74184SMartin Algesten             to_be_deleted
186ffe74184SMartin Algesten         };
187ffe74184SMartin Algesten 
188ffe74184SMartin Algesten         if to_be_deleted {
189ffe74184SMartin Algesten             self.respond_with_nonce(m, calling_method, CODE_STALE_NONCE)
190ffe74184SMartin Algesten                 .await?;
191ffe74184SMartin Algesten             return Ok(None);
192ffe74184SMartin Algesten         }
193ffe74184SMartin Algesten 
194ffe74184SMartin Algesten         if let Err(err) = realm_attr.get_from(m) {
195ffe74184SMartin Algesten             build_and_send_err(&self.conn, self.src_addr, bad_request_msg, err.into()).await?;
196ffe74184SMartin Algesten             return Ok(None);
197ffe74184SMartin Algesten         }
198ffe74184SMartin Algesten         if let Err(err) = username_attr.get_from(m) {
199ffe74184SMartin Algesten             build_and_send_err(&self.conn, self.src_addr, bad_request_msg, err.into()).await?;
200ffe74184SMartin Algesten             return Ok(None);
201ffe74184SMartin Algesten         }
202ffe74184SMartin Algesten 
203ffe74184SMartin Algesten         let our_key = match self.auth_handler.auth_handle(
204ffe74184SMartin Algesten             &username_attr.to_string(),
205ffe74184SMartin Algesten             &realm_attr.to_string(),
206ffe74184SMartin Algesten             self.src_addr,
207ffe74184SMartin Algesten         ) {
208ffe74184SMartin Algesten             Ok(key) => key,
209ffe74184SMartin Algesten             Err(_) => {
210ffe74184SMartin Algesten                 build_and_send_err(
211ffe74184SMartin Algesten                     &self.conn,
212ffe74184SMartin Algesten                     self.src_addr,
213ffe74184SMartin Algesten                     bad_request_msg,
214ffe74184SMartin Algesten                     Error::ErrNoSuchUser,
215ffe74184SMartin Algesten                 )
216ffe74184SMartin Algesten                 .await?;
217ffe74184SMartin Algesten                 return Ok(None);
218ffe74184SMartin Algesten             }
219ffe74184SMartin Algesten         };
220ffe74184SMartin Algesten 
221ffe74184SMartin Algesten         let mi = MessageIntegrity(our_key);
222ffe74184SMartin Algesten         if let Err(err) = mi.check(&mut m.clone()) {
223ffe74184SMartin Algesten             build_and_send_err(&self.conn, self.src_addr, bad_request_msg, err.into()).await?;
224ffe74184SMartin Algesten             Ok(None)
225ffe74184SMartin Algesten         } else {
226c4e6ecf8Slogist322             Ok(Some((username_attr, mi)))
227ffe74184SMartin Algesten         }
228ffe74184SMartin Algesten     }
229ffe74184SMartin Algesten 
respond_with_nonce( &mut self, m: &Message, calling_method: Method, response_code: ErrorCode, ) -> Result<()>230ffe74184SMartin Algesten     async fn respond_with_nonce(
231ffe74184SMartin Algesten         &mut self,
232ffe74184SMartin Algesten         m: &Message,
233ffe74184SMartin Algesten         calling_method: Method,
234ffe74184SMartin Algesten         response_code: ErrorCode,
235ffe74184SMartin Algesten     ) -> Result<()> {
236ffe74184SMartin Algesten         let nonce = build_nonce()?;
237ffe74184SMartin Algesten 
238ffe74184SMartin Algesten         {
239ffe74184SMartin Algesten             // Nonce has already been taken
240ffe74184SMartin Algesten             let mut nonces = self.nonces.lock().await;
241ffe74184SMartin Algesten             if nonces.contains_key(&nonce) {
242ffe74184SMartin Algesten                 return Err(Error::ErrDuplicatedNonce);
243ffe74184SMartin Algesten             }
244ffe74184SMartin Algesten             nonces.insert(nonce.clone(), Instant::now());
245ffe74184SMartin Algesten         }
246ffe74184SMartin Algesten 
247ffe74184SMartin Algesten         let msg = build_msg(
248ffe74184SMartin Algesten             m.transaction_id,
249ffe74184SMartin Algesten             MessageType::new(calling_method, CLASS_ERROR_RESPONSE),
250ffe74184SMartin Algesten             vec![
251ffe74184SMartin Algesten                 Box::new(ErrorCodeAttribute {
252ffe74184SMartin Algesten                     code: response_code,
253ffe74184SMartin Algesten                     reason: vec![],
254ffe74184SMartin Algesten                 }),
255ffe74184SMartin Algesten                 Box::new(Nonce::new(ATTR_NONCE, nonce)),
256ffe74184SMartin Algesten                 Box::new(Realm::new(ATTR_REALM, self.realm.clone())),
257ffe74184SMartin Algesten             ],
258ffe74184SMartin Algesten         )?;
259ffe74184SMartin Algesten 
260ffe74184SMartin Algesten         build_and_send(&self.conn, self.src_addr, msg).await
261ffe74184SMartin Algesten     }
262ffe74184SMartin Algesten 
handle_binding_request(&mut self, m: &Message) -> Result<()>263ffe74184SMartin Algesten     pub(crate) async fn handle_binding_request(&mut self, m: &Message) -> Result<()> {
264ffe74184SMartin Algesten         log::debug!("received BindingRequest from {}", self.src_addr);
265ffe74184SMartin Algesten 
266ffe74184SMartin Algesten         let (ip, port) = (self.src_addr.ip(), self.src_addr.port());
267ffe74184SMartin Algesten 
268ffe74184SMartin Algesten         let msg = build_msg(
269ffe74184SMartin Algesten             m.transaction_id,
270ffe74184SMartin Algesten             BINDING_SUCCESS,
271ffe74184SMartin Algesten             vec![
272ffe74184SMartin Algesten                 Box::new(XorMappedAddress { ip, port }),
273ffe74184SMartin Algesten                 Box::new(FINGERPRINT),
274ffe74184SMartin Algesten             ],
275ffe74184SMartin Algesten         )?;
276ffe74184SMartin Algesten 
277ffe74184SMartin Algesten         build_and_send(&self.conn, self.src_addr, msg).await
278ffe74184SMartin Algesten     }
279ffe74184SMartin Algesten 
280ffe74184SMartin Algesten     // // https://tools.ietf.org/html/rfc5766#section-6.2
handle_allocate_request(&mut self, m: &Message) -> Result<()>281ffe74184SMartin Algesten     pub(crate) async fn handle_allocate_request(&mut self, m: &Message) -> Result<()> {
282ffe74184SMartin Algesten         log::debug!("received AllocateRequest from {}", self.src_addr);
283ffe74184SMartin Algesten 
284ffe74184SMartin Algesten         // 1. The server MUST require that the request be authenticated.  This
285ffe74184SMartin Algesten         //    authentication MUST be done using the long-term credential
286ffe74184SMartin Algesten         //    mechanism of [https://tools.ietf.org/html/rfc5389#section-10.2.2]
287ffe74184SMartin Algesten         //    unless the client and server agree to use another mechanism through
288ffe74184SMartin Algesten         //    some procedure outside the scope of this document.
289c4e6ecf8Slogist322         let (username, message_integrity) =
290ffe74184SMartin Algesten             if let Some(mi) = self.authenticate_request(m, METHOD_ALLOCATE).await? {
291ffe74184SMartin Algesten                 mi
292ffe74184SMartin Algesten             } else {
293ffe74184SMartin Algesten                 log::debug!("no MessageIntegrity");
294ffe74184SMartin Algesten                 return Ok(());
295ffe74184SMartin Algesten             };
296ffe74184SMartin Algesten 
297ffe74184SMartin Algesten         let five_tuple = FiveTuple {
298ffe74184SMartin Algesten             src_addr: self.src_addr,
299*5b79f08aSalexlapa             dst_addr: self.conn.local_addr()?,
300ffe74184SMartin Algesten             protocol: PROTO_UDP,
301ffe74184SMartin Algesten         };
302ffe74184SMartin Algesten         let mut requested_port = 0;
303ffe74184SMartin Algesten         let mut reservation_token = "".to_owned();
304ffe74184SMartin Algesten 
305ffe74184SMartin Algesten         // 2. The server checks if the 5-tuple is currently in use by an
306ffe74184SMartin Algesten         //    existing allocation.  If yes, the server rejects the request with
307ffe74184SMartin Algesten         //    a 437 (Allocation Mismatch) error.
308ffe74184SMartin Algesten         if self
309ffe74184SMartin Algesten             .allocation_manager
310ffe74184SMartin Algesten             .get_allocation(&five_tuple)
311ffe74184SMartin Algesten             .await
312ffe74184SMartin Algesten             .is_some()
313ffe74184SMartin Algesten         {
314ffe74184SMartin Algesten             let msg = build_msg(
315ffe74184SMartin Algesten                 m.transaction_id,
316ffe74184SMartin Algesten                 MessageType::new(METHOD_ALLOCATE, CLASS_ERROR_RESPONSE),
317ffe74184SMartin Algesten                 vec![Box::new(ErrorCodeAttribute {
318ffe74184SMartin Algesten                     code: CODE_ALLOC_MISMATCH,
319ffe74184SMartin Algesten                     reason: vec![],
320ffe74184SMartin Algesten                 })],
321ffe74184SMartin Algesten             )?;
322ffe74184SMartin Algesten             return build_and_send_err(
323ffe74184SMartin Algesten                 &self.conn,
324ffe74184SMartin Algesten                 self.src_addr,
325ffe74184SMartin Algesten                 msg,
326ffe74184SMartin Algesten                 Error::ErrRelayAlreadyAllocatedForFiveTuple,
327ffe74184SMartin Algesten             )
328ffe74184SMartin Algesten             .await;
329ffe74184SMartin Algesten         }
330ffe74184SMartin Algesten 
331ffe74184SMartin Algesten         // 3. The server checks if the request contains a REQUESTED-TRANSPORT
332ffe74184SMartin Algesten         //    attribute.  If the REQUESTED-TRANSPORT attribute is not included
333ffe74184SMartin Algesten         //    or is malformed, the server rejects the request with a 400 (Bad
334ffe74184SMartin Algesten         //    Request) error.  Otherwise, if the attribute is included but
335ffe74184SMartin Algesten         //    specifies a protocol other that UDP, the server rejects the
336ffe74184SMartin Algesten         //    request with a 442 (Unsupported Transport Protocol) error.
337ffe74184SMartin Algesten         let mut requested_transport = RequestedTransport::default();
338ffe74184SMartin Algesten         if let Err(err) = requested_transport.get_from(m) {
339ffe74184SMartin Algesten             let bad_request_msg = build_msg(
340ffe74184SMartin Algesten                 m.transaction_id,
341ffe74184SMartin Algesten                 MessageType::new(METHOD_ALLOCATE, CLASS_ERROR_RESPONSE),
342ffe74184SMartin Algesten                 vec![Box::new(ErrorCodeAttribute {
343ffe74184SMartin Algesten                     code: CODE_BAD_REQUEST,
344ffe74184SMartin Algesten                     reason: vec![],
345ffe74184SMartin Algesten                 })],
346ffe74184SMartin Algesten             )?;
347ffe74184SMartin Algesten             return build_and_send_err(&self.conn, self.src_addr, bad_request_msg, err.into())
348ffe74184SMartin Algesten                 .await;
349ffe74184SMartin Algesten         } else if requested_transport.protocol != PROTO_UDP {
350ffe74184SMartin Algesten             let msg = build_msg(
351ffe74184SMartin Algesten                 m.transaction_id,
352ffe74184SMartin Algesten                 MessageType::new(METHOD_ALLOCATE, CLASS_ERROR_RESPONSE),
353ffe74184SMartin Algesten                 vec![Box::new(ErrorCodeAttribute {
354ffe74184SMartin Algesten                     code: CODE_UNSUPPORTED_TRANS_PROTO,
355ffe74184SMartin Algesten                     reason: vec![],
356ffe74184SMartin Algesten                 })],
357ffe74184SMartin Algesten             )?;
358ffe74184SMartin Algesten             return build_and_send_err(
359ffe74184SMartin Algesten                 &self.conn,
360ffe74184SMartin Algesten                 self.src_addr,
361ffe74184SMartin Algesten                 msg,
362ffe74184SMartin Algesten                 Error::ErrRequestedTransportMustBeUdp,
363ffe74184SMartin Algesten             )
364ffe74184SMartin Algesten             .await;
365ffe74184SMartin Algesten         }
366ffe74184SMartin Algesten 
367ffe74184SMartin Algesten         // 4. The request may contain a DONT-FRAGMENT attribute.  If it does,
368ffe74184SMartin Algesten         //    but the server does not support sending UDP datagrams with the DF
369ffe74184SMartin Algesten         //    bit set to 1 (see Section 12), then the server treats the DONT-
370ffe74184SMartin Algesten         //    FRAGMENT attribute in the Allocate request as an unknown
371ffe74184SMartin Algesten         //    comprehension-required attribute.
372ffe74184SMartin Algesten         if m.contains(ATTR_DONT_FRAGMENT) {
373ffe74184SMartin Algesten             let msg = build_msg(
374ffe74184SMartin Algesten                 m.transaction_id,
375ffe74184SMartin Algesten                 MessageType::new(METHOD_ALLOCATE, CLASS_ERROR_RESPONSE),
376ffe74184SMartin Algesten                 vec![
377ffe74184SMartin Algesten                     Box::new(ErrorCodeAttribute {
378ffe74184SMartin Algesten                         code: CODE_UNKNOWN_ATTRIBUTE,
379ffe74184SMartin Algesten                         reason: vec![],
380ffe74184SMartin Algesten                     }),
381ffe74184SMartin Algesten                     Box::new(UnknownAttributes(vec![ATTR_DONT_FRAGMENT])),
382ffe74184SMartin Algesten                 ],
383ffe74184SMartin Algesten             )?;
384ffe74184SMartin Algesten             return build_and_send_err(
385ffe74184SMartin Algesten                 &self.conn,
386ffe74184SMartin Algesten                 self.src_addr,
387ffe74184SMartin Algesten                 msg,
388ffe74184SMartin Algesten                 Error::ErrNoDontFragmentSupport,
389ffe74184SMartin Algesten             )
390ffe74184SMartin Algesten             .await;
391ffe74184SMartin Algesten         }
392ffe74184SMartin Algesten 
393ffe74184SMartin Algesten         // 5.  The server checks if the request contains a RESERVATION-TOKEN
394ffe74184SMartin Algesten         //     attribute.  If yes, and the request also contains an EVEN-PORT
395ffe74184SMartin Algesten         //     attribute, then the server rejects the request with a 400 (Bad
396ffe74184SMartin Algesten         //     Request) error.  Otherwise, it checks to see if the token is
397ffe74184SMartin Algesten         //     valid (i.e., the token is in range and has not expired and the
398ffe74184SMartin Algesten         //     corresponding relayed transport address is still available).  If
399ffe74184SMartin Algesten         //     the token is not valid for some reason, the server rejects the
400ffe74184SMartin Algesten         //     request with a 508 (Insufficient Capacity) error.
401ffe74184SMartin Algesten         let mut reservation_token_attr = ReservationToken::default();
402ffe74184SMartin Algesten         if reservation_token_attr.get_from(m).is_ok() {
403ffe74184SMartin Algesten             let mut even_port = EvenPort::default();
404ffe74184SMartin Algesten             if even_port.get_from(m).is_ok() {
405ffe74184SMartin Algesten                 let bad_request_msg = build_msg(
406ffe74184SMartin Algesten                     m.transaction_id,
407ffe74184SMartin Algesten                     MessageType::new(METHOD_ALLOCATE, CLASS_ERROR_RESPONSE),
408ffe74184SMartin Algesten                     vec![Box::new(ErrorCodeAttribute {
409ffe74184SMartin Algesten                         code: CODE_BAD_REQUEST,
410ffe74184SMartin Algesten                         reason: vec![],
411ffe74184SMartin Algesten                     })],
412ffe74184SMartin Algesten                 )?;
413ffe74184SMartin Algesten                 return build_and_send_err(
414ffe74184SMartin Algesten                     &self.conn,
415ffe74184SMartin Algesten                     self.src_addr,
416ffe74184SMartin Algesten                     bad_request_msg,
417ffe74184SMartin Algesten                     Error::ErrRequestWithReservationTokenAndEvenPort,
418ffe74184SMartin Algesten                 )
419ffe74184SMartin Algesten                 .await;
420ffe74184SMartin Algesten             }
421ffe74184SMartin Algesten         }
422ffe74184SMartin Algesten 
423ffe74184SMartin Algesten         // 6. The server checks if the request contains an EVEN-PORT attribute.
424ffe74184SMartin Algesten         //    If yes, then the server checks that it can satisfy the request
425ffe74184SMartin Algesten         //    (i.e., can allocate a relayed transport address as described
426ffe74184SMartin Algesten         //    below).  If the server cannot satisfy the request, then the
427ffe74184SMartin Algesten         //    server rejects the request with a 508 (Insufficient Capacity)
428ffe74184SMartin Algesten         //    error.
429ffe74184SMartin Algesten         let mut even_port = EvenPort::default();
430ffe74184SMartin Algesten         if even_port.get_from(m).is_ok() {
431ffe74184SMartin Algesten             let mut random_port = 1;
432ffe74184SMartin Algesten 
433ffe74184SMartin Algesten             while random_port % 2 != 0 {
434ffe74184SMartin Algesten                 random_port = match self.allocation_manager.get_random_even_port().await {
435ffe74184SMartin Algesten                     Ok(port) => port,
436ffe74184SMartin Algesten                     Err(err) => {
437ffe74184SMartin Algesten                         let insufficent_capacity_msg = build_msg(
438ffe74184SMartin Algesten                             m.transaction_id,
439ffe74184SMartin Algesten                             MessageType::new(METHOD_ALLOCATE, CLASS_ERROR_RESPONSE),
440ffe74184SMartin Algesten                             vec![Box::new(ErrorCodeAttribute {
441ffe74184SMartin Algesten                                 code: CODE_INSUFFICIENT_CAPACITY,
442ffe74184SMartin Algesten                                 reason: vec![],
443ffe74184SMartin Algesten                             })],
444ffe74184SMartin Algesten                         )?;
445ffe74184SMartin Algesten                         return build_and_send_err(
446ffe74184SMartin Algesten                             &self.conn,
447ffe74184SMartin Algesten                             self.src_addr,
448ffe74184SMartin Algesten                             insufficent_capacity_msg,
449ffe74184SMartin Algesten                             err,
450ffe74184SMartin Algesten                         )
451ffe74184SMartin Algesten                         .await;
452ffe74184SMartin Algesten                     }
453ffe74184SMartin Algesten                 };
454ffe74184SMartin Algesten             }
455ffe74184SMartin Algesten 
456ffe74184SMartin Algesten             requested_port = random_port;
457ffe74184SMartin Algesten             reservation_token = rand_seq(8);
458ffe74184SMartin Algesten         }
459ffe74184SMartin Algesten 
460ffe74184SMartin Algesten         // 7. At any point, the server MAY choose to reject the request with a
461ffe74184SMartin Algesten         //    486 (Allocation Quota Reached) error if it feels the client is
462ffe74184SMartin Algesten         //    trying to exceed some locally defined allocation quota.  The
463ffe74184SMartin Algesten         //    server is free to define this allocation quota any way it wishes,
464ffe74184SMartin Algesten         //    but SHOULD define it based on the username used to authenticate
465ffe74184SMartin Algesten         //    the request, and not on the client's transport address.
466ffe74184SMartin Algesten 
467ffe74184SMartin Algesten         // 8. Also at any point, the server MAY choose to reject the request
468ffe74184SMartin Algesten         //    with a 300 (Try Alternate) error if it wishes to redirect the
469ffe74184SMartin Algesten         //    client to a different server.  The use of this error code and
470ffe74184SMartin Algesten         //    attribute follow the specification in [RFC5389].
471ffe74184SMartin Algesten         let lifetime_duration = allocation_lifetime(m);
472ffe74184SMartin Algesten         let a = match self
473ffe74184SMartin Algesten             .allocation_manager
474ffe74184SMartin Algesten             .create_allocation(
475ffe74184SMartin Algesten                 five_tuple,
476ffe74184SMartin Algesten                 Arc::clone(&self.conn),
477ffe74184SMartin Algesten                 requested_port,
478ffe74184SMartin Algesten                 lifetime_duration,
479c4e6ecf8Slogist322                 username,
480ffe74184SMartin Algesten             )
481ffe74184SMartin Algesten             .await
482ffe74184SMartin Algesten         {
483ffe74184SMartin Algesten             Ok(a) => a,
484ffe74184SMartin Algesten             Err(err) => {
485ffe74184SMartin Algesten                 let insufficent_capacity_msg = build_msg(
486ffe74184SMartin Algesten                     m.transaction_id,
487ffe74184SMartin Algesten                     MessageType::new(METHOD_ALLOCATE, CLASS_ERROR_RESPONSE),
488ffe74184SMartin Algesten                     vec![Box::new(ErrorCodeAttribute {
489ffe74184SMartin Algesten                         code: CODE_INSUFFICIENT_CAPACITY,
490ffe74184SMartin Algesten                         reason: vec![],
491ffe74184SMartin Algesten                     })],
492ffe74184SMartin Algesten                 )?;
493ffe74184SMartin Algesten                 return build_and_send_err(
494ffe74184SMartin Algesten                     &self.conn,
495ffe74184SMartin Algesten                     self.src_addr,
496ffe74184SMartin Algesten                     insufficent_capacity_msg,
497ffe74184SMartin Algesten                     err,
498ffe74184SMartin Algesten                 )
499ffe74184SMartin Algesten                 .await;
500ffe74184SMartin Algesten             }
501ffe74184SMartin Algesten         };
502ffe74184SMartin Algesten 
503ffe74184SMartin Algesten         // Once the allocation is created, the server replies with a success
504ffe74184SMartin Algesten         // response.  The success response contains:
505ffe74184SMartin Algesten         //   * An XOR-RELAYED-ADDRESS attribute containing the relayed transport
506ffe74184SMartin Algesten         //     address.
507ffe74184SMartin Algesten         //   * A LIFETIME attribute containing the current value of the time-to-
508ffe74184SMartin Algesten         //     expiry timer.
509ffe74184SMartin Algesten         //   * A RESERVATION-TOKEN attribute (if a second relayed transport
510ffe74184SMartin Algesten         //     address was reserved).
511ffe74184SMartin Algesten         //   * An XOR-MAPPED-ADDRESS attribute containing the client's IP address
512ffe74184SMartin Algesten         //     and port (from the 5-tuple).
513ffe74184SMartin Algesten 
514ffe74184SMartin Algesten         let (src_ip, src_port) = (self.src_addr.ip(), self.src_addr.port());
515c4e6ecf8Slogist322         let relay_ip = a.relay_addr.ip();
516c4e6ecf8Slogist322         let relay_port = a.relay_addr.port();
517ffe74184SMartin Algesten 
518ffe74184SMartin Algesten         let msg = {
519ffe74184SMartin Algesten             if !reservation_token.is_empty() {
520ffe74184SMartin Algesten                 self.allocation_manager
521ffe74184SMartin Algesten                     .create_reservation(reservation_token.clone(), relay_port)
522ffe74184SMartin Algesten                     .await;
523ffe74184SMartin Algesten             }
524ffe74184SMartin Algesten 
525ffe74184SMartin Algesten             let mut response_attrs: Vec<Box<dyn Setter>> = vec![
526ffe74184SMartin Algesten                 Box::new(RelayedAddress {
527ffe74184SMartin Algesten                     ip: relay_ip,
528ffe74184SMartin Algesten                     port: relay_port,
529ffe74184SMartin Algesten                 }),
530ffe74184SMartin Algesten                 Box::new(Lifetime(lifetime_duration)),
531ffe74184SMartin Algesten                 Box::new(XorMappedAddress {
532ffe74184SMartin Algesten                     ip: src_ip,
533ffe74184SMartin Algesten                     port: src_port,
534ffe74184SMartin Algesten                 }),
535ffe74184SMartin Algesten             ];
536ffe74184SMartin Algesten 
537ffe74184SMartin Algesten             if !reservation_token.is_empty() {
538ffe74184SMartin Algesten                 response_attrs.push(Box::new(ReservationToken(
539ffe74184SMartin Algesten                     reservation_token.as_bytes().to_vec(),
540ffe74184SMartin Algesten                 )));
541ffe74184SMartin Algesten             }
542ffe74184SMartin Algesten 
543ffe74184SMartin Algesten             response_attrs.push(Box::new(message_integrity));
544ffe74184SMartin Algesten             build_msg(
545ffe74184SMartin Algesten                 m.transaction_id,
546ffe74184SMartin Algesten                 MessageType::new(METHOD_ALLOCATE, CLASS_SUCCESS_RESPONSE),
547ffe74184SMartin Algesten                 response_attrs,
548ffe74184SMartin Algesten             )?
549ffe74184SMartin Algesten         };
550ffe74184SMartin Algesten 
551ffe74184SMartin Algesten         build_and_send(&self.conn, self.src_addr, msg).await
552ffe74184SMartin Algesten     }
553ffe74184SMartin Algesten 
handle_refresh_request(&mut self, m: &Message) -> Result<()>554ffe74184SMartin Algesten     pub(crate) async fn handle_refresh_request(&mut self, m: &Message) -> Result<()> {
555ffe74184SMartin Algesten         log::debug!("received RefreshRequest from {}", self.src_addr);
556ffe74184SMartin Algesten 
557c4e6ecf8Slogist322         let (_, message_integrity) =
558ffe74184SMartin Algesten             if let Some(mi) = self.authenticate_request(m, METHOD_REFRESH).await? {
559ffe74184SMartin Algesten                 mi
560ffe74184SMartin Algesten             } else {
561ffe74184SMartin Algesten                 log::debug!("no MessageIntegrity");
562ffe74184SMartin Algesten                 return Ok(());
563ffe74184SMartin Algesten             };
564ffe74184SMartin Algesten 
565ffe74184SMartin Algesten         let lifetime_duration = allocation_lifetime(m);
566ffe74184SMartin Algesten         let five_tuple = FiveTuple {
567ffe74184SMartin Algesten             src_addr: self.src_addr,
568*5b79f08aSalexlapa             dst_addr: self.conn.local_addr()?,
569ffe74184SMartin Algesten             protocol: PROTO_UDP,
570ffe74184SMartin Algesten         };
571ffe74184SMartin Algesten 
572ffe74184SMartin Algesten         if lifetime_duration != Duration::from_secs(0) {
573ffe74184SMartin Algesten             let a = self.allocation_manager.get_allocation(&five_tuple).await;
574ffe74184SMartin Algesten             if let Some(a) = a {
575ffe74184SMartin Algesten                 a.refresh(lifetime_duration).await;
576ffe74184SMartin Algesten             } else {
577ffe74184SMartin Algesten                 return Err(Error::ErrNoAllocationFound);
578ffe74184SMartin Algesten             }
579ffe74184SMartin Algesten         } else {
580ffe74184SMartin Algesten             self.allocation_manager.delete_allocation(&five_tuple).await;
581ffe74184SMartin Algesten         }
582ffe74184SMartin Algesten 
583ffe74184SMartin Algesten         let msg = build_msg(
584ffe74184SMartin Algesten             m.transaction_id,
585ffe74184SMartin Algesten             MessageType::new(METHOD_REFRESH, CLASS_SUCCESS_RESPONSE),
586ffe74184SMartin Algesten             vec![
587ffe74184SMartin Algesten                 Box::new(Lifetime(lifetime_duration)),
588ffe74184SMartin Algesten                 Box::new(message_integrity),
589ffe74184SMartin Algesten             ],
590ffe74184SMartin Algesten         )?;
591ffe74184SMartin Algesten 
592ffe74184SMartin Algesten         build_and_send(&self.conn, self.src_addr, msg).await
593ffe74184SMartin Algesten     }
594ffe74184SMartin Algesten 
handle_create_permission_request(&mut self, m: &Message) -> Result<()>595ffe74184SMartin Algesten     pub(crate) async fn handle_create_permission_request(&mut self, m: &Message) -> Result<()> {
596ffe74184SMartin Algesten         log::debug!("received CreatePermission from {}", self.src_addr);
597ffe74184SMartin Algesten 
598ffe74184SMartin Algesten         let a = self
599ffe74184SMartin Algesten             .allocation_manager
600ffe74184SMartin Algesten             .get_allocation(&FiveTuple {
601ffe74184SMartin Algesten                 src_addr: self.src_addr,
602*5b79f08aSalexlapa                 dst_addr: self.conn.local_addr()?,
603ffe74184SMartin Algesten                 protocol: PROTO_UDP,
604ffe74184SMartin Algesten             })
605ffe74184SMartin Algesten             .await;
606ffe74184SMartin Algesten 
607ffe74184SMartin Algesten         if let Some(a) = a {
608c4e6ecf8Slogist322             let (_, message_integrity) = if let Some(mi) = self
609ffe74184SMartin Algesten                 .authenticate_request(m, METHOD_CREATE_PERMISSION)
610ffe74184SMartin Algesten                 .await?
611ffe74184SMartin Algesten             {
612ffe74184SMartin Algesten                 mi
613ffe74184SMartin Algesten             } else {
614ffe74184SMartin Algesten                 log::debug!("no MessageIntegrity");
615ffe74184SMartin Algesten                 return Ok(());
616ffe74184SMartin Algesten             };
617ffe74184SMartin Algesten             let mut add_count = 0;
618ffe74184SMartin Algesten 
619ffe74184SMartin Algesten             {
620ffe74184SMartin Algesten                 for attr in &m.attributes.0 {
621ffe74184SMartin Algesten                     if attr.typ != ATTR_XOR_PEER_ADDRESS {
622ffe74184SMartin Algesten                         continue;
623ffe74184SMartin Algesten                     }
624ffe74184SMartin Algesten 
625ffe74184SMartin Algesten                     let mut peer_address = PeerAddress::default();
626ffe74184SMartin Algesten                     if peer_address.get_from(m).is_err() {
627ffe74184SMartin Algesten                         add_count = 0;
628ffe74184SMartin Algesten                         break;
629ffe74184SMartin Algesten                     }
630ffe74184SMartin Algesten 
631ffe74184SMartin Algesten                     log::debug!(
632ffe74184SMartin Algesten                         "adding permission for {}",
633ffe74184SMartin Algesten                         format!("{}:{}", peer_address.ip, peer_address.port)
634ffe74184SMartin Algesten                     );
635ffe74184SMartin Algesten 
636ffe74184SMartin Algesten                     a.add_permission(Permission::new(SocketAddr::new(
637ffe74184SMartin Algesten                         peer_address.ip,
638ffe74184SMartin Algesten                         peer_address.port,
639ffe74184SMartin Algesten                     )))
640ffe74184SMartin Algesten                     .await;
641ffe74184SMartin Algesten                     add_count += 1;
642ffe74184SMartin Algesten                 }
643ffe74184SMartin Algesten             }
644ffe74184SMartin Algesten 
645ffe74184SMartin Algesten             let mut resp_class = CLASS_SUCCESS_RESPONSE;
646ffe74184SMartin Algesten             if add_count == 0 {
647ffe74184SMartin Algesten                 resp_class = CLASS_ERROR_RESPONSE;
648ffe74184SMartin Algesten             }
649ffe74184SMartin Algesten 
650ffe74184SMartin Algesten             let msg = build_msg(
651ffe74184SMartin Algesten                 m.transaction_id,
652ffe74184SMartin Algesten                 MessageType::new(METHOD_CREATE_PERMISSION, resp_class),
653ffe74184SMartin Algesten                 vec![Box::new(message_integrity)],
654ffe74184SMartin Algesten             )?;
655ffe74184SMartin Algesten 
656ffe74184SMartin Algesten             build_and_send(&self.conn, self.src_addr, msg).await
657ffe74184SMartin Algesten         } else {
658ffe74184SMartin Algesten             Err(Error::ErrNoAllocationFound)
659ffe74184SMartin Algesten         }
660ffe74184SMartin Algesten     }
661ffe74184SMartin Algesten 
handle_send_indication(&mut self, m: &Message) -> Result<()>662ffe74184SMartin Algesten     pub(crate) async fn handle_send_indication(&mut self, m: &Message) -> Result<()> {
663ffe74184SMartin Algesten         log::debug!("received SendIndication from {}", self.src_addr);
664ffe74184SMartin Algesten 
665ffe74184SMartin Algesten         let a = self
666ffe74184SMartin Algesten             .allocation_manager
667ffe74184SMartin Algesten             .get_allocation(&FiveTuple {
668ffe74184SMartin Algesten                 src_addr: self.src_addr,
669*5b79f08aSalexlapa                 dst_addr: self.conn.local_addr()?,
670ffe74184SMartin Algesten                 protocol: PROTO_UDP,
671ffe74184SMartin Algesten             })
672ffe74184SMartin Algesten             .await;
673ffe74184SMartin Algesten 
674ffe74184SMartin Algesten         if let Some(a) = a {
675ffe74184SMartin Algesten             let mut data_attr = Data::default();
676ffe74184SMartin Algesten             data_attr.get_from(m)?;
677ffe74184SMartin Algesten 
678ffe74184SMartin Algesten             let mut peer_address = PeerAddress::default();
679ffe74184SMartin Algesten             peer_address.get_from(m)?;
680ffe74184SMartin Algesten 
681ffe74184SMartin Algesten             let msg_dst = SocketAddr::new(peer_address.ip, peer_address.port);
682ffe74184SMartin Algesten 
683c4e6ecf8Slogist322             let has_perm = a.has_permission(&msg_dst).await;
684ffe74184SMartin Algesten             if !has_perm {
685ffe74184SMartin Algesten                 return Err(Error::ErrNoPermission);
686ffe74184SMartin Algesten             }
687ffe74184SMartin Algesten 
688ffe74184SMartin Algesten             let l = a.relay_socket.send_to(&data_attr.0, msg_dst).await?;
689ffe74184SMartin Algesten             if l != data_attr.0.len() {
690ffe74184SMartin Algesten                 Err(Error::ErrShortWrite)
691ffe74184SMartin Algesten             } else {
69226682c3dSlogist322                 #[cfg(feature = "metrics")]
69326682c3dSlogist322                 a.relayed_bytes
69426682c3dSlogist322                     .fetch_add(data_attr.0.len(), Ordering::AcqRel);
69526682c3dSlogist322 
696ffe74184SMartin Algesten                 Ok(())
697ffe74184SMartin Algesten             }
698ffe74184SMartin Algesten         } else {
699ffe74184SMartin Algesten             Err(Error::ErrNoAllocationFound)
700ffe74184SMartin Algesten         }
701ffe74184SMartin Algesten     }
702ffe74184SMartin Algesten 
handle_channel_bind_request(&mut self, m: &Message) -> Result<()>703ffe74184SMartin Algesten     pub(crate) async fn handle_channel_bind_request(&mut self, m: &Message) -> Result<()> {
704ffe74184SMartin Algesten         log::debug!("received ChannelBindRequest from {}", self.src_addr);
705ffe74184SMartin Algesten 
706ffe74184SMartin Algesten         let a = self
707ffe74184SMartin Algesten             .allocation_manager
708ffe74184SMartin Algesten             .get_allocation(&FiveTuple {
709ffe74184SMartin Algesten                 src_addr: self.src_addr,
710*5b79f08aSalexlapa                 dst_addr: self.conn.local_addr()?,
711ffe74184SMartin Algesten                 protocol: PROTO_UDP,
712ffe74184SMartin Algesten             })
713ffe74184SMartin Algesten             .await;
714ffe74184SMartin Algesten 
715ffe74184SMartin Algesten         if let Some(a) = a {
716ffe74184SMartin Algesten             let bad_request_msg = build_msg(
717ffe74184SMartin Algesten                 m.transaction_id,
718ffe74184SMartin Algesten                 MessageType::new(METHOD_CHANNEL_BIND, CLASS_ERROR_RESPONSE),
719ffe74184SMartin Algesten                 vec![Box::new(ErrorCodeAttribute {
720ffe74184SMartin Algesten                     code: CODE_BAD_REQUEST,
721ffe74184SMartin Algesten                     reason: vec![],
722ffe74184SMartin Algesten                 })],
723ffe74184SMartin Algesten             )?;
724ffe74184SMartin Algesten 
725c4e6ecf8Slogist322             let (_, message_integrity) =
726ffe74184SMartin Algesten                 if let Some(mi) = self.authenticate_request(m, METHOD_CHANNEL_BIND).await? {
727ffe74184SMartin Algesten                     mi
728ffe74184SMartin Algesten                 } else {
729ffe74184SMartin Algesten                     log::debug!("no MessageIntegrity");
730ffe74184SMartin Algesten                     return Ok(());
731ffe74184SMartin Algesten                 };
732ffe74184SMartin Algesten             let mut channel = ChannelNumber::default();
733ffe74184SMartin Algesten             if let Err(err) = channel.get_from(m) {
734ffe74184SMartin Algesten                 return build_and_send_err(&self.conn, self.src_addr, bad_request_msg, err.into())
735ffe74184SMartin Algesten                     .await;
736ffe74184SMartin Algesten             }
737ffe74184SMartin Algesten 
738ffe74184SMartin Algesten             let mut peer_addr = PeerAddress::default();
739ffe74184SMartin Algesten             if let Err(err) = peer_addr.get_from(m) {
740ffe74184SMartin Algesten                 return build_and_send_err(&self.conn, self.src_addr, bad_request_msg, err.into())
741ffe74184SMartin Algesten                     .await;
742ffe74184SMartin Algesten             }
743ffe74184SMartin Algesten 
744ffe74184SMartin Algesten             log::debug!(
745ffe74184SMartin Algesten                 "binding channel {} to {}",
746ffe74184SMartin Algesten                 channel,
747ffe74184SMartin Algesten                 format!("{}:{}", peer_addr.ip, peer_addr.port)
748ffe74184SMartin Algesten             );
749ffe74184SMartin Algesten 
750ffe74184SMartin Algesten             let result = {
751ffe74184SMartin Algesten                 a.add_channel_bind(
752ffe74184SMartin Algesten                     ChannelBind::new(channel, SocketAddr::new(peer_addr.ip, peer_addr.port)),
753ffe74184SMartin Algesten                     self.channel_bind_timeout,
754ffe74184SMartin Algesten                 )
755ffe74184SMartin Algesten                 .await
756ffe74184SMartin Algesten             };
757ffe74184SMartin Algesten             if let Err(err) = result {
758ffe74184SMartin Algesten                 return build_and_send_err(&self.conn, self.src_addr, bad_request_msg, err).await;
759ffe74184SMartin Algesten             }
760ffe74184SMartin Algesten 
761ffe74184SMartin Algesten             let msg = build_msg(
762ffe74184SMartin Algesten                 m.transaction_id,
763ffe74184SMartin Algesten                 MessageType::new(METHOD_CHANNEL_BIND, CLASS_SUCCESS_RESPONSE),
764ffe74184SMartin Algesten                 vec![Box::new(message_integrity)],
765ffe74184SMartin Algesten             )?;
766ffe74184SMartin Algesten             build_and_send(&self.conn, self.src_addr, msg).await
767ffe74184SMartin Algesten         } else {
768ffe74184SMartin Algesten             Err(Error::ErrNoAllocationFound)
769ffe74184SMartin Algesten         }
770ffe74184SMartin Algesten     }
771ffe74184SMartin Algesten 
handle_channel_data(&mut self, c: &ChannelData) -> Result<()>772ffe74184SMartin Algesten     pub(crate) async fn handle_channel_data(&mut self, c: &ChannelData) -> Result<()> {
773ffe74184SMartin Algesten         log::debug!("received ChannelData from {}", self.src_addr);
774ffe74184SMartin Algesten 
775ffe74184SMartin Algesten         let a = self
776ffe74184SMartin Algesten             .allocation_manager
777ffe74184SMartin Algesten             .get_allocation(&FiveTuple {
778ffe74184SMartin Algesten                 src_addr: self.src_addr,
779*5b79f08aSalexlapa                 dst_addr: self.conn.local_addr()?,
780ffe74184SMartin Algesten                 protocol: PROTO_UDP,
781ffe74184SMartin Algesten             })
782ffe74184SMartin Algesten             .await;
783ffe74184SMartin Algesten 
784ffe74184SMartin Algesten         if let Some(a) = a {
785ffe74184SMartin Algesten             let channel = a.get_channel_addr(&c.number).await;
786ffe74184SMartin Algesten             if let Some(peer) = channel {
787ffe74184SMartin Algesten                 let l = a.relay_socket.send_to(&c.data, peer).await?;
788ffe74184SMartin Algesten                 if l != c.data.len() {
789ffe74184SMartin Algesten                     Err(Error::ErrShortWrite)
790ffe74184SMartin Algesten                 } else {
79126682c3dSlogist322                     #[cfg(feature = "metrics")]
79226682c3dSlogist322                     a.relayed_bytes.fetch_add(c.data.len(), Ordering::AcqRel);
79326682c3dSlogist322 
794ffe74184SMartin Algesten                     Ok(())
795ffe74184SMartin Algesten                 }
796ffe74184SMartin Algesten             } else {
797ffe74184SMartin Algesten                 Err(Error::ErrNoSuchChannelBind)
798ffe74184SMartin Algesten             }
799ffe74184SMartin Algesten         } else {
800ffe74184SMartin Algesten             Err(Error::ErrNoAllocationFound)
801ffe74184SMartin Algesten         }
802ffe74184SMartin Algesten     }
803ffe74184SMartin Algesten }
804ffe74184SMartin Algesten 
rand_seq(n: usize) -> String805ffe74184SMartin Algesten pub(crate) fn rand_seq(n: usize) -> String {
806ffe74184SMartin Algesten     let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".as_bytes();
807ffe74184SMartin Algesten     let mut buf = vec![0u8; n];
808ffe74184SMartin Algesten     for b in &mut buf {
809ffe74184SMartin Algesten         *b = letters[rand::random::<usize>() % letters.len()];
810ffe74184SMartin Algesten     }
811ffe74184SMartin Algesten     if let Ok(s) = String::from_utf8(buf) {
812ffe74184SMartin Algesten         s
813ffe74184SMartin Algesten     } else {
814ffe74184SMartin Algesten         String::new()
815ffe74184SMartin Algesten     }
816ffe74184SMartin Algesten }
817ffe74184SMartin Algesten 
build_nonce() -> Result<String>818ffe74184SMartin Algesten pub(crate) fn build_nonce() -> Result<String> {
819ffe74184SMartin Algesten     /* #nosec */
820ffe74184SMartin Algesten     let mut s = String::new();
821ffe74184SMartin Algesten     s.push_str(
822ffe74184SMartin Algesten         format!(
823ffe74184SMartin Algesten             "{}",
824ffe74184SMartin Algesten             SystemTime::now()
825ffe74184SMartin Algesten                 .duration_since(SystemTime::UNIX_EPOCH)?
826ffe74184SMartin Algesten                 .as_nanos()
827ffe74184SMartin Algesten         )
828ffe74184SMartin Algesten         .as_str(),
829ffe74184SMartin Algesten     );
830ffe74184SMartin Algesten     s.push_str(format!("{}", rand::random::<u64>()).as_str());
831ffe74184SMartin Algesten 
832ffe74184SMartin Algesten     let mut h = Md5::new();
833ffe74184SMartin Algesten     h.update(s.as_bytes());
834ffe74184SMartin Algesten     Ok(format!("{:x}", h.finalize()))
835ffe74184SMartin Algesten }
836ffe74184SMartin Algesten 
build_and_send( conn: &Arc<dyn Conn + Send + Sync>, dst: SocketAddr, msg: Message, ) -> Result<()>837ffe74184SMartin Algesten pub(crate) async fn build_and_send(
838ffe74184SMartin Algesten     conn: &Arc<dyn Conn + Send + Sync>,
839ffe74184SMartin Algesten     dst: SocketAddr,
840ffe74184SMartin Algesten     msg: Message,
841ffe74184SMartin Algesten ) -> Result<()> {
842ffe74184SMartin Algesten     let _ = conn.send_to(&msg.raw, dst).await?;
843ffe74184SMartin Algesten     Ok(())
844ffe74184SMartin Algesten }
845ffe74184SMartin Algesten 
846ffe74184SMartin Algesten // Send a STUN packet and return the original error to the caller
build_and_send_err( conn: &Arc<dyn Conn + Send + Sync>, dst: SocketAddr, msg: Message, err: Error, ) -> Result<()>847ffe74184SMartin Algesten pub(crate) async fn build_and_send_err(
848ffe74184SMartin Algesten     conn: &Arc<dyn Conn + Send + Sync>,
849ffe74184SMartin Algesten     dst: SocketAddr,
850ffe74184SMartin Algesten     msg: Message,
851ffe74184SMartin Algesten     err: Error,
852ffe74184SMartin Algesten ) -> Result<()> {
853c9409ba1SHugo Tunius     build_and_send(conn, dst, msg).await?;
854c9409ba1SHugo Tunius 
855ffe74184SMartin Algesten     Err(err)
856ffe74184SMartin Algesten }
857ffe74184SMartin Algesten 
build_msg( transaction_id: TransactionId, msg_type: MessageType, mut additional: Vec<Box<dyn Setter>>, ) -> Result<Message>858ffe74184SMartin Algesten pub(crate) fn build_msg(
859ffe74184SMartin Algesten     transaction_id: TransactionId,
860ffe74184SMartin Algesten     msg_type: MessageType,
861ffe74184SMartin Algesten     mut additional: Vec<Box<dyn Setter>>,
862ffe74184SMartin Algesten ) -> Result<Message> {
863ffe74184SMartin Algesten     let mut attrs: Vec<Box<dyn Setter>> = vec![
864ffe74184SMartin Algesten         Box::new(Message {
865ffe74184SMartin Algesten             transaction_id,
866ffe74184SMartin Algesten             ..Default::default()
867ffe74184SMartin Algesten         }),
868ffe74184SMartin Algesten         Box::new(msg_type),
869ffe74184SMartin Algesten     ];
870ffe74184SMartin Algesten 
871ffe74184SMartin Algesten     attrs.append(&mut additional);
872ffe74184SMartin Algesten 
873ffe74184SMartin Algesten     let mut msg = Message::new();
874ffe74184SMartin Algesten     msg.build(&attrs)?;
875ffe74184SMartin Algesten     Ok(msg)
876ffe74184SMartin Algesten }
877ffe74184SMartin Algesten 
allocation_lifetime(m: &Message) -> Duration878ffe74184SMartin Algesten pub(crate) fn allocation_lifetime(m: &Message) -> Duration {
879ffe74184SMartin Algesten     let mut lifetime_duration = DEFAULT_LIFETIME;
880ffe74184SMartin Algesten 
881ffe74184SMartin Algesten     let mut lifetime = Lifetime::default();
882ffe74184SMartin Algesten     if lifetime.get_from(m).is_ok() && lifetime.0 < MAXIMUM_ALLOCATION_LIFETIME {
883ffe74184SMartin Algesten         lifetime_duration = lifetime.0;
884ffe74184SMartin Algesten     }
885ffe74184SMartin Algesten 
886ffe74184SMartin Algesten     lifetime_duration
887ffe74184SMartin Algesten }
888