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}