turn_rs/processor/
binding.rs

1use super::{Context, Response};
2use crate::{StunClass, SOFTWARE};
3
4use bytes::BytesMut;
5use faster_stun::attribute::*;
6use faster_stun::*;
7
8/// process binding request
9///
10/// [rfc8489](https://tools.ietf.org/html/rfc8489)
11///
12/// In the Binding request/response transaction, a Binding request is
13/// sent from a STUN client to a STUN server.  When the Binding request
14/// arrives at the STUN server, it may have passed through one or more
15/// NATs between the STUN client and the STUN server (in Figure 1, there
16/// are two such NATs).  As the Binding request message passes through a
17/// NAT, the NAT will modify the source transport address (that is, the
18/// source IP address and the source port) of the packet.  As a result,
19/// the source transport address of the request received by the server
20/// will be the public IP address and port created by the NAT closest to
21/// the server.  This is called a "reflexive transport address".  The
22/// STUN server copies that source transport address into an XOR-MAPPED-
23/// ADDRESS attribute in the STUN Binding response and sends the Binding
24/// response back to the STUN client.  As this packet passes back through
25/// a NAT, the NAT will modify the destination transport address in the
26/// IP header, but the transport address in the XOR-MAPPED-ADDRESS
27/// attribute within the body of the STUN response will remain untouched.
28/// In this way, the client can learn its reflexive transport address
29/// allocated by the outermost NAT with respect to the STUN server.
30pub fn process<'a>(
31    ctx: Context,
32    payload: MessageReader,
33    bytes: &'a mut BytesMut,
34) -> Result<Option<Response<'a>>, StunError> {
35    let method = Method::Binding(Kind::Response);
36    let mut pack = MessageWriter::extend(method, &payload, bytes);
37    pack.append::<XorMappedAddress>(ctx.addr);
38    pack.append::<MappedAddress>(ctx.addr);
39    pack.append::<ResponseOrigin>(*ctx.env.external.as_ref());
40    pack.append::<Software>(SOFTWARE);
41    pack.flush(None)?;
42    ctx.env.observer.binding(&ctx.addr);
43    Ok(Some(Response::new(bytes, StunClass::Msg, None, None)))
44}