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