turn_rs/processor/
indication.rs

1use std::net::SocketAddr;
2
3use super::{ip_is_local, Context, Response};
4use crate::StunClass;
5
6use bytes::BytesMut;
7use faster_stun::attribute::{Data, XorPeerAddress};
8use faster_stun::{MessageReader, MessageWriter, Method, StunError};
9
10/// process send indication request
11///
12/// When the server receives a Send indication, it processes as per
13/// [Section 5](https://tools.ietf.org/html/rfc8656#section-5) plus
14/// the specific rules mentioned here.
15///
16/// The message is first checked for validity.  The Send indication MUST
17/// contain both an XOR-PEER-ADDRESS attribute and a DATA attribute.  If
18/// one of these attributes is missing or invalid, then the message is
19/// discarded.  Note that the DATA attribute is allowed to contain zero
20/// bytes of data.
21///
22/// The Send indication may also contain the DONT-FRAGMENT attribute.  If
23/// the server is unable to set the DF bit on outgoing UDP datagrams when
24/// this attribute is present, then the server acts as if the DONT-
25/// FRAGMENT attribute is an unknown comprehension-required attribute
26/// (and thus the Send indication is discarded).
27///
28/// The server also checks that there is a permission installed for the
29/// IP address contained in the XOR-PEER-ADDRESS attribute.  If no such
30/// permission exists, the message is discarded.  Note that a Send
31/// indication never causes the server to refresh the permission.
32///
33/// The server MAY impose restrictions on the IP address and port values
34/// allowed in the XOR-PEER-ADDRESS attribute; if a value is not allowed,
35/// the server silently discards the Send indication.
36///
37/// If everything is OK, then the server forms a UDP datagram as follows:
38///
39/// * the source transport address is the relayed transport address of
40/// the allocation, where the allocation is determined by the 5-tuple
41/// on which the Send indication arrived;
42///
43/// * the destination transport address is taken from the XOR-PEER-
44/// ADDRESS attribute;
45///
46/// * the data following the UDP header is the contents of the value
47/// field of the DATA attribute.
48///
49/// The handling of the DONT-FRAGMENT attribute (if present), is
50/// described in Sections [14](https://tools.ietf.org/html/rfc8656#section-14)
51/// and [15](https://tools.ietf.org/html/rfc8656#section-15).
52///
53/// The resulting UDP datagram is then sent to the peer.
54pub async fn process<'a>(
55    ctx: Context,
56    reader: MessageReader<'_, '_>,
57    bytes: &'a mut BytesMut,
58) -> Result<Option<Response<'a>>, StunError> {
59    let peer = match reader.get::<XorPeerAddress>() {
60        None => return Ok(None),
61        Some(x) => x,
62    };
63
64    if !ip_is_local(&ctx, &peer) {
65        return Ok(None);
66    }
67
68    let data = match reader.get::<Data>() {
69        None => return Ok(None),
70        Some(x) => x,
71    };
72
73    let addr = match ctx.env.router.get_port_bound(peer.port()) {
74        None => return Ok(None),
75        Some(a) => a,
76    };
77
78    let port = match ctx.env.router.get_bound_port(&ctx.addr, &addr) {
79        None => return Ok(None),
80        Some(p) => p,
81    };
82
83    let interface = match ctx.env.router.get_interface(&addr) {
84        None => return Ok(None),
85        Some(p) => p,
86    };
87
88    let method = Method::DataIndication;
89    let mut pack = MessageWriter::extend(method, &reader, bytes);
90    pack.append::<XorPeerAddress>(SocketAddr::new(interface.external.ip(), port));
91    pack.append::<Data>(data);
92    pack.flush(None)?;
93
94    let to = (&ctx.env.interface != &interface.addr).then(|| interface.addr);
95    Ok(Some(Response::new(bytes, StunClass::Msg, Some(addr), to)))
96}