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