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