Skip to main content

turn_client_proto/
client.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.
12//!
13//! A cohesive TURN client that can be one of the transport specific (UDP, TCP, TLS) implementations.
14
15use alloc::vec::Vec;
16
17pub use crate::api::{
18    BindChannelError, CreatePermissionError, DeleteError, SendError, TcpAllocateError, TurnEvent,
19    TurnPollRet, TurnRecvRet,
20};
21use crate::tcp::TurnClientTcp;
22use crate::udp::TurnClientUdp;
23
24/// Implement an enum over a list of TURN client implementations.
25///
26/// All discriminants must implement `TurnClientApi`.
27///
28/// # Example
29///
30/// ```
31/// # use turn_client_proto::udp::TurnClientUdp;
32/// # use turn_client_proto::tcp::TurnClientTcp;
33/// turn_client_proto::impl_client!(pub TurnClient, (Udp, TurnClientUdp), (Tcp, TurnClientTcp));
34/// ```
35///
36/// Roughly translates to:
37///
38/// ```
39/// # use turn_client_proto::udp::TurnClientUdp;
40/// # use turn_client_proto::tcp::TurnClientTcp;
41/// pub enum TurnClient {
42///    Udp(TurnClientUdp),
43///    Tcp(TurnClientTcp),
44/// }
45///
46/// // impl TurnClientApi for TurnClient {
47/// //    ...
48/// // }
49/// ```
50#[macro_export]
51macro_rules! impl_client {
52    ($vis:vis $name:ident, $(($variant:ident, $ty:ty)),+) => {
53        /// A TURN client.
54        #[derive(Debug)]
55        $vis enum $name {
56            $(
57                #[doc = "A "]
58                #[doc = stringify!($ty)]
59                #[doc = " TURN client."]
60                $variant($ty),)+
61        }
62        impl $crate::api::TurnClientApi for $name
63        {
64            fn transport(&self) -> $crate::types::TransportType {
65                match self {
66                    $(Self::$variant(val) => val.transport(),)+
67                }
68            }
69            fn local_addr(&self) -> core::net::SocketAddr {
70                match self {
71                    $(Self::$variant(val) => val.local_addr(),)+
72                }
73            }
74            fn remote_addr(&self) -> core::net::SocketAddr {
75                match self {
76                    $(Self::$variant(val) => val.remote_addr(),)+
77                }
78            }
79            fn relayed_addresses(&self) -> impl Iterator<Item = ($crate::types::TransportType, core::net::SocketAddr)> + '_ {
80                match self {
81                    $(Self::$variant(val) => RelayedAddressesIter::$variant(val.relayed_addresses()),)+
82                }
83            }
84            fn permissions(
85                &self,
86                transport: $crate::types::TransportType,
87                relayed: core::net::SocketAddr,
88            ) -> impl Iterator<Item = core::net::IpAddr> + '_ {
89                match self {
90                    $(Self::$variant(val) => PermissionAddressesIter::$variant(val.permissions(transport, relayed)),)+
91                }
92            }
93            fn delete(&mut self, now: $crate::types::Instant) -> Result<(), $crate::api::DeleteError> {
94                match self {
95                    $(Self::$variant(val) => val.delete(now),)+
96                }
97            }
98            fn create_permission(
99                &mut self,
100                transport: $crate::types::TransportType,
101                peer_addr: core::net::IpAddr,
102                now: $crate::types::Instant,
103            ) -> Result<(), $crate::api::CreatePermissionError> {
104                match self {
105                    $(Self::$variant(val) => val.create_permission(transport, peer_addr, now),)+
106                }
107            }
108            fn have_permission(&self, transport: $crate::types::TransportType, to: core::net::IpAddr) -> bool {
109                match self {
110                    $(Self::$variant(val) => val.have_permission(transport, to),)+
111                }
112            }
113            fn bind_channel(
114                &mut self,
115                transport: $crate::types::TransportType,
116                peer_addr: core::net::SocketAddr,
117                now: $crate::types::Instant,
118            ) -> Result<(), $crate::api::BindChannelError> {
119                match self {
120                    $(Self::$variant(val) => val.bind_channel(transport, peer_addr, now),)+
121                }
122            }
123            fn tcp_connect(&mut self, peer_addr: core::net::SocketAddr, now: $crate::types::Instant) -> Result<(), $crate::api::TcpConnectError> {
124                match self {
125                    $(Self::$variant(val) => val.tcp_connect(peer_addr, now),)+
126                }
127            }
128            fn allocated_tcp_socket(
129                &mut self,
130                id: u32,
131                five_tuple: $crate::api::Socket5Tuple,
132                peer_addr: core::net::SocketAddr,
133                local_addr: Option<core::net::SocketAddr>,
134                now: $crate::types::Instant,
135            ) -> Result<(), $crate::api::TcpAllocateError> {
136                match self {
137                    $(Self::$variant(val) => val.allocated_tcp_socket(id, five_tuple, peer_addr, local_addr, now),)+
138                }
139            }
140            fn tcp_closed(
141                &mut self,
142                local_addr: core::net::SocketAddr,
143                remote_addr: core::net::SocketAddr,
144                now: $crate::types::Instant,
145            ) {
146                match self {
147                    $(Self::$variant(val) => val.tcp_closed(local_addr, remote_addr, now),)+
148                }
149            }
150            fn send_to<T: AsRef<[u8]> + core::fmt::Debug>(
151                &mut self,
152                transport: $crate::types::TransportType,
153                to: core::net::SocketAddr,
154                data: T,
155                now: $crate::types::Instant,
156            ) -> Result<Option<$crate::api::TransmitBuild<$crate::api::DelayedMessageOrChannelSend<T>>>, $crate::api::SendError> {
157                match self {
158                    $(Self::$variant(val) => val.send_to(transport, to, data, now),)+
159                }
160            }
161            fn recv<T: AsRef<[u8]> + core::fmt::Debug>(
162                &mut self,
163                transmit: $crate::api::Transmit<T>,
164                now: $crate::types::Instant,
165            ) -> $crate::api::TurnRecvRet<T> {
166                match self {
167                    $(Self::$variant(val) => val.recv(transmit, now),)+
168                }
169            }
170            fn poll_recv(&mut self, now: $crate::types::Instant) -> Option<$crate::api::TurnPeerData<Vec<u8>>> {
171                match self {
172                    $(Self::$variant(val) => val.poll_recv(now),)+
173                }
174            }
175            fn poll(&mut self, now: $crate::types::Instant) -> $crate::api::TurnPollRet {
176                match self {
177                    $(Self::$variant(val) => val.poll(now),)+
178                }
179            }
180            fn poll_transmit(&mut self, now: $crate::types::Instant) -> Option<$crate::api::Transmit<$crate::types::stun::data::Data<'static>>> {
181                match self {
182                    $(Self::$variant(val) => val.poll_transmit(now),)+
183                }
184            }
185            fn poll_event(&mut self) -> Option<$crate::api::TurnEvent> {
186                match self {
187                    $(Self::$variant(val) => val.poll_event(),)+
188                }
189            }
190            fn protocol_error(&mut self) {
191                match self {
192                    $(Self::$variant(val) => val.protocol_error(),)+
193                }
194            }
195        }
196        enum RelayedAddressesIter<$($variant: Iterator<Item = ($crate::types::TransportType, core::net::SocketAddr)>, )+> {
197            $($variant($variant),)+
198        }
199        impl<$($variant: Iterator<Item = ($crate::types::TransportType, core::net::SocketAddr)>,)+> Iterator for RelayedAddressesIter<$($variant,)+> {
200            type Item = ($crate::types::TransportType, core::net::SocketAddr);
201            fn next(&mut self) -> Option<Self::Item> {
202                match self {
203                    $(Self::$variant(ref mut val) => val.next(),)+
204                }
205            }
206        }
207        enum PermissionAddressesIter<$($variant: Iterator<Item = core::net::IpAddr>, )+> {
208            $($variant($variant),)+
209        }
210        impl<$($variant: Iterator<Item = core::net::IpAddr>,)+> Iterator for PermissionAddressesIter<$($variant,)+> {
211            type Item = core::net::IpAddr;
212            fn next(&mut self) -> Option<Self::Item> {
213                match self {
214                    $(Self::$variant(ref mut val) => val.next(),)+
215                }
216            }
217        }
218        $(impl From<$ty> for $name {
219            fn from(value: $ty) -> Self {
220                Self::$variant(value)
221            }
222        })+
223    }
224}
225
226impl_client!(pub TurnClient, (Udp, TurnClientUdp), (Tcp, TurnClientTcp));