rtc_turn/client/mod.rs
1//! The Sans-I/O TURN client.
2//!
3//! Using a relay takes three steps: Allocate to obtain a public address, CreatePermission for
4//! each peer you intend to exchange data with, and then Send/Data indications (or a bound channel)
5//! to move bytes. Each step is a STUN transaction, so every [`Event`] carries the
6//! transaction id of the request it answers.
7//!
8//! The three address kinds are easy to confuse: [`RelayedAddr`] is what peers send to,
9//! [`ReflexiveAddr`] is how the server sees this client, and [`PeerAddr`] is the far end.
10#[cfg(test)]
11mod client_test;
12
13/// Channel bindings, which replace the 36-byte Data indication header with a 4-byte one.
14pub mod binding;
15/// Per-peer send permissions, which a relay requires before it will forward to an address.
16pub mod permission;
17mod proto;
18/// A live allocation on the server, and sending or receiving through it.
19pub mod relay;
20/// Outstanding request tracking, with the RFC's retransmission schedule.
21pub mod transaction;
22
23use bytes::BytesMut;
24use crypto::RTCCryptoProvider;
25use log::{debug, trace};
26use std::collections::{HashMap, VecDeque};
27use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
28use std::sync::Arc;
29use std::time::{Duration, Instant};
30
31use stun::attributes::*;
32use stun::integrity::*;
33use stun::message::*;
34use stun::textattrs::*;
35use stun::xoraddr::*;
36
37use binding::*;
38use transaction::*;
39
40use crate::client::relay::{Relay, RelayState};
41use crate::proto::chandata::*;
42use crate::proto::channum::ChannelNumber;
43use crate::proto::data::*;
44use crate::proto::lifetime::Lifetime;
45use crate::proto::peeraddr::*;
46use crate::proto::relayaddr::RelayedAddress;
47use crate::proto::reqtrans::RequestedTransport;
48use crate::proto::{PROTO_TCP, PROTO_UDP};
49use shared::error::{Error, Result};
50use shared::util::lookup_host;
51use shared::{TransportContext, TransportMessage, TransportProtocol};
52use stun::error_code::ErrorCodeAttribute;
53use stun::fingerprint::FINGERPRINT;
54
55const DEFAULT_RTO_IN_MS: u64 = 200;
56const MAX_DATA_BUFFER_SIZE: usize = u16::MAX as usize; // message size limit for Chromium
57const MAX_READ_QUEUE_SIZE: usize = 1024;
58
59/// The public address the TURN server allocated on this client's behalf.
60///
61/// Peers send here; the server forwards to the client.
62pub type RelayedAddr = SocketAddr;
63/// The client's own address as seen by the server — its server-reflexive address.
64pub type ReflexiveAddr = SocketAddr;
65/// The address of a remote peer the client exchanges data with through the relay.
66pub type PeerAddr = SocketAddr;
67
68#[derive(Debug)]
69/// What the client produces in response to inbound datagrams and elapsed time.
70///
71/// Every variant carries the [`TransactionId`] of the request it answers, so a caller can
72/// match responses to the requests it issued.
73#[non_exhaustive]
74pub enum Event {
75 /// A request exhausted its retransmissions without a response.
76 TransactionTimeout(TransactionId),
77
78 /// A STUN Binding succeeded, reporting this client's server-reflexive address.
79 BindingResponse(TransactionId, ReflexiveAddr),
80 /// A STUN Binding failed.
81 BindingError(TransactionId, Error),
82
83 /// An Allocate succeeded; the relayed address is now usable.
84 AllocateResponse(TransactionId, RelayedAddr),
85 /// An Allocate failed — commonly authentication, or the server being out of ports.
86 AllocateError(TransactionId, Error),
87
88 /// A CreatePermission succeeded; the relay will now forward to and from this peer.
89 CreatePermissionResponse(TransactionId, PeerAddr),
90 /// A CreatePermission failed.
91 CreatePermissionError(TransactionId, Error),
92
93 /// Data arrived from a peer through the relay.
94 ///
95 /// The channel number is `Some` when it came as ChannelData and `None` when it came as a
96 /// Data indication.
97 DataIndicationOrChannelData(Option<ChannelNumber>, PeerAddr, BytesMut),
98}
99
100enum AllocateState {
101 Attempting,
102 Requesting(TextAttribute),
103}
104
105// interval [msec]
106// 0: 0 ms +500
107// 1: 500 ms +1000
108// 2: 1500 ms +2000
109// 3: 3500 ms +4000
110// 4: 7500 ms +8000
111// 5: 15500 ms +16000
112// 6: 31500 ms +32000
113// -: 63500 ms failed
114
115/// ClientConfig is a bag of config parameters for Client.
116pub struct ClientConfig {
117 /// The STUN server to use for Binding requests, as `host:port`. May be empty.
118 pub stun_serv_addr: String, // STUN server address (e.g. "stun.abc.com:3478")
119 /// The TURN server to allocate from, as `host:port`.
120 pub turn_serv_addr: String, // TURN server address (e.g. "turn.abc.com:3478")
121 /// The local address the client sends from.
122 pub local_addr: SocketAddr,
123 /// Whether to reach the server over UDP or TCP.
124 pub transport_protocol: TransportProtocol,
125 /// The long-term credential username for the TURN server.
126 pub username: String,
127 /// The long-term credential password.
128 pub password: String,
129 /// The authentication realm, used in the `MESSAGE-INTEGRITY` computation.
130 pub realm: String,
131 /// An optional `SOFTWARE` attribute value, sent for diagnostics.
132 pub software: String,
133 /// The initial retransmission timeout in milliseconds; each retry doubles it.
134 pub rto_in_ms: u64,
135 /// Optional upper bound for the interval between allocation Refresh requests.
136 ///
137 /// By default, allocations are refreshed at half the lifetime advertised by the server.
138 /// A shorter cap can also keep the client-to-server NAT mapping active when an allocation
139 /// waits without carrying application traffic. Values below one second are rounded up.
140 pub allocation_refresh_interval_cap: Option<Duration>,
141}
142
143impl Default for ClientConfig {
144 fn default() -> Self {
145 Self {
146 stun_serv_addr: "".to_string(),
147 turn_serv_addr: "".to_string(),
148 local_addr: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0)),
149 transport_protocol: Default::default(),
150 username: "".to_string(),
151 password: "".to_string(),
152 realm: "".to_string(),
153 software: "".to_string(),
154 rto_in_ms: 0,
155 allocation_refresh_interval_cap: None,
156 }
157 }
158}
159
160/// Client is a STUN client
161pub struct Client {
162 crypto_provider: Arc<dyn RTCCryptoProvider>,
163 stun_serv_addr: Option<SocketAddr>,
164 turn_serv_addr: Option<SocketAddr>,
165 local_addr: SocketAddr,
166 transport_protocol: TransportProtocol,
167 username: Username,
168 password: String,
169 realm: Realm,
170 software: Software,
171 tr_map: TransactionMap,
172 binding_mgr: BindingManager,
173 rto_in_ms: u64,
174 allocation_refresh_interval_cap: Option<Duration>,
175
176 relays: HashMap<RelayedAddr, RelayState>,
177 transmits: VecDeque<TransportMessage<BytesMut>>,
178 events: VecDeque<Event>,
179}
180
181impl Client {
182 /// Returns a new TURN client.
183 ///
184 /// The crypto provider is supplied by the caller; this crate never resolves a default.
185 pub fn new(config: ClientConfig, crypto_provider: Arc<dyn RTCCryptoProvider>) -> Result<Self> {
186 let stun_serv_addr = if config.stun_serv_addr.is_empty() {
187 None
188 } else {
189 Some(lookup_host(
190 config.local_addr.is_ipv4(),
191 config.stun_serv_addr.as_str(),
192 )?)
193 };
194
195 let turn_serv_addr = if config.turn_serv_addr.is_empty() {
196 None
197 } else {
198 Some(lookup_host(
199 config.local_addr.is_ipv4(),
200 config.turn_serv_addr.as_str(),
201 )?)
202 };
203
204 Ok(Client {
205 crypto_provider: crypto_provider.clone(),
206 stun_serv_addr,
207 turn_serv_addr,
208 local_addr: config.local_addr,
209 transport_protocol: config.transport_protocol,
210 username: Username::new(ATTR_USERNAME, config.username),
211 password: config.password,
212 realm: Realm::new(ATTR_REALM, config.realm),
213 software: Software::new(ATTR_SOFTWARE, config.software),
214 tr_map: TransactionMap::new(),
215 binding_mgr: BindingManager::new(),
216 rto_in_ms: if config.rto_in_ms != 0 {
217 config.rto_in_ms
218 } else {
219 DEFAULT_RTO_IN_MS
220 },
221 allocation_refresh_interval_cap: config.allocation_refresh_interval_cap,
222 relays: HashMap::new(),
223 transmits: VecDeque::new(),
224 events: VecDeque::new(),
225 })
226 }
227
228 // handle_inbound handles data received.
229 // This method handles incoming packet demultiplex it by the source address
230 // and the types of the message.
231 // This return Ok(handled or not) and if there was an error.
232 // Caller should check if the packet was handled by this client or not.
233 // If not handled, it is assumed that the packet is application data.
234 // If an error is returned, the caller should discard the packet regardless.
235 fn handle_inbound(&mut self, now: Instant, data: &[u8], from: SocketAddr) -> Result<()> {
236 // +-------------------+-------------------------------+
237 // | Return Values | |
238 // +-------------------+ Meaning / Action |
239 // | handled | error | |
240 // |=========+=========+===============================+
241 // | false | nil | Handle the packet as app data |
242 // |---------+---------+-------------------------------+
243 // | true | nil | Nothing to do |
244 // |---------+---------+-------------------------------+
245 // | false | error | (shouldn't happen) |
246 // |---------+---------+-------------------------------+
247 // | true | error | Error occurred while handling |
248 // +---------+---------+-------------------------------+
249 // Possible causes of the error:
250 // - Malformed packet (parse error)
251 // - STUN message was a request
252 // - Non-STUN message from the STUN server
253
254 if is_stun_message(data) {
255 self.handle_stun_message(now, data)
256 } else if ChannelData::is_channel_data(data) {
257 self.handle_channel_data(data)
258 } else if self.stun_serv_addr.is_some() && &from == self.stun_serv_addr.as_ref().unwrap() {
259 // received from STUN server, but it is not a STUN message
260 Err(Error::ErrNonStunmessage)
261 } else {
262 // assume, this is an application data
263 trace!("non-STUN/TURN packet, unhandled");
264 Ok(())
265 }
266 }
267
268 fn handle_stun_message(&mut self, now: Instant, data: &[u8]) -> Result<()> {
269 let mut msg = Message::new();
270 msg.raw = data.to_vec();
271 msg.decode()?;
272
273 if msg.typ.class == CLASS_REQUEST {
274 return Err(Error::Other(format!(
275 "{:?} : {}",
276 Error::ErrUnexpectedStunrequestMessage,
277 msg
278 )));
279 }
280
281 if msg.typ.class == CLASS_INDICATION {
282 if msg.typ.method == METHOD_DATA {
283 let mut peer_addr = PeerAddress::default();
284 peer_addr.get_from(&msg)?;
285 let from = SocketAddr::new(peer_addr.ip, peer_addr.port);
286
287 let mut data = Data::default();
288 data.get_from(&msg)?;
289
290 debug!("data indication received from {}", from);
291
292 self.events.push_back(Event::DataIndicationOrChannelData(
293 None,
294 from,
295 BytesMut::from(&data.0[..]),
296 ))
297 }
298
299 return Ok(());
300 }
301
302 // This is a STUN response message (transactional)
303 // The type is either:
304 // - stun.ClassSuccessResponse
305 // - stun.ClassErrorResponse
306
307 if self.tr_map.find(&msg.transaction_id).is_none() {
308 // silently discard
309 debug!("no transaction for {}", msg);
310 return Ok(());
311 }
312
313 if let Some(tr) = self.tr_map.delete(&msg.transaction_id) {
314 match msg.typ.method {
315 METHOD_BINDING => {
316 if msg.typ.class == CLASS_ERROR_RESPONSE {
317 let mut code = ErrorCodeAttribute::default();
318 let err = if code.get_from(&msg).is_err() {
319 Error::Other(format!("{}", msg.typ))
320 } else {
321 Error::Other(format!("{} (error {})", msg.typ, code))
322 };
323 self.events
324 .push_back(Event::BindingError(tr.transaction_id, err));
325 } else {
326 let mut refl_addr = XorMappedAddress::default();
327 match refl_addr.get_from(&msg) {
328 Ok(_) => {
329 self.events.push_back(Event::BindingResponse(
330 tr.transaction_id,
331 ReflexiveAddr::new(refl_addr.ip, refl_addr.port),
332 ));
333 }
334 Err(err) => {
335 self.events
336 .push_back(Event::BindingError(tr.transaction_id, err));
337 }
338 }
339 }
340 }
341 METHOD_ALLOCATE => {
342 self.handle_allocate_response(now, msg, tr.transaction_type)?;
343 }
344 METHOD_CREATE_PERMISSION => {
345 if let TransactionType::CreatePermissionRequest(relayed_addr, peer_addr) =
346 tr.transaction_type
347 {
348 let mut relay = Relay {
349 relayed_addr,
350 client: self,
351 };
352 relay.handle_create_permission_response(msg, peer_addr)?;
353 }
354 }
355 METHOD_REFRESH => {
356 if let TransactionType::RefreshRequest(relayed_addr) = tr.transaction_type {
357 let mut relay = Relay {
358 relayed_addr,
359 client: self,
360 };
361 relay.handle_refresh_allocation_response(now, msg)?;
362 }
363 }
364 METHOD_CHANNEL_BIND => {
365 if let TransactionType::ChannelBindRequest(relayed_addr, bind_addr) =
366 tr.transaction_type
367 {
368 let mut relay = Relay {
369 relayed_addr,
370 client: self,
371 };
372 relay.handle_channel_bind_response(now, msg, bind_addr)?;
373 }
374 }
375 _ => {}
376 }
377 }
378
379 Ok(())
380 }
381
382 fn handle_channel_data(&mut self, data: &[u8]) -> Result<()> {
383 let mut ch_data = ChannelData {
384 raw: data.to_vec(),
385 ..Default::default()
386 };
387 ch_data.decode()?;
388
389 let addr = self
390 .find_addr_by_channel_number(ch_data.number.0)
391 .ok_or(Error::ErrChannelBindNotFound)?;
392
393 trace!(
394 "channel data received from {} (ch={})",
395 addr, ch_data.number.0
396 );
397
398 self.events.push_back(Event::DataIndicationOrChannelData(
399 Some(ch_data.number),
400 addr,
401 BytesMut::from(&ch_data.data[..]),
402 ));
403
404 Ok(())
405 }
406
407 /// Borrows the allocation for `relayed_addr` so data can be sent or permissions created.
408 ///
409 /// # Errors
410 ///
411 /// Fails if this client has no allocation for that address — it was never allocated, or has
412 /// already been closed.
413 pub fn relay(&mut self, relayed_addr: SocketAddr) -> Result<Relay<'_>> {
414 if !self.relays.contains_key(&relayed_addr) {
415 Err(Error::ErrStreamNotExisted)
416 } else {
417 Ok(Relay {
418 relayed_addr,
419 client: self,
420 })
421 }
422 }
423
424 /// Whether this client is waiting on a response for transaction `id`.
425 ///
426 /// A STUN response belongs to whoever sent the matching request — [RFC 5389 §7.3.3] matches
427 /// them by transaction ID, and nothing else identifies the owner. That is only a question
428 /// worth asking when several STUN users share one socket, which is exactly the situation a
429 /// host is in when it points a STUN gatherer and this client at the same server address: both
430 /// see every response, and the four-tuple is identical for both, so addresses cannot say whose
431 /// a response is.
432 ///
433 /// Such a host calls this to route a response, rather than guessing from the peer address and
434 /// handing it to a client that will silently discard it — [`handle_read`](Self::handle_read)
435 /// drops a response with no matching transaction, as it must.
436 ///
437 /// Applies to responses only. TURN ChannelData carries no transaction ID at all, and
438 /// indications are not transaction-matched; both are routed by address.
439 ///
440 /// [RFC 5389 §7.3.3]: https://www.rfc-editor.org/rfc/rfc5389#section-7.3.3
441 #[must_use]
442 pub fn has_transaction(&self, id: &TransactionId) -> bool {
443 self.tr_map.find(id).is_some()
444 }
445
446 /// send_binding_request_to sends a new STUN request to the given transport address
447 /// return key to find out corresponding Event either BindingResponse or BindingRequestTimeout
448 pub fn send_binding_request_to(
449 &mut self,
450 now: Instant,
451 to: SocketAddr,
452 ) -> Result<TransactionId> {
453 let msg = {
454 let attrs: Vec<Box<dyn Setter + '_>> = if !self.software.text.is_empty() {
455 vec![
456 Box::new(TransactionId::new()),
457 Box::new(BINDING_REQUEST),
458 Box::new(self.software.clone()),
459 ]
460 } else {
461 vec![Box::new(TransactionId::new()), Box::new(BINDING_REQUEST)]
462 };
463
464 let mut msg = Message::new();
465 msg.build(&attrs)?;
466 msg
467 };
468
469 debug!("client.SendBindingRequestTo call PerformTransaction 1");
470 Ok(self.perform_transaction(now, &msg, to, TransactionType::BindingRequest))
471 }
472
473 /// send_binding_request sends a new STUN request to the STUN server
474 /// return key to find out corresponding Event either BindingResponse or BindingRequestTimeout
475 pub fn send_binding_request(&mut self, now: Instant) -> Result<TransactionId> {
476 if let Some(stun_serv_addr) = &self.stun_serv_addr {
477 self.send_binding_request_to(now, *stun_serv_addr)
478 } else {
479 Err(Error::ErrStunserverAddressNotSet)
480 }
481 }
482
483 // find_addr_by_channel_number returns a peer address associated with the
484 // channel number on this UDPConn
485 fn find_addr_by_channel_number(&self, ch_num: u16) -> Option<SocketAddr> {
486 self.binding_mgr.find_by_number(ch_num).map(|b| b.addr)
487 }
488
489 // stun_server_addr return the STUN server address
490 fn stun_server_addr(&self) -> Option<SocketAddr> {
491 self.stun_serv_addr
492 }
493
494 /* https://datatracker.ietf.org/doc/html/rfc8656#section-20
495 TURN TURN Peer Peer
496 client server A B
497 | | | |
498 |--- Allocate request -------------->| | |
499 | Transaction-Id=0xA56250D3F17ABE679422DE85 | |
500 | SOFTWARE="Example client, version 1.03" | |
501 | LIFETIME=3600 (1 hour) | | |
502 | REQUESTED-TRANSPORT=17 (UDP) | | |
503 | DONT-FRAGMENT | | |
504 | | | |
505 |<-- Allocate error response --------| | |
506 | Transaction-Id=0xA56250D3F17ABE679422DE85 | |
507 | SOFTWARE="Example server, version 1.17" | |
508 | ERROR-CODE=401 (Unauthorized) | | |
509 | REALM="example.com" | | |
510 | NONCE="obMatJos2gAAAadl7W7PeDU4hKE72jda" | |
511 | PASSWORD-ALGORITHMS=MD5 and SHA256 | |
512 | | | |
513 |--- Allocate request -------------->| | |
514 | Transaction-Id=0xC271E932AD7446A32C234492 | |
515 | SOFTWARE="Example client 1.03" | | |
516 | LIFETIME=3600 (1 hour) | | |
517 | REQUESTED-TRANSPORT=17 (UDP) | | |
518 | DONT-FRAGMENT | | |
519 | USERNAME="George" | | |
520 | REALM="example.com" | | |
521 | NONCE="obMatJos2gAAAadl7W7PeDU4hKE72jda" | |
522 | PASSWORD-ALGORITHMS=MD5 and SHA256 | |
523 | PASSWORD-ALGORITHM=SHA256 | | |
524 | MESSAGE-INTEGRITY=... | | |
525 | MESSAGE-INTEGRITY-SHA256=... | | |
526 | | | |
527 |<-- Allocate success response ------| | |
528 | Transaction-Id=0xC271E932AD7446A32C234492 | |
529 | SOFTWARE="Example server, version 1.17" | |
530 | LIFETIME=1200 (20 minutes) | | |
531 | XOR-RELAYED-ADDRESS=192.0.2.15:50000 | |
532 | XOR-MAPPED-ADDRESS=192.0.2.1:7000 | |
533 | MESSAGE-INTEGRITY-SHA256=... | | |
534 */
535 /// Replaces the long-term credential used to sign subsequent requests, **keeping any
536 /// existing allocation**.
537 ///
538 /// A TURN allocation is a property of the 5-tuple, not of the credential that created
539 /// it: [RFC 5766 §6.2] identifies an allocation by 5-tuple, and a server's
540 /// `Refresh` handling looks it up the same way. So when credentials are rotated on the
541 /// same server there is no need to give up the allocation and re-`Allocate` — which
542 /// would in fact be rejected with **437 (Allocation Mismatch)**, since the server still
543 /// holds the previous allocation for that 5-tuple. Re-signing the existing allocation is
544 /// both correct and seamless: permissions and channel bindings survive.
545 ///
546 /// The realm is *not* re-negotiated. It was learned from the server's 401 during the
547 /// first `Allocate`, and a credential rotation keeps the same server, so it still
548 /// applies. Follow this with [`Self::refresh_allocations`] so the server sees the new
549 /// credential before the allocation would otherwise expire.
550 ///
551 /// [RFC 5766 §6.2]: https://datatracker.ietf.org/doc/html/rfc5766#section-6.2
552 pub fn update_credentials(&mut self, username: String, password: String) -> Result<()> {
553 let username = Username::new(ATTR_USERNAME, username);
554 let long_term_integrity_key = MessageIntegrity::long_term_integrity_key(
555 username.text.clone(),
556 self.realm.text.clone(),
557 password.clone(),
558 self.crypto_provider.crypto(),
559 )?;
560 self.username = username;
561 self.password = password;
562
563 // Each allocation carries the integrity it will sign its own Refresh /
564 // CreatePermission / ChannelBind with, so they have to be re-signed too — otherwise
565 // the next refresh would still present the retired credential.
566 for relay in self.relays.values_mut() {
567 relay.long_term_integrity_key = long_term_integrity_key.clone();
568 }
569
570 Ok(())
571 }
572
573 /// Refreshes every live allocation, re-signing each with the current credential.
574 ///
575 /// Each allocation is refreshed with its own current lifetime, so this extends rather
576 /// than changes it. Intended to follow [`update_credentials`](Self::update_credentials).
577 pub fn refresh_allocations(&mut self, now: Instant) -> Result<()> {
578 let relays: Vec<(RelayedAddr, Duration)> = self
579 .relays
580 .iter()
581 .map(|(addr, relay)| (*addr, relay.lifetime))
582 .collect();
583
584 for (relayed_addr, lifetime) in relays {
585 self.relay(relayed_addr)?
586 .refresh_allocation(now, lifetime)?;
587 }
588
589 Ok(())
590 }
591
592 /// Allocate sends a TURN allocation request to the given transport address
593 pub fn allocate(&mut self, now: Instant) -> Result<TransactionId> {
594 let mut msg = Message::new();
595 msg.build(&[
596 Box::new(TransactionId::new()),
597 Box::new(MessageType::new(METHOD_ALLOCATE, CLASS_REQUEST)),
598 Box::new(RequestedTransport {
599 protocol: if self.transport_protocol == TransportProtocol::UDP {
600 PROTO_UDP
601 } else {
602 PROTO_TCP
603 },
604 }),
605 Box::new(FINGERPRINT),
606 ])?;
607
608 debug!("client.Allocate call PerformTransaction 1");
609 let mut tid = self.perform_transaction(
610 now,
611 &msg,
612 self.turn_server_addr()?,
613 TransactionType::AllocateAttempt,
614 );
615 tid.0[TRANSACTION_ID_SIZE - 1] = tid.0[TRANSACTION_ID_SIZE - 1].wrapping_add(1);
616 Ok(tid)
617 }
618
619 fn handle_allocate_response(
620 &mut self,
621 now: Instant,
622 response: Message,
623 allocate_state: TransactionType,
624 ) -> Result<()> {
625 match allocate_state {
626 TransactionType::AllocateAttempt => {
627 // Anonymous allocate failed, trying to authenticate.
628 let nonce = match Nonce::get_from_as(&response, ATTR_NONCE) {
629 Ok(nonce) => nonce,
630 Err(err) => {
631 self.events
632 .push_back(Event::AllocateError(response.transaction_id, err));
633 return Ok(());
634 }
635 };
636 self.realm = match Realm::get_from_as(&response, ATTR_REALM) {
637 Ok(realm) => realm,
638 Err(err) => {
639 self.events
640 .push_back(Event::AllocateError(response.transaction_id, err));
641 return Ok(());
642 }
643 };
644
645 let integrity = MessageIntegrity::new_long_term_integrity_with_provider(
646 self.username.text.clone(),
647 self.realm.text.clone(),
648 self.password.clone(),
649 self.crypto_provider.crypto(),
650 )?;
651
652 let mut msg = Message::new();
653
654 // make it same as allocate() return value so that client can retrieve it
655 // from Event::AllocateResponse
656 let mut tid = response.transaction_id;
657 tid.0[TRANSACTION_ID_SIZE - 1] = tid.0[TRANSACTION_ID_SIZE - 1].wrapping_add(1);
658
659 // Trying to authorize.
660 msg.build(&[
661 Box::new(tid),
662 Box::new(MessageType::new(METHOD_ALLOCATE, CLASS_REQUEST)),
663 Box::new(RequestedTransport {
664 protocol: if self.transport_protocol == TransportProtocol::UDP {
665 PROTO_UDP
666 } else {
667 PROTO_TCP
668 },
669 }),
670 Box::new(self.username.clone()),
671 Box::new(self.realm.clone()),
672 Box::new(nonce.clone()),
673 Box::new(integrity),
674 Box::new(FINGERPRINT),
675 ])?;
676
677 debug!("client.Allocate call PerformTransaction 2");
678 self.perform_transaction(
679 now,
680 &msg,
681 self.turn_server_addr()?,
682 TransactionType::AllocateRequest(nonce),
683 );
684 }
685 TransactionType::AllocateRequest(nonce) => {
686 if response.typ.class == CLASS_ERROR_RESPONSE {
687 let mut code = ErrorCodeAttribute::default();
688 let err = if code.get_from(&response).is_err() {
689 Error::Other(format!("{}", response.typ))
690 } else {
691 Error::Other(format!("{} (error {})", response.typ, code))
692 };
693 self.events
694 .push_back(Event::AllocateError(response.transaction_id, err));
695 return Ok(());
696 }
697
698 // Getting relayed addresses from response.
699 let mut relayed = RelayedAddress::default();
700 relayed.get_from(&response)?;
701 let relayed_addr = RelayedAddr::new(relayed.ip, relayed.port);
702
703 // Getting lifetime from response
704 let mut lifetime = Lifetime::default();
705 lifetime.get_from(&response)?;
706
707 // A zero lifetime here is a protocol violation, not a degenerate allocation.
708 // RFC 5766 §6.2 has the server take `min(client proposed, server maximum)` and
709 // fall back to the *default* lifetime (600 s) whenever that computation does
710 // not exceed it — so the value returned by a successful Allocate is never
711 // below the default, and certainly never zero. Zero is meaningful only on the
712 // Refresh path (§7), where it means "allocation deleted".
713 //
714 // Accepting it would build a `RelayState` whose `refresh_alloc_timer` is
715 // `now.add(0)` — expired the instant it is created — for an allocation that is
716 // already gone. That relay then reports an expired refresh deadline forever,
717 // which is what a caller polling deadlines hot-loops on. See
718 // [webrtc#862](https://github.com/webrtc-rs/webrtc/issues/862).
719 if lifetime.0.is_zero() {
720 self.events.push_back(Event::AllocateError(
721 response.transaction_id,
722 Error::Other(
723 "Allocate success response carried LIFETIME=0; RFC 5766 §6.2 \
724 requires at least the default lifetime"
725 .to_owned(),
726 ),
727 ));
728 return Ok(());
729 }
730
731 self.relays.insert(
732 relayed_addr,
733 RelayState::new(
734 now,
735 relayed_addr,
736 MessageIntegrity::long_term_integrity_key(
737 self.username.text.clone(),
738 self.realm.text.clone(),
739 self.password.clone(),
740 self.crypto_provider.crypto(),
741 )?,
742 nonce,
743 lifetime.0,
744 self.allocation_refresh_interval_cap,
745 ),
746 );
747 self.events.push_back(Event::AllocateResponse(
748 response.transaction_id,
749 relayed_addr,
750 ));
751 }
752 _ => {}
753 }
754 Ok(())
755 }
756
757 /// turn_server_addr return the TURN server address
758 fn turn_server_addr(&self) -> Result<SocketAddr> {
759 self.turn_serv_addr.ok_or(Error::ErrNilTurnSocket)
760 }
761
762 /// username returns username
763 fn username(&self) -> Username {
764 self.username.clone()
765 }
766
767 /// realm return realm
768 fn realm(&self) -> Realm {
769 self.realm.clone()
770 }
771
772 /// WriteTo sends data to the specified destination using the base socket.
773 fn write_to(&mut self, now: Instant, data: &[u8], remote: SocketAddr) {
774 self.transmits.push_back(TransportMessage {
775 now,
776 transport: TransportContext {
777 local_addr: self.local_addr,
778 peer_addr: remote,
779 transport_protocol: self.transport_protocol,
780 ecn: None,
781 },
782 message: BytesMut::from(data),
783 });
784 }
785
786 // PerformTransaction performs STUN transaction
787 fn perform_transaction(
788 &mut self,
789 now: Instant,
790 msg: &Message,
791 to: SocketAddr,
792 transaction_type: TransactionType,
793 ) -> TransactionId {
794 let tr = Transaction::new(TransactionConfig {
795 now,
796 transaction_id: msg.transaction_id,
797 transaction_type,
798 raw: BytesMut::from(&msg.raw[..]),
799 local_addr: self.local_addr,
800 peer_addr: to,
801 transport_protocol: self.transport_protocol,
802 interval: self.rto_in_ms,
803 });
804
805 trace!(
806 "start {} transaction {:?} to {}",
807 msg.typ, msg.transaction_id, tr.peer_addr
808 );
809 self.tr_map.insert(msg.transaction_id, tr);
810
811 self.write_to(now, &msg.raw, to);
812
813 msg.transaction_id
814 }
815}