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; 36*26682c3dSlogist322 #[cfg(feature = "metrics")] 37*26682c3dSlogist322 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 { 66ffe74184SMartin 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 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 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 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 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 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 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 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 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, 299ffe74184SMartin Algesten dst_addr: self.conn.local_addr().await?, 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 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, 568ffe74184SMartin Algesten dst_addr: self.conn.local_addr().await?, 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 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, 602ffe74184SMartin Algesten dst_addr: self.conn.local_addr().await?, 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 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, 669ffe74184SMartin Algesten dst_addr: self.conn.local_addr().await?, 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 { 692*26682c3dSlogist322 #[cfg(feature = "metrics")] 693*26682c3dSlogist322 a.relayed_bytes 694*26682c3dSlogist322 .fetch_add(data_attr.0.len(), Ordering::AcqRel); 695*26682c3dSlogist322 696ffe74184SMartin Algesten Ok(()) 697ffe74184SMartin Algesten } 698ffe74184SMartin Algesten } else { 699ffe74184SMartin Algesten Err(Error::ErrNoAllocationFound) 700ffe74184SMartin Algesten } 701ffe74184SMartin Algesten } 702ffe74184SMartin Algesten 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, 710ffe74184SMartin Algesten dst_addr: self.conn.local_addr().await?, 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 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, 779ffe74184SMartin Algesten dst_addr: self.conn.local_addr().await?, 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 { 791*26682c3dSlogist322 #[cfg(feature = "metrics")] 792*26682c3dSlogist322 a.relayed_bytes.fetch_add(c.data.len(), Ordering::AcqRel); 793*26682c3dSlogist322 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 805ffe74184SMartin 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 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 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 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 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 878ffe74184SMartin 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