mycrl_turn/lib.rs
1pub mod operations;
2pub mod sessions;
3
4use self::operations::ServiceContext;
5
6pub use self::{
7 operations::{Operationer, ResponseMethod},
8 sessions::{PortAllocatePools, Session, SessionAddr, Sessions},
9};
10
11use std::{future::Future, net::SocketAddr, sync::Arc};
12
13#[rustfmt::skip]
14static SOFTWARE: &str = concat!(
15 "turn-rs.",
16 env!("CARGO_PKG_VERSION")
17);
18
19#[allow(unused)]
20pub trait Observer: Send + Sync {
21 fn get_password(
22 &self,
23 addr: &SessionAddr,
24 username: &str,
25 ) -> impl Future<Output = Option<String>> + Send {
26 async { None }
27 }
28
29 /// allocate request
30 ///
31 /// [rfc8489](https://tools.ietf.org/html/rfc8489)
32 ///
33 /// In all cases, the server SHOULD only allocate ports from the range
34 /// 49152 - 65535 (the Dynamic and/or Private Port range [PORT-NUMBERS]),
35 /// unless the TURN server application knows, through some means not
36 /// specified here, that other applications running on the same host as
37 /// the TURN server application will not be impacted by allocating ports
38 /// outside this range. This condition can often be satisfied by running
39 /// the TURN server application on a dedicated machine and/or by
40 /// arranging that any other applications on the machine allocate ports
41 /// before the TURN server application starts. In any case, the TURN
42 /// server SHOULD NOT allocate ports in the range 0 - 1023 (the Well-
43 /// Known Port range) to discourage clients from using TURN to run
44 /// standard services.
45 fn allocated(&self, addr: &SessionAddr, username: &str, port: u16) {}
46
47 /// channel binding request
48 ///
49 /// The server MAY impose restrictions on the IP address and port values
50 /// allowed in the XOR-PEER-ADDRESS attribute; if a value is not allowed,
51 /// the server rejects the request with a 403 (Forbidden) error.
52 ///
53 /// If the request is valid, but the server is unable to fulfill the
54 /// request due to some capacity limit or similar, the server replies
55 /// with a 508 (Insufficient Capacity) error.
56 ///
57 /// Otherwise, the server replies with a ChannelBind success response.
58 /// There are no required attributes in a successful ChannelBind
59 /// response.
60 ///
61 /// If the server can satisfy the request, then the server creates or
62 /// refreshes the channel binding using the channel number in the
63 /// CHANNEL-NUMBER attribute and the transport address in the XOR-PEER-
64 /// ADDRESS attribute. The server also installs or refreshes a
65 /// permission for the IP address in the XOR-PEER-ADDRESS attribute as
66 /// described in Section 9.
67 ///
68 /// NOTE: A server need not do anything special to implement
69 /// idempotency of ChannelBind requests over UDP using the
70 /// "stateless stack approach". Retransmitted ChannelBind requests
71 /// will simply refresh the channel binding and the corresponding
72 /// permission. Furthermore, the client must wait 5 minutes before
73 /// binding a previously bound channel number or peer address to a
74 /// different channel, eliminating the possibility that the
75 /// transaction would initially fail but succeed on a
76 /// retransmission.
77 fn channel_bind(&self, addr: &SessionAddr, username: &str, channel: u16) {}
78
79 /// create permission request
80 ///
81 /// [rfc8489](https://tools.ietf.org/html/rfc8489)
82 ///
83 /// When the server receives the CreatePermission request, it processes
84 /// as per [Section 5](https://tools.ietf.org/html/rfc8656#section-5)
85 /// plus the specific rules mentioned here.
86 ///
87 /// The message is checked for validity. The CreatePermission request
88 /// MUST contain at least one XOR-PEER-ADDRESS attribute and MAY contain
89 /// multiple such attributes. If no such attribute exists, or if any of
90 /// these attributes are invalid, then a 400 (Bad Request) error is
91 /// returned. If the request is valid, but the server is unable to
92 /// satisfy the request due to some capacity limit or similar, then a 508
93 /// (Insufficient Capacity) error is returned.
94 ///
95 /// If an XOR-PEER-ADDRESS attribute contains an address of an address
96 /// family that is not the same as that of a relayed transport address
97 /// for the allocation, the server MUST generate an error response with
98 /// the 443 (Peer Address Family Mismatch) response code.
99 ///
100 /// The server MAY impose restrictions on the IP address allowed in the
101 /// XOR-PEER-ADDRESS attribute; if a value is not allowed, the server
102 /// rejects the request with a 403 (Forbidden) error.
103 ///
104 /// If the message is valid and the server is capable of carrying out the
105 /// request, then the server installs or refreshes a permission for the
106 /// IP address contained in each XOR-PEER-ADDRESS attribute as described
107 /// in [Section 9](https://tools.ietf.org/html/rfc8656#section-9).
108 /// The port portion of each attribute is ignored and may be any arbitrary
109 /// value.
110 ///
111 /// The server then responds with a CreatePermission success response.
112 /// There are no mandatory attributes in the success response.
113 ///
114 /// > NOTE: A server need not do anything special to implement
115 /// idempotency of CreatePermission requests over UDP using the
116 /// "stateless stack approach". Retransmitted CreatePermission
117 /// requests will simply refresh the permissions.
118 fn create_permission(&self, addr: &SessionAddr, username: &str, ports: &[u16]) {}
119
120 /// refresh request
121 ///
122 /// If the server receives a Refresh Request with a REQUESTED-ADDRESS-
123 /// FAMILY attribute and the attribute value does not match the address
124 /// family of the allocation, the server MUST reply with a 443 (Peer
125 /// Address Family Mismatch) Refresh error response.
126 ///
127 /// The server computes a value called the "desired lifetime" as follows:
128 /// if the request contains a LIFETIME attribute and the attribute value
129 /// is zero, then the "desired lifetime" is zero. Otherwise, if the
130 /// request contains a LIFETIME attribute, then the server computes the
131 /// minimum of the client's requested lifetime and the server's maximum
132 /// allowed lifetime. If this computed value is greater than the default
133 /// lifetime, then the "desired lifetime" is the computed value.
134 /// Otherwise, the "desired lifetime" is the default lifetime.
135 ///
136 /// Subsequent processing depends on the "desired lifetime" value:
137 ///
138 /// * If the "desired lifetime" is zero, then the request succeeds and
139 /// the allocation is deleted.
140 ///
141 /// * If the "desired lifetime" is non-zero, then the request succeeds
142 /// and the allocation's time-to-expiry is set to the "desired
143 /// lifetime".
144 ///
145 /// If the request succeeds, then the server sends a success response
146 /// containing:
147 ///
148 /// * A LIFETIME attribute containing the current value of the time-to-
149 /// expiry timer.
150 ///
151 /// NOTE: A server need not do anything special to implement
152 /// idempotency of Refresh requests over UDP using the "stateless
153 /// stack approach". Retransmitted Refresh requests with a non-
154 /// zero "desired lifetime" will simply refresh the allocation. A
155 /// retransmitted Refresh request with a zero "desired lifetime"
156 /// will cause a 437 (Allocation Mismatch) response if the
157 /// allocation has already been deleted, but the client will treat
158 /// this as equivalent to a success response (see below).
159 fn refresh(&self, addr: &SessionAddr, username: &str, lifetime: u32) {}
160
161 /// session closed
162 ///
163 /// Triggered when the session leaves from the turn. Possible reasons: the
164 /// session life cycle has expired, external active deletion, or active
165 /// exit of the session.
166 fn closed(&self, addr: &SessionAddr, username: &str) {}
167}
168
169/// Turn service.
170#[derive(Clone)]
171pub struct Service<T> {
172 interfaces: Arc<Vec<SocketAddr>>,
173 sessions: Arc<Sessions<T>>,
174 realm: Arc<String>,
175 observer: T,
176}
177
178impl<T> Service<T>
179where
180 T: Clone + Observer + 'static,
181{
182 pub fn get_sessions(&self) -> Arc<Sessions<T>> {
183 self.sessions.clone()
184 }
185
186 /// Create turn service.
187 ///
188 /// # Test
189 ///
190 /// ```
191 /// use turn::*;
192 ///
193 /// #[derive(Clone)]
194 /// struct ObserverTest;
195 ///
196 /// impl Observer for ObserverTest {}
197 ///
198 /// Service::new("test".to_string(), vec![], ObserverTest);
199 /// ```
200 pub fn new(realm: String, interfaces: Vec<SocketAddr>, observer: T) -> Self {
201 Self {
202 sessions: Sessions::new(observer.clone()),
203 interfaces: Arc::new(interfaces),
204 realm: Arc::new(realm),
205 observer,
206 }
207 }
208
209 /// Get operationer.
210 ///
211 /// # Test
212 ///
213 /// ```
214 /// use std::net::SocketAddr;
215 /// use stun::attribute::Transport;
216 /// use turn::*;
217 ///
218 /// #[derive(Clone)]
219 /// struct ObserverTest;
220 ///
221 /// impl Observer for ObserverTest {}
222 ///
223 /// let addr = "127.0.0.1:8080".parse::<SocketAddr>().unwrap();
224 /// let service = Service::new("test".to_string(), vec![], ObserverTest);
225 ///
226 /// service.get_operationer(addr, addr);
227 /// ```
228 pub fn get_operationer(&self, endpoint: SocketAddr, interface: SocketAddr) -> Operationer<T> {
229 Operationer::new(ServiceContext {
230 interfaces: self.interfaces.clone(),
231 observer: self.observer.clone(),
232 sessions: self.sessions.clone(),
233 realm: self.realm.clone(),
234 interface,
235 endpoint,
236 })
237 }
238}