Skip to main content

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}