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