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