Skip to main content

turn_client_proto/
api.rs

1// Copyright (C) 2025 Matthew Waters <matthew@centricular.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8//
9// SPDX-License-Identifier: MIT OR Apache-2.0
10
11//! TURN client API.
12//!
13//! Provides a consistent interface between multiple implementations of TURN clients for different
14//! transports (TCP, and UDP) and wrappers (TLS).
15
16use alloc::vec::Vec;
17use core::net::{IpAddr, SocketAddr};
18use core::ops::Range;
19use core::time::Duration;
20use stun_proto::agent::StunAgentBuilder;
21use stun_proto::auth::Feature;
22use turn_types::prelude::DelayedTransmitBuild;
23use turn_types::stun::message::IntegrityAlgorithm;
24pub use turn_types::transmit::TransmitBuild;
25use turn_types::transmit::{DelayedChannel, DelayedMessage};
26
27pub use stun_proto::agent::Transmit;
28pub use stun_proto::types::data::Data;
29use stun_proto::types::TransportType;
30use stun_proto::Instant;
31use turn_types::{AddressFamily, TurnCredentials};
32
33/// The public API of a TURN client.
34pub trait TurnClientApi: core::fmt::Debug + Send {
35    /// The transport of the connection to the TURN server.
36    fn transport(&self) -> TransportType;
37
38    /// The local address of this TURN client.
39    fn local_addr(&self) -> SocketAddr;
40
41    /// The remote TURN server's address.
42    fn remote_addr(&self) -> SocketAddr;
43
44    /// The list of allocated relayed addresses on the TURN server.
45    fn relayed_addresses(&self) -> impl Iterator<Item = (TransportType, SocketAddr)> + '_;
46
47    /// The list of permissions available for the provided relayed address.
48    fn permissions(
49        &self,
50        transport: TransportType,
51        relayed: SocketAddr,
52    ) -> impl Iterator<Item = IpAddr> + '_;
53
54    /// Remove the allocation/s on the server.
55    fn delete(&mut self, now: Instant) -> Result<(), DeleteError>;
56
57    /// Create a permission address to allow sending/receiving data to/from.
58    fn create_permission(
59        &mut self,
60        transport: TransportType,
61        peer_addr: IpAddr,
62        now: Instant,
63    ) -> Result<(), CreatePermissionError>;
64
65    /// Whether the client currently has a permission installed for the provided transport and
66    /// address.
67    fn have_permission(&self, transport: TransportType, to: IpAddr) -> bool;
68
69    /// Bind a channel for sending/receiving data to/from a particular peer.
70    fn bind_channel(
71        &mut self,
72        transport: TransportType,
73        peer_addr: SocketAddr,
74        now: Instant,
75    ) -> Result<(), BindChannelError>;
76
77    /// Attempt to connect to a peer from the TURN server using TCP.
78    ///
79    /// Requires that a TCP allocation has been allocated on the TURN server.
80    fn tcp_connect(&mut self, peer_addr: SocketAddr, now: Instant) -> Result<(), TcpConnectError>;
81
82    /// Indicate success (or failure) to create a socket for the specified server and peer address.
83    ///
84    /// The values @id, @five_tuple, and @peer_addr must match the values provided in matching the
85    /// [`TurnPollRet::AllocateTcpSocket`].
86    fn allocated_tcp_socket(
87        &mut self,
88        id: u32,
89        five_tuple: Socket5Tuple,
90        peer_addr: SocketAddr,
91        local_addr: Option<SocketAddr>,
92        now: Instant,
93    ) -> Result<(), TcpAllocateError>;
94
95    /// Indicate that the TCP connection has been closed.
96    fn tcp_closed(&mut self, local_addr: SocketAddr, remote_addr: SocketAddr, now: Instant);
97
98    /// Send data to a peer through the TURN server.
99    ///
100    /// The provided transport, address and data are the data to send to the peer.
101    ///
102    /// The returned value may instruct the caller to send a message to the turn server.
103    fn send_to<T: AsRef<[u8]> + core::fmt::Debug>(
104        &mut self,
105        transport: TransportType,
106        to: SocketAddr,
107        data: T,
108        now: Instant,
109    ) -> Result<Option<TransmitBuild<DelayedMessageOrChannelSend<T>>>, SendError>;
110
111    /// Provide received data to the TURN client for handling.
112    ///
113    /// The return value outlines what to do with this data.
114    fn recv<T: AsRef<[u8]> + core::fmt::Debug>(
115        &mut self,
116        transmit: Transmit<T>,
117        now: Instant,
118    ) -> TurnRecvRet<T>;
119
120    /// Poll the client for any further received data.
121    fn poll_recv(&mut self, now: Instant) -> Option<TurnPeerData<Vec<u8>>>;
122
123    /// Poll the client for further progress.
124    fn poll(&mut self, now: Instant) -> TurnPollRet;
125
126    /// Poll for a packet to send.
127    fn poll_transmit(&mut self, now: Instant) -> Option<Transmit<Data<'static>>>;
128
129    /// Poll for an event that has occurred.
130    fn poll_event(&mut self) -> Option<TurnEvent>;
131
132    /// A higher layer has encountered an error and this client is no longer usable.
133    fn protocol_error(&mut self);
134}
135
136/// Configuration structure for handling TURN client configuration.
137///
138/// Holds the following information:
139///   - Long term credentials for connecting to a TURN server.
140///   - The [`TransportType`] of the requested allocation.
141///   - A list of [`AddressFamily`]s the allocation should be attempted to be created with.
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub struct TurnConfig {
144    allocation_transport: TransportType,
145    address_families: smallvec::SmallVec<[AddressFamily; 2]>,
146    credentials: TurnCredentials,
147    supported_integrity: smallvec::SmallVec<[IntegrityAlgorithm; 2]>,
148    anonymous_username: Feature,
149    rto: Option<RequestRto>,
150}
151
152#[derive(Debug, Clone, PartialEq, Eq)]
153pub(crate) struct RequestRto {
154    initial: Duration,
155    max: Duration,
156    retransmits: u32,
157    final_retransmit_timeout: Duration,
158}
159
160impl RequestRto {}
161
162impl TurnConfig {
163    /// Construct a new [`TurnConfig`] with the provided credentials.
164    ///
165    /// By default a IPV4/UDP allocation is requested.
166    ///
167    /// # Examples
168    ///
169    /// ```
170    /// # use turn_client_proto::api::TurnConfig;
171    /// # use turn_types::{AddressFamily, TransportType, TurnCredentials};
172    /// let credentials = TurnCredentials::new("user", "pass");
173    /// let config = TurnConfig::new(credentials.clone());
174    /// assert_eq!(config.credentials(), &credentials);
175    /// assert_eq!(config.allocation_transport(), TransportType::Udp);
176    /// assert_eq!(config.address_families(), &[AddressFamily::IPV4]);
177    /// ```
178    pub fn new(credentials: TurnCredentials) -> Self {
179        Self {
180            allocation_transport: TransportType::Udp,
181            address_families: smallvec::smallvec![AddressFamily::IPV4],
182            credentials,
183            supported_integrity: smallvec::smallvec![IntegrityAlgorithm::Sha1],
184            anonymous_username: Feature::Auto,
185            rto: None,
186        }
187    }
188
189    /// Set the allocation transport requested.
190    ///
191    /// # Examples
192    ///
193    /// ```
194    /// # use turn_client_proto::api::TurnConfig;
195    /// # use turn_types::{TransportType, TurnCredentials};
196    /// let credentials = TurnCredentials::new("user", "pass");
197    /// let mut config = TurnConfig::new(credentials.clone());
198    /// config.set_allocation_transport(TransportType::Tcp);
199    /// assert_eq!(config.allocation_transport(), TransportType::Tcp);
200    /// ```
201    pub fn set_allocation_transport(&mut self, allocation_transport: TransportType) {
202        self.allocation_transport = allocation_transport;
203    }
204
205    /// Retrieve the allocation transport requested.
206    pub fn allocation_transport(&self) -> TransportType {
207        self.allocation_transport
208    }
209
210    /// Add an [`AddressFamily`] that will be requested.
211    ///
212    /// Duplicate [`AddressFamily`]s are ignored.
213    ///
214    /// # Examples
215    ///
216    /// ```
217    /// # use turn_client_proto::api::TurnConfig;
218    /// # use turn_types::{AddressFamily, TurnCredentials};
219    /// let credentials = TurnCredentials::new("user", "pass");
220    /// let mut config = TurnConfig::new(credentials.clone());
221    /// assert_eq!(config.address_families(), &[AddressFamily::IPV4]);
222    /// // Duplicate AddressFamily is ignored.
223    /// config.add_address_family(AddressFamily::IPV4);
224    /// assert_eq!(config.address_families(), &[AddressFamily::IPV4]);
225    /// config.add_address_family(AddressFamily::IPV6);
226    /// assert_eq!(config.address_families(), &[AddressFamily::IPV4, AddressFamily::IPV6]);
227    /// ```
228    pub fn add_address_family(&mut self, family: AddressFamily) {
229        if !self.address_families.contains(&family) {
230            self.address_families.push(family);
231        }
232    }
233
234    /// Set the [`AddressFamily`] that will be requested.
235    ///
236    /// # Examples
237    ///
238    /// ```
239    /// # use turn_client_proto::api::TurnConfig;
240    /// # use turn_types::{AddressFamily, TurnCredentials};
241    /// let credentials = TurnCredentials::new("user", "pass");
242    /// let mut config = TurnConfig::new(credentials.clone());
243    /// assert_eq!(config.address_families(), &[AddressFamily::IPV4]);
244    /// config.set_address_family(AddressFamily::IPV4);
245    /// assert_eq!(config.address_families(), &[AddressFamily::IPV4]);
246    /// config.set_address_family(AddressFamily::IPV6);
247    /// assert_eq!(config.address_families(), &[AddressFamily::IPV6]);
248    /// ```
249    pub fn set_address_family(&mut self, family: AddressFamily) {
250        self.address_families = smallvec::smallvec![family];
251    }
252
253    /// Retrieve the [`AddressFamily`]s that are requested.
254    pub fn address_families(&self) -> &[AddressFamily] {
255        &self.address_families
256    }
257
258    /// Retrieve the [`TurnCredentials`] used for authenticating with the TURN server.
259    pub fn credentials(&self) -> &TurnCredentials {
260        &self.credentials
261    }
262
263    /// Add a supported integrity algorithm that could be used.
264    pub fn add_supported_integrity(&mut self, integrity: IntegrityAlgorithm) {
265        if !self.supported_integrity.contains(&integrity) {
266            self.supported_integrity.push(integrity);
267        }
268    }
269
270    /// Set the supported integrity algorithm used.
271    pub fn set_supported_integrity(&mut self, integrity: IntegrityAlgorithm) {
272        self.supported_integrity = smallvec::smallvec![integrity];
273    }
274
275    /// The supported integrity algorithms used.
276    pub fn supported_integrity(&self) -> &[IntegrityAlgorithm] {
277        &self.supported_integrity
278    }
279
280    /// Set whether anonymous username usage is required.
281    ///
282    /// A value of `Required` requires the server to support RFC 8489 and the
283    /// [`Userhash`](stun_proto::types::attribute::Userhash) attribute.
284    pub fn set_anonymous_username(&mut self, anon: Feature) {
285        self.anonymous_username = anon;
286    }
287
288    /// Whether anonymous username usage is required.
289    ///
290    /// A value of `Required` requires the server to support RFC 8489 and the
291    /// [`Userhash`](stun_proto::types::attribute::Userhash) attribute.
292    pub fn anonymous_username(&self) -> Feature {
293        self.anonymous_username
294    }
295
296    /// Configure the default timeouts and retransmissions for each STUN request.
297    ///
298    /// - `initial` - the initial time between consecutive transmissions. If 0, or 1, then only a
299    ///   single request will be performed.
300    /// - `max` - the maximum amount of time between consecutive retransmits.
301    /// - `retransmits` - the total number of transmissions of the request.
302    /// - `final_retransmit_timeout` - the amount of time after the final transmission to wait
303    ///   for a response before considering the request as having timed out.
304    ///
305    /// As specified in RFC 8489, `initial_rto` should be >= 500ms (unless specific information is
306    /// available on the RTT, `max` is `Duration::MAX`, `retransmits` has a default value of 7,
307    /// and `last_retransmit_timeout` should be `16 * initial_rto`.
308    ///
309    /// STUN transactions over TCP will only send a single request and have a timeout of the sum of
310    /// the timeouts of a UDP transaction.
311    pub fn set_request_retransmits(
312        &mut self,
313        initial: Duration,
314        max: Duration,
315        retransmits: u32,
316        final_retransmit_timeout: Duration,
317    ) {
318        let rto = self.rto.get_or_insert(RequestRto {
319            initial,
320            max,
321            retransmits,
322            final_retransmit_timeout,
323        });
324        rto.initial = initial;
325        rto.max = max;
326        rto.retransmits = retransmits;
327        rto.final_retransmit_timeout = final_retransmit_timeout;
328    }
329
330    pub(crate) fn apply_to_stun_builder(&self, builder: StunAgentBuilder) -> StunAgentBuilder {
331        if let Some(rto) = self.rto.as_ref() {
332            builder.request_retransmits(
333                rto.initial,
334                rto.max,
335                rto.retransmits,
336                rto.final_retransmit_timeout,
337            )
338        } else {
339            builder
340        }
341    }
342}
343
344/// Return value from calling [poll](TurnClientApi::poll)().
345#[derive(Debug)]
346pub enum TurnPollRet {
347    /// The caller should wait until the provided time. Other events may cause this value to
348    /// modified and poll() should be rechecked.
349    WaitUntil(Instant),
350    /// The caller should initiate a connection using the provided remote address based on the
351    /// provided local address.
352    AllocateTcpSocket {
353        /// The server-unique identifier for this connection.
354        id: u32,
355        /// The client-server network 5-tuple.
356        socket: Socket5Tuple,
357        /// The address of the peer to connect to.
358        peer_addr: SocketAddr,
359    },
360    /// The client has completed closing a TCP connection between the TURN client and a peer.
361    ///
362    /// The connection can be in progress of being setup.
363    TcpClose {
364        /// The socket address local to the TURN client.
365        local_addr: SocketAddr,
366        /// The address of the remote peer.
367        remote_addr: SocketAddr,
368    },
369    /// The connection is closed and no further progress will be made.
370    Closed,
371}
372
373/// A socket with the specified network 5-tuple.
374#[derive(Clone, Copy, Debug, PartialEq, Eq)]
375pub struct Socket5Tuple {
376    /// The transport for the socket.
377    pub transport: TransportType,
378    /// The local address for the socket.
379    pub from: SocketAddr,
380    /// The remote address for the socket.
381    pub to: SocketAddr,
382}
383
384/// Return value from call [recv](TurnClientApi::recv).
385#[derive(Debug)]
386pub enum TurnRecvRet<T: AsRef<[u8]> + core::fmt::Debug> {
387    /// The data has been handled internally and should not be forwarded any further.
388    Handled,
389    /// The data is not directed at this [`TurnClientApi`].
390    Ignored(Transmit<T>),
391    /// Data has been received from a peer of the TURN server.
392    PeerData(TurnPeerData<T>),
393    /// An ICMP packet has been received from a peer of the TURN server.
394    PeerIcmp {
395        /// The [`TransportType`] of the peer address.
396        transport: TransportType,
397        /// The network address of the peer that produced the ICMP data.
398        peer: SocketAddr,
399        /// The type of ICMP data.
400        icmp_type: u8,
401        /// The ICMP code.
402        icmp_code: u8,
403        /// The ICMP data.
404        icmp_data: u32,
405    },
406}
407
408/// Data that has been received from the TURN server.
409#[derive(Debug)]
410pub struct TurnPeerData<T: AsRef<[u8]> + core::fmt::Debug> {
411    /// The data received.
412    pub(crate) data: DataRangeOrOwned<T>,
413    /// The transport the data was received over.
414    pub transport: TransportType,
415    /// The address of the peer that sent the data.
416    pub peer: SocketAddr,
417}
418
419impl<T: AsRef<[u8]> + core::fmt::Debug> TurnPeerData<T> {
420    /// Produce an owned variant of [`TurnPeerData`], copying only if necessary.
421    pub fn into_owned<R: AsRef<[u8]> + core::fmt::Debug>(self) -> TurnPeerData<R> {
422        TurnPeerData {
423            data: self.data.into_owned(),
424            transport: self.transport,
425            peer: self.peer,
426        }
427    }
428}
429
430impl<T: AsRef<[u8]> + core::fmt::Debug> TurnPeerData<T> {
431    /// The data slice of this [`TurnPeerData`]
432    pub fn data(&self) -> &[u8] {
433        self.data.as_ref()
434    }
435}
436
437impl<T: AsRef<[u8]> + core::fmt::Debug> AsRef<[u8]> for TurnPeerData<T> {
438    fn as_ref(&self) -> &[u8] {
439        self.data.as_ref()
440    }
441}
442
443/// A set of events that can occur within a TURN client's connection to a TURN server.
444#[derive(Debug)]
445pub enum TurnEvent {
446    /// An allocation was created on the server for the client.  The allocation as the associated
447    /// transport and address.
448    AllocationCreated(TransportType, SocketAddr),
449    /// Allocation failed to be created for the specified address family.
450    AllocationCreateFailed(AddressFamily),
451    /// A permission was created for the provided transport and IP address.
452    PermissionCreated(TransportType, IpAddr),
453    /// A permission could not be installed for the provided transport and IP address.
454    PermissionCreateFailed(TransportType, IpAddr),
455    /// A channel was created for the provided transport and IP address.
456    ChannelCreated(TransportType, SocketAddr),
457    /// A channel could not be installed for the provided transport and IP address.
458    ChannelCreateFailed(TransportType, SocketAddr),
459    /// A TCP connection was created for the provided peer IP address.
460    TcpConnected(SocketAddr),
461    /// A TCP connection could not be installed for the provided peer IP address.
462    TcpConnectFailed(SocketAddr),
463}
464
465/// Errors produced when attempting to bind a channel.
466#[derive(Debug, thiserror::Error)]
467#[non_exhaustive]
468pub enum BindChannelError {
469    /// The channel identifier already exists and cannot be recreated.
470    #[error("The channel identifier already exists and cannot be recreated.")]
471    AlreadyExists,
472    /// The channel for requested peer address has expired and cannot be recreated yet.
473    #[error("The channel for requested peer address has expired and cannot be recreated until {}.", .0)]
474    ExpiredChannelExists(Instant),
475    /// There is no connection to the TURN server that can handle this channel.
476    #[error("There is no connection to the TURN server that can handle this channel.")]
477    NoAllocation,
478}
479
480/// Errors produced when attempting to create a permission for a peer address.
481#[derive(Debug, thiserror::Error)]
482#[non_exhaustive]
483pub enum CreatePermissionError {
484    /// The permission already exists and cannot be recreated.
485    #[error("The permission already exists and cannot be recreated.")]
486    AlreadyExists,
487    /// There is no connection to the TURN server that can handle this permission.
488    #[error("There is no connection to the TURN server that can handle this permission")]
489    NoAllocation,
490}
491
492/// Errors produced when attempting to delete an allocation.
493#[derive(Debug, thiserror::Error)]
494#[non_exhaustive]
495pub enum DeleteError {
496    /// There is no connection to the TURN server.
497    #[error("There is no connection to the TURN server")]
498    NoAllocation,
499}
500
501/// Errors produced when attempting to send data to a peer.
502#[derive(Debug, thiserror::Error)]
503#[non_exhaustive]
504pub enum SendError {
505    /// There is no connection to the TURN server.
506    #[error("There is no connection to the TURN server")]
507    NoAllocation,
508    /// There is no permission installed for the requested peer.
509    #[error("There is no permission installed for the requested peer")]
510    NoPermission,
511    /// There is no local TCP socket for the requested peer.
512    #[error("There is no local TCP socket for the requested peer")]
513    NoTcpSocket,
514}
515
516/// Errors produced when attempting to connect to a peer over TCP.
517#[derive(Debug, thiserror::Error)]
518#[non_exhaustive]
519pub enum TcpConnectError {
520    /// The TCP connection already exists and cannot be recreated.
521    #[error("The TCP connection already exists and cannot be recreated.")]
522    AlreadyExists,
523    /// There is no connection to the TURN server that can handle this TCP socket.
524    #[error("There is no connection to the TURN server that can handle this TCP socket.")]
525    NoAllocation,
526    /// There is no permission installed for the requested peer.
527    #[error("There is no permission installed for the requested peer")]
528    NoPermission,
529}
530
531/// Errors produced when attempting to connect to a peer over TCP.
532#[derive(Debug, thiserror::Error)]
533#[non_exhaustive]
534pub enum TcpAllocateError {
535    /// The TCP connection already exists and cannot be recreated.
536    #[error("The TCP connection already exists and cannot be recreated.")]
537    AlreadyExists,
538    /// There is no connection to the TURN server that can handle this TCP socket.
539    #[error("There is no connection to the TURN server that can handle this TCP socket.")]
540    NoAllocation,
541}
542
543/// A slice range or an owned piece of data.
544#[derive(Debug)]
545pub enum DataRangeOrOwned<T: AsRef<[u8]> + core::fmt::Debug> {
546    /// A range of a provided data slice.
547    Range {
548        /// The data received.
549        data: T,
550        /// The range of data to access.
551        range: Range<usize>,
552    },
553    /// An owned piece of data.
554    Owned(Vec<u8>),
555}
556
557impl<T: AsRef<[u8]> + core::fmt::Debug> AsRef<[u8]> for DataRangeOrOwned<T> {
558    fn as_ref(&self) -> &[u8] {
559        match self {
560            Self::Range { data, range } => &data.as_ref()[range.start..range.end],
561            Self::Owned(owned) => owned,
562        }
563    }
564}
565
566impl<T: AsRef<[u8]> + core::fmt::Debug> DataRangeOrOwned<T> {
567    pub(crate) fn into_owned<R: AsRef<[u8]> + core::fmt::Debug>(self) -> DataRangeOrOwned<R> {
568        DataRangeOrOwned::Owned(match self {
569            Self::Range { data: _, range: _ } => self.as_ref().to_vec(),
570            Self::Owned(owned) => owned,
571        })
572    }
573}
574
575/// A `Transmit` where the data is some subset of the provided data.
576#[derive(Debug)]
577pub struct DelayedTransmit<T: AsRef<[u8]> + core::fmt::Debug> {
578    data: T,
579    range: Range<usize>,
580}
581
582impl<T: AsRef<[u8]> + core::fmt::Debug> DelayedTransmit<T> {
583    fn data(&self) -> &[u8] {
584        &self.data.as_ref()[self.range.clone()]
585    }
586}
587
588impl<T: AsRef<[u8]> + core::fmt::Debug> DelayedTransmitBuild for DelayedTransmit<T> {
589    fn len(&self) -> usize {
590        self.range.len()
591    }
592
593    fn build(self) -> Vec<u8> {
594        self.data().to_vec()
595    }
596
597    fn write_into(self, data: &mut [u8]) -> usize {
598        data.copy_from_slice(self.data());
599        self.len()
600    }
601}
602
603/// A delayed `Transmit` that will produce data for a TURN server.
604#[derive(Debug)]
605pub enum DelayedMessageOrChannelSend<T: AsRef<[u8]> + core::fmt::Debug> {
606    /// A [`DelayedChannel`].
607    Channel(DelayedChannel<T>),
608    /// A [`DelayedMessage`].
609    Message(DelayedMessage<T>),
610    /// Passthrough of a piece of data.
611    Data(T),
612    /// An already constructed piece of data.
613    OwnedData(Vec<u8>),
614}
615
616impl<T: AsRef<[u8]> + core::fmt::Debug> DelayedMessageOrChannelSend<T> {
617    pub(crate) fn new_channel(data: T, channel_id: u16) -> Self {
618        Self::Channel(DelayedChannel::new(channel_id, data))
619    }
620
621    pub(crate) fn new_message(data: T, peer_addr: SocketAddr) -> Self {
622        Self::Message(DelayedMessage::for_server(peer_addr, data))
623    }
624}
625
626impl<T: AsRef<[u8]> + core::fmt::Debug> DelayedTransmitBuild for DelayedMessageOrChannelSend<T> {
627    fn len(&self) -> usize {
628        match self {
629            Self::Channel(channel) => channel.len(),
630            Self::Message(msg) => msg.len(),
631            Self::Data(data) => data.as_ref().len(),
632            Self::OwnedData(owned) => owned.len(),
633        }
634    }
635
636    fn build(self) -> Vec<u8> {
637        match self {
638            Self::Channel(channel) => channel.build(),
639            Self::Message(msg) => msg.build(),
640            Self::Data(data) => data.as_ref().to_vec(),
641            Self::OwnedData(owned) => owned,
642        }
643    }
644
645    fn write_into(self, data: &mut [u8]) -> usize {
646        match self {
647            Self::Channel(channel) => channel.write_into(data),
648            Self::Message(msg) => msg.write_into(data),
649            Self::Data(slice) => {
650                data.copy_from_slice(slice.as_ref());
651                slice.as_ref().len()
652            }
653            Self::OwnedData(owned) => {
654                data.copy_from_slice(&owned);
655                owned.len()
656            }
657        }
658    }
659}
660
661#[cfg(test)]
662pub(crate) mod tests {
663    use alloc::vec;
664
665    use super::*;
666    use turn_types::stun::message::Message;
667    use turn_types::{
668        attribute::{Data as AData, XorPeerAddress},
669        channel::ChannelData,
670    };
671
672    pub(crate) fn generate_addresses() -> (SocketAddr, SocketAddr) {
673        (
674            "192.168.0.1:1000".parse().unwrap(),
675            "10.0.0.2:2000".parse().unwrap(),
676        )
677    }
678
679    #[test]
680    fn test_delayed_message() {
681        let (local_addr, remote_addr) = generate_addresses();
682        let data = [5; 5];
683        let peer_addr = "127.0.0.1:1".parse().unwrap();
684        let transmit = TransmitBuild::new(
685            DelayedMessageOrChannelSend::Message(DelayedMessage::for_server(peer_addr, data)),
686            TransportType::Udp,
687            local_addr,
688            remote_addr,
689        );
690        assert!(!transmit.data.is_empty());
691        let len = transmit.data.len();
692        let out = transmit.build();
693        assert_eq!(len, out.data.len());
694        let msg = Message::from_bytes(&out.data).unwrap();
695        let addr = msg.attribute::<XorPeerAddress>().unwrap();
696        assert_eq!(addr.addr(msg.transaction_id()), peer_addr);
697        let out_data = msg.attribute::<AData>().unwrap();
698        assert_eq!(out_data.data(), data.as_ref());
699        let transmit = TransmitBuild::new(
700            DelayedMessageOrChannelSend::Message(DelayedMessage::for_server(peer_addr, data)),
701            TransportType::Udp,
702            local_addr,
703            remote_addr,
704        );
705        let mut out2 = vec![0; len];
706        transmit.write_into(&mut out2);
707        let msg = Message::from_bytes(&out2).unwrap();
708        let addr = msg.attribute::<XorPeerAddress>().unwrap();
709        assert_eq!(addr.addr(msg.transaction_id()), peer_addr);
710        let out_data = msg.attribute::<AData>().unwrap();
711        assert_eq!(out_data.data(), data.as_ref());
712    }
713
714    #[test]
715    fn test_delayed_channel() {
716        let (local_addr, remote_addr) = generate_addresses();
717        let data = [5; 5];
718        let channel_id = 0x4567;
719        let transmit = TransmitBuild::new(
720            DelayedMessageOrChannelSend::Channel(DelayedChannel::new(channel_id, data)),
721            TransportType::Udp,
722            local_addr,
723            remote_addr,
724        );
725        assert!(!transmit.data.is_empty());
726        let len = transmit.data.len();
727        let out = transmit.build();
728        assert_eq!(len, out.data.len());
729        let channel = ChannelData::parse(&out.data).unwrap();
730        assert_eq!(channel.id(), channel_id);
731        assert_eq!(channel.data(), data.as_ref());
732        let transmit = TransmitBuild::new(
733            DelayedMessageOrChannelSend::Channel(DelayedChannel::new(channel_id, data)),
734            TransportType::Udp,
735            local_addr,
736            remote_addr,
737        );
738        let mut out2 = vec![0; len];
739        transmit.write_into(&mut out2);
740        assert_eq!(len, out2.len());
741        let channel = ChannelData::parse(&out2).unwrap();
742        assert_eq!(channel.id(), channel_id);
743        assert_eq!(channel.data(), data.as_ref());
744    }
745
746    #[test]
747    fn test_delayed_owned() {
748        let (local_addr, remote_addr) = generate_addresses();
749        let data = vec![7; 7];
750        let transmit = TransmitBuild::new(
751            DelayedMessageOrChannelSend::<Vec<u8>>::Data(data.clone()),
752            TransportType::Udp,
753            local_addr,
754            remote_addr,
755        );
756        assert!(!transmit.data.is_empty());
757        let len = transmit.data.len();
758        let out = transmit.build();
759        assert_eq!(len, out.data.len());
760        assert_eq!(data, out.data);
761        let transmit = TransmitBuild::new(
762            DelayedMessageOrChannelSend::<Vec<u8>>::Data(data.clone()),
763            TransportType::Udp,
764            local_addr,
765            remote_addr,
766        );
767        let mut out2 = vec![0; len];
768        transmit.write_into(&mut out2);
769        assert_eq!(len, out2.len());
770        assert_eq!(data, out2);
771    }
772}