turn_server/service/routing.rs
1use std::{net::SocketAddr, sync::Arc};
2
3use bytes::BytesMut;
4use rand::seq::IteratorRandom;
5
6use super::{
7 InterfaceAddr, Service, ServiceHandler,
8 session::{DEFAULT_SESSION_LIFETIME, Identifier, SessionManager},
9};
10
11use crate::{
12 codec::{
13 DecodeResult, Decoder,
14 channel_data::ChannelData,
15 crypto::Password,
16 message::{
17 Message, MessageEncoder,
18 attributes::{address::IpAddrExt, error::ErrorType, *},
19 methods::*,
20 },
21 },
22 service::Transport,
23};
24
25struct Request<'a, 'b, T, M>
26where
27 T: ServiceHandler,
28{
29 response_buffer: &'b mut BytesMut,
30 state: &'a RouterState<T>,
31 payload: &'a M,
32}
33
34impl<'a, 'b, T> Request<'a, 'b, T, Message<'a>>
35where
36 T: ServiceHandler,
37{
38 // Verify the IP address specified by the client in the request, such as the
39 // peer address used when creating permissions and binding channels. Currently,
40 // only peer addresses that are local addresses of the TURN server are allowed;
41 // arbitrary addresses are not permitted.
42 //
43 // Allowing arbitrary addresses would pose security risks, such as enabling
44 // the TURN server to forward data to any target.
45 #[inline(always)]
46 fn verify_ip(&self, address: &SocketAddr) -> bool {
47 self.state
48 .interfaces
49 .iter()
50 .any(|item| item.external.ip() == address.ip())
51 }
52
53 // The key for the HMAC depends on whether long-term or short-term
54 // credentials are in use. For long-term credentials, the key is 16
55 // bytes:
56 //
57 // key = MD5(username ":" realm ":" SASLprep(password))
58 //
59 // That is, the 16-byte key is formed by taking the MD5 hash of the
60 // result of concatenating the following five fields: (1) the username,
61 // with any quotes and trailing nulls removed, as taken from the
62 // USERNAME attribute (in which case SASLprep has already been applied);
63 // (2) a single colon; (3) the realm, with any quotes and trailing nulls
64 // removed; (4) a single colon; and (5) the password, with any trailing
65 // nulls removed and after processing using SASLprep. For example, if
66 // the username was 'user', the realm was 'realm', and the password was
67 // 'pass', then the 16-byte HMAC key would be the result of performing
68 // an MD5 hash on the string 'user:realm:pass', the resulting hash being
69 // 0x8493fbc53ba582fb4c044c456bdc40eb.
70 //
71 // For short-term credentials:
72 //
73 // key = SASLprep(password)
74 //
75 // where MD5 is defined in RFC 1321 [RFC1321] and SASLprep() is defined
76 // in RFC 4013 [RFC4013].
77 //
78 // The structure of the key when used with long-term credentials
79 // facilitates deployment in systems that also utilize SIP. Typically,
80 // SIP systems utilizing SIP's digest authentication mechanism do not
81 // actually store the password in the database. Rather, they store a
82 // value called H(A1), which is equal to the key defined above.
83 //
84 // Based on the rules above, the hash used to construct MESSAGE-
85 // INTEGRITY includes the length field from the STUN message header.
86 // Prior to performing the hash, the MESSAGE-INTEGRITY attribute MUST be
87 // inserted into the message (with dummy content). The length MUST then
88 // be set to point to the length of the message up to, and including,
89 // the MESSAGE-INTEGRITY attribute itself, but excluding any attributes
90 // after it. Once the computation is performed, the value of the
91 // MESSAGE-INTEGRITY attribute can be filled in, and the value of the
92 // length in the STUN header can be set to its correct value -- the
93 // length of the entire message. Similarly, when validating the
94 // MESSAGE-INTEGRITY, the length field should be adjusted to point to
95 // the end of the MESSAGE-INTEGRITY attribute prior to calculating the
96 // HMAC. Such adjustment is necessary when attributes, such as
97 // FINGERPRINT, appear after MESSAGE-INTEGRITY.
98 #[inline(always)]
99 async fn verify(&self) -> Option<(&str, Password)> {
100 let username = self.payload.get::<UserName>()?;
101 let algorithm = self
102 .payload
103 .get::<PasswordAlgorithm>()
104 .unwrap_or(PasswordAlgorithm::Md5);
105
106 let password = self
107 .state
108 .manager
109 .get_password(&self.state.id, username, algorithm)
110 .await?;
111
112 if self.payload.verify(&password).is_err() {
113 return None;
114 }
115
116 Some((username, password))
117 }
118}
119
120/// The route result.
121#[derive(Debug)]
122pub struct RouteResult {
123 /// if the method is None, the response is a channel data response
124 pub method: Option<Method>,
125 /// the relay target of the response
126 pub relay: Option<Identifier>,
127}
128
129pub(crate) struct RouterState<T>
130where
131 T: ServiceHandler,
132{
133 pub id: Identifier,
134 pub realm: String,
135 pub software: String,
136 pub manager: Arc<SessionManager<T>>,
137 pub interfaces: Arc<Vec<InterfaceAddr>>,
138 pub handler: T,
139}
140
141pub struct Router<T>
142where
143 T: ServiceHandler,
144{
145 state: RouterState<T>,
146 decoder: Decoder,
147}
148
149impl<T> Router<T>
150where
151 T: ServiceHandler + Clone,
152{
153 pub fn new(service: &Service<T>, id: Identifier) -> Self {
154 Self {
155 decoder: Decoder::default(),
156 state: RouterState {
157 interfaces: service.interfaces.clone(),
158 software: service.software.clone(),
159 handler: service.handler.clone(),
160 manager: service.manager.clone(),
161 realm: service.realm.clone(),
162 id,
163 },
164 }
165 }
166
167 pub async fn route(
168 &mut self,
169 bytes: &[u8],
170 response_buffer: &mut BytesMut,
171 ) -> Result<Option<RouteResult>, crate::codec::Error> {
172 Ok(match self.decoder.decode(bytes)? {
173 DecodeResult::ChannelData(channel) => channel_data(Request {
174 state: &self.state,
175 payload: &channel,
176 response_buffer,
177 }),
178 DecodeResult::Message(message) => {
179 let req = Request {
180 state: &self.state,
181 payload: &message,
182 response_buffer,
183 };
184
185 match req.payload.method() {
186 BINDING_REQUEST => binding(req),
187 ALLOCATE_REQUEST => allocate(req).await,
188 CREATE_PERMISSION_REQUEST => create_permission(req).await,
189 CHANNEL_BIND_REQUEST => channel_bind(req).await,
190 REFRESH_REQUEST => refresh(req).await,
191 SEND_INDICATION => indication(req),
192 _ => None,
193 }
194 }
195 })
196 }
197}
198
199fn reject<T>(req: Request<'_, '_, T, Message<'_>>, error: ErrorType) -> Option<RouteResult>
200where
201 T: ServiceHandler,
202{
203 let method = req.payload.method().error()?;
204
205 {
206 let mut message = MessageEncoder::extend(method, req.payload, req.response_buffer);
207
208 message.append::<ErrorCode>(ErrorCode::from(error));
209
210 if error == ErrorType::Unauthorized {
211 message.append::<Realm>(&req.state.realm);
212 message.append::<Nonce>(
213 req.state
214 .manager
215 .get_session_or_default(&req.state.id)
216 .get_ref()?
217 .nonce(),
218 );
219
220 message.append::<PasswordAlgorithms>(vec![
221 PasswordAlgorithm::Md5,
222 PasswordAlgorithm::Sha256,
223 ]);
224 }
225
226 message.flush(None).ok()?;
227 }
228
229 Some(RouteResult {
230 method: Some(method),
231 relay: None,
232 })
233}
234
235/// [rfc8489](https://tools.ietf.org/html/rfc8489)
236///
237/// In the Binding request/response transaction, a Binding request is
238/// sent from a STUN client to a STUN server. When the Binding request
239/// arrives at the STUN server, it may have passed through one or more
240/// NATs between the STUN client and the STUN server (in Figure 1, there
241/// are two such NATs). As the Binding request message passes through a
242/// NAT, the NAT will modify the source transport address (that is, the
243/// source IP address and the source port) of the packet. As a result,
244/// the source transport address of the request received by the server
245/// will be the public IP address and port created by the NAT closest to
246/// the server. This is called a "reflexive transport address". The
247/// STUN server copies that source transport address into an XOR-MAPPED-
248/// ADDRESS attribute in the STUN Binding response and sends the Binding
249/// response back to the STUN client. As this packet passes back through
250/// a NAT, the NAT will modify the destination transport address in the
251/// IP header, but the transport address in the XOR-MAPPED-ADDRESS
252/// attribute within the body of the STUN response will remain untouched.
253/// In this way, the client can learn its reflexive transport address
254/// allocated by the outermost NAT with respect to the STUN server.
255fn binding<T>(req: Request<'_, '_, T, Message<'_>>) -> Option<RouteResult>
256where
257 T: ServiceHandler,
258{
259 {
260 let mut message =
261 MessageEncoder::extend(BINDING_RESPONSE, req.payload, req.response_buffer);
262
263 message.append::<XorMappedAddress>(req.state.id.source);
264 message.append::<MappedAddress>(req.state.id.source);
265 message.append::<ResponseOrigin>(req.state.id.external);
266 message.append::<Software>(&req.state.software);
267 message.flush(None).ok()?;
268 }
269
270 Some(RouteResult {
271 method: Some(BINDING_RESPONSE),
272 relay: None,
273 })
274}
275
276/// [rfc8489](https://tools.ietf.org/html/rfc8489)
277///
278/// In all cases, the server SHOULD only allocate ports from the range
279/// 49152 - 65535 (the Dynamic and/or Private Port range [PORT-NUMBERS]),
280/// unless the TURN server application knows, through some means not
281/// specified here, that other applications running on the same host as
282/// the TURN server application will not be impacted by allocating ports
283/// outside this range. This condition can often be satisfied by running
284/// the TURN server application on a dedicated machine and/or by
285/// arranging that any other applications on the machine allocate ports
286/// before the TURN server application starts. In any case, the TURN
287/// server SHOULD NOT allocate ports in the range 0 - 1023 (the Well-
288/// Known Port range) to discourage clients from using TURN to run
289/// standard contexts.
290async fn allocate<T>(req: Request<'_, '_, T, Message<'_>>) -> Option<RouteResult>
291where
292 T: ServiceHandler,
293{
294 let xor_relayed_ip = {
295 let mut ip = req.state.id.external.ip();
296
297 let request_transport = if let Some(it) = req.payload.get::<RequestedTransport>() {
298 match it {
299 RequestedTransport::Tcp => Transport::Tcp,
300 RequestedTransport::Udp => Transport::Udp,
301 }
302 } else {
303 return reject(req, ErrorType::BadRequest);
304 };
305
306 let request_family = req
307 .payload
308 .get::<RequestedAddressFamily>()
309 .unwrap_or_else(|| ip.family());
310
311 // If the requested transport protocol or address family does not match the
312 // address assigned by the server, a different address must be selected.
313 // Both conditions must be checked independently: even when request_family
314 // is present, a transport mismatch also requires selecting a new interface.
315 if request_transport != req.state.id.transport || request_family != ip.family() {
316 if let Some(addr) = req
317 .state
318 .interfaces
319 .iter()
320 .filter(|addr| {
321 addr.transport == request_transport
322 && addr.external.ip().family() == request_family
323 })
324 .choose(&mut rand::rng())
325 {
326 ip = addr.external.ip();
327 } else {
328 return reject(
329 req,
330 if request_family != ip.family() {
331 ErrorType::AddressFamilyNotSupported
332 } else {
333 ErrorType::UnsupportedTransportAddress
334 },
335 );
336 }
337 }
338
339 ip
340 };
341
342 let Some((username, password)) = req.verify().await else {
343 return reject(req, ErrorType::Unauthorized);
344 };
345
346 let lifetime = req.payload.get::<Lifetime>();
347
348 let Some(port) = req.state.manager.allocate(&req.state.id, lifetime) else {
349 return reject(req, ErrorType::AllocationQuotaReached);
350 };
351
352 req.state
353 .handler
354 .on_allocated(&req.state.id, username, port);
355
356 {
357 let mut message =
358 MessageEncoder::extend(ALLOCATE_RESPONSE, req.payload, req.response_buffer);
359
360 message.append::<XorRelayedAddress>(SocketAddr::new(xor_relayed_ip, port));
361 message.append::<XorMappedAddress>(req.state.id.source);
362 message.append::<Lifetime>(lifetime.unwrap_or(DEFAULT_SESSION_LIFETIME as u32));
363 message.append::<Software>(&req.state.software);
364 message.flush(Some(&password)).ok()?;
365 }
366
367 Some(RouteResult {
368 method: Some(ALLOCATE_RESPONSE),
369 relay: None,
370 })
371}
372
373/// [rfc8489](https://tools.ietf.org/html/rfc8489)
374///
375/// When the server receives the CreatePermission request, it processes
376/// as per [Section 5](https://tools.ietf.org/html/rfc8656#section-5)
377/// plus the specific rules mentioned here.
378///
379/// The message is checked for validity. The CreatePermission request
380/// MUST contain at least one XOR-PEER-ADDRESS attribute and MAY contain
381/// multiple such attributes. If no such attribute exists, or if any of
382/// these attributes are invalid, then a 400 (Bad Request) error is
383/// returned. If the request is valid, but the server is unable to
384/// satisfy the request due to some capacity limit or similar, then a 508
385/// (Insufficient Capacity) error is returned.
386///
387/// If an XOR-PEER-ADDRESS attribute contains an address of an address
388/// family that is not the same as that of a relayed transport address
389/// for the allocation, the server MUST generate an error response with
390/// the 443 (Peer Address Family Mismatch) response code.
391///
392/// The server MAY impose restrictions on the IP address allowed in the
393/// XOR-PEER-ADDRESS attribute; if a value is not allowed, the server
394/// rejects the request with a 403 (Forbidden) error.
395///
396/// If the message is valid and the server is capable of carrying out the
397/// request, then the server installs or refreshes a permission for the
398/// IP address contained in each XOR-PEER-ADDRESS attribute as described
399/// in [Section 9](https://tools.ietf.org/html/rfc8656#section-9).
400/// The port portion of each attribute is ignored and may be any arbitrary
401/// value.
402///
403/// The server then responds with a CreatePermission success response.
404/// There are no mandatory attributes in the success response.
405///
406/// NOTE: A server need not do anything special to implement idempotency of
407/// CreatePermission requests over UDP using the "stateless stack approach".
408/// Retransmitted CreatePermission requests will simply refresh the
409/// permissions.
410async fn create_permission<T>(req: Request<'_, '_, T, Message<'_>>) -> Option<RouteResult>
411where
412 T: ServiceHandler,
413{
414 let Some((username, password)) = req.verify().await else {
415 return reject(req, ErrorType::Unauthorized);
416 };
417
418 let mut ports = Vec::with_capacity(15);
419 for it in req.payload.get_all::<XorPeerAddress>() {
420 if !req.verify_ip(&it) {
421 return reject(req, ErrorType::PeerAddressFamilyMismatch);
422 }
423
424 ports.push(it.port());
425 }
426
427 if !req.state.manager.create_permission(&req.state.id, &ports) {
428 return reject(req, ErrorType::Forbidden);
429 }
430
431 req.state
432 .handler
433 .on_create_permission(&req.state.id, username, &ports);
434
435 {
436 MessageEncoder::extend(CREATE_PERMISSION_RESPONSE, req.payload, req.response_buffer)
437 .flush(Some(&password))
438 .ok()?;
439 }
440
441 Some(RouteResult {
442 method: Some(CREATE_PERMISSION_RESPONSE),
443 relay: None,
444 })
445}
446
447/// The server MAY impose restrictions on the IP address and port values
448/// allowed in the XOR-PEER-ADDRESS attribute; if a value is not allowed,
449/// the server rejects the request with a 403 (Forbidden) error.
450///
451/// If the request is valid, but the server is unable to fulfill the
452/// request due to some capacity limit or similar, the server replies
453/// with a 508 (Insufficient Capacity) error.
454///
455/// Otherwise, the server replies with a ChannelBind success response.
456/// There are no required attributes in a successful ChannelBind
457/// response.
458///
459/// If the server can satisfy the request, then the server creates or
460/// refreshes the channel binding using the channel number in the
461/// CHANNEL-NUMBER attribute and the transport address in the XOR-PEER-
462/// ADDRESS attribute. The server also installs or refreshes a
463/// permission for the IP address in the XOR-PEER-ADDRESS attribute as
464/// described in Section 9.
465///
466/// NOTE: A server need not do anything special to implement
467/// idempotency of ChannelBind requests over UDP using the
468/// "stateless stack approach". Retransmitted ChannelBind requests
469/// will simply refresh the channel binding and the corresponding
470/// permission. Furthermore, the client must wait 5 minutes before
471/// binding a previously bound channel number or peer address to a
472/// different channel, eliminating the possibility that the
473/// transaction would initially fail but succeed on a
474/// retransmission.
475async fn channel_bind<T>(req: Request<'_, '_, T, Message<'_>>) -> Option<RouteResult>
476where
477 T: ServiceHandler,
478{
479 let Some(peer) = req.payload.get::<XorPeerAddress>() else {
480 return reject(req, ErrorType::BadRequest);
481 };
482
483 if !req.verify_ip(&peer) {
484 return reject(req, ErrorType::PeerAddressFamilyMismatch);
485 }
486
487 let Some(number) = req.payload.get::<ChannelNumber>() else {
488 return reject(req, ErrorType::BadRequest);
489 };
490
491 if !(0x4000..=0xFFFF).contains(&number) {
492 return reject(req, ErrorType::BadRequest);
493 }
494
495 let Some((username, password)) = req.verify().await else {
496 return reject(req, ErrorType::Unauthorized);
497 };
498
499 if !req
500 .state
501 .manager
502 .bind_channel(&req.state.id, peer.port(), number)
503 {
504 return reject(req, ErrorType::Forbidden);
505 }
506
507 req.state
508 .handler
509 .on_channel_bind(&req.state.id, username, number);
510
511 {
512 MessageEncoder::extend(CHANNEL_BIND_RESPONSE, req.payload, req.response_buffer)
513 .flush(Some(&password))
514 .ok()?;
515 }
516
517 Some(RouteResult {
518 method: Some(CHANNEL_BIND_RESPONSE),
519 relay: None,
520 })
521}
522
523/// When the server receives a Send indication, it processes as per
524/// [Section 5](https://tools.ietf.org/html/rfc8656#section-5) plus
525/// the specific rules mentioned here.
526///
527/// The message is first checked for validity. The Send indication MUST
528/// contain both an XOR-PEER-ADDRESS attribute and a DATA attribute. If
529/// one of these attributes is missing or invalid, then the message is
530/// discarded. Note that the DATA attribute is allowed to contain zero
531/// bytes of data.
532///
533/// The Send indication may also contain the DONT-FRAGMENT attribute. If
534/// the server is unable to set the DF bit on outgoing UDP datagrams when
535/// this attribute is present, then the server acts as if the DONT-
536/// FRAGMENT attribute is an unknown comprehension-required attribute
537/// (and thus the Send indication is discarded).
538///
539/// The server also checks that there is a permission installed for the
540/// IP address contained in the XOR-PEER-ADDRESS attribute. If no such
541/// permission exists, the message is discarded. Note that a Send
542/// indication never causes the server to refresh the permission.
543///
544/// The server MAY impose restrictions on the IP address and port values
545/// allowed in the XOR-PEER-ADDRESS attribute; if a value is not allowed,
546/// the server silently discards the Send indication.
547///
548/// If everything is OK, then the server forms a UDP datagram as follows:
549///
550/// * the source transport address is the relayed transport address of the
551/// allocation, where the allocation is determined by the 5-tuple on which the
552/// Send indication arrived;
553///
554/// * the destination transport address is taken from the XOR-PEER-ADDRESS
555/// attribute;
556///
557/// * the data following the UDP header is the contents of the value field of
558/// the DATA attribute.
559///
560/// The handling of the DONT-FRAGMENT attribute (if present), is
561/// described in Sections [14](https://tools.ietf.org/html/rfc8656#section-14)
562/// and [15](https://tools.ietf.org/html/rfc8656#section-15).
563///
564/// The resulting UDP datagram is then sent to the peer.
565#[rustfmt::skip]
566fn indication<T>(req: Request<'_, '_, T, Message<'_>>) -> Option<RouteResult>
567where
568 T: ServiceHandler,
569{
570 let peer = req.payload.get::<XorPeerAddress>()?;
571 let data = req.payload.get::<Data>()?;
572
573 let (local_port, relay) = req.state.manager.get_port_relay_address(&req.state.id, peer.port())?;
574
575 {
576 let mut message = MessageEncoder::extend(DATA_INDICATION, req.payload, req.response_buffer);
577
578 message.append::<XorPeerAddress>(SocketAddr::new(req.state.id.external.ip(), local_port));
579 message.append::<Data>(data);
580 message.flush(None).ok()?;
581 }
582
583 Some(RouteResult {
584 method: Some(DATA_INDICATION),
585 relay: Some(relay),
586 })
587}
588
589/// If the server receives a Refresh Request with a REQUESTED-ADDRESS-
590/// FAMILY attribute and the attribute value does not match the address
591/// family of the allocation, the server MUST reply with a 443 (Peer
592/// Address Family Mismatch) Refresh error response.
593///
594/// The server computes a value called the "desired lifetime" as follows:
595/// if the request contains a LIFETIME attribute and the attribute value
596/// is zero, then the "desired lifetime" is zero. Otherwise, if the
597/// request contains a LIFETIME attribute, then the server computes the
598/// minimum of the client's requested lifetime and the server's maximum
599/// allowed lifetime. If this computed value is greater than the default
600/// lifetime, then the "desired lifetime" is the computed value.
601/// Otherwise, the "desired lifetime" is the default lifetime.
602///
603/// Subsequent processing depends on the "desired lifetime" value:
604///
605/// * If the "desired lifetime" is zero, then the request succeeds and the
606/// allocation is deleted.
607///
608/// * If the "desired lifetime" is non-zero, then the request succeeds and the
609/// allocation's time-to-expiry is set to the "desired lifetime".
610///
611/// If the request succeeds, then the server sends a success response
612/// containing:
613///
614/// * A LIFETIME attribute containing the current value of the time-to-expiry
615/// timer.
616///
617/// NOTE: A server need not do anything special to implement
618/// idempotency of Refresh requests over UDP using the "stateless
619/// stack approach". Retransmitted Refresh requests with a non-
620/// zero "desired lifetime" will simply refresh the allocation. A
621/// retransmitted Refresh request with a zero "desired lifetime"
622/// will cause a 437 (Allocation Mismatch) response if the
623/// allocation has already been deleted, but the client will treat
624/// this as equivalent to a success response (see below).
625async fn refresh<T>(req: Request<'_, '_, T, Message<'_>>) -> Option<RouteResult>
626where
627 T: ServiceHandler,
628{
629 let Some((username, password)) = req.verify().await else {
630 return reject(req, ErrorType::Unauthorized);
631 };
632
633 let lifetime = req
634 .payload
635 .get::<Lifetime>()
636 .unwrap_or(DEFAULT_SESSION_LIFETIME as u32);
637 if !req.state.manager.refresh(&req.state.id, lifetime) {
638 return reject(req, ErrorType::AllocationMismatch);
639 }
640
641 req.state
642 .handler
643 .on_refresh(&req.state.id, username, lifetime);
644
645 {
646 let mut message =
647 MessageEncoder::extend(REFRESH_RESPONSE, req.payload, req.response_buffer);
648
649 message.append::<Lifetime>(lifetime);
650 message.flush(Some(&password)).ok()?;
651 }
652
653 Some(RouteResult {
654 method: Some(REFRESH_RESPONSE),
655 relay: None,
656 })
657}
658
659/// If the ChannelData message is received on a channel that is not bound
660/// to any peer, then the message is silently discarded.
661///
662/// On the client, it is RECOMMENDED that the client discard the
663/// ChannelData message if the client believes there is no active
664/// permission towards the peer. On the server, the receipt of a
665/// ChannelData message MUST NOT refresh either the channel binding or
666/// the permission towards the peer.
667///
668/// On the server, if no errors are detected, the server relays the
669/// application data to the peer by forming a UDP datagram as follows:
670///
671/// * the source transport address is the relayed transport address of the
672/// allocation, where the allocation is determined by the 5-tuple on which the
673/// ChannelData message arrived;
674///
675/// * the destination transport address is the transport address to which the
676/// channel is bound;
677///
678/// * the data following the UDP header is the contents of the data field of the
679/// ChannelData message.
680///
681/// The resulting UDP datagram is then sent to the peer. Note that if
682/// the Length field in the ChannelData message is 0, then there will be
683/// no data in the UDP datagram, but the UDP datagram is still formed and
684/// sent [(Section 4.1 of [RFC6263])](https://tools.ietf.org/html/rfc6263#section-4.1).
685fn channel_data<T>(req: Request<'_, '_, T, ChannelData<'_>>) -> Option<RouteResult>
686where
687 T: ServiceHandler,
688{
689 let (relay_channel, relay) = req
690 .state
691 .manager
692 .get_channel_relay_address(&req.state.id, req.payload.number())?;
693
694 {
695 ChannelData::new(relay_channel, req.payload.bytes()).encode(req.response_buffer);
696 }
697
698 Some(RouteResult {
699 relay: Some(relay),
700 method: None,
701 })
702}