turn_server/turn/operations/binding.rs
1use super::{Observer, Requet, Response, ResponseMethod};
2
3use crate::stun::{
4 MessageEncoder, MessageRef,
5 attribute::{MappedAddress, ResponseOrigin, Software, XorMappedAddress},
6 method::BINDING_RESPONSE,
7};
8
9/// process binding request
10///
11/// [rfc8489](https://tools.ietf.org/html/rfc8489)
12///
13/// In the Binding request/response transaction, a Binding request is
14/// sent from a STUN client to a STUN server. When the Binding request
15/// arrives at the STUN server, it may have passed through one or more
16/// NATs between the STUN client and the STUN server (in Figure 1, there
17/// are two such NATs). As the Binding request message passes through a
18/// NAT, the NAT will modify the source transport address (that is, the
19/// source IP address and the source port) of the packet. As a result,
20/// the source transport address of the request received by the server
21/// will be the public IP address and port created by the NAT closest to
22/// the server. This is called a "reflexive transport address". The
23/// STUN server copies that source transport address into an XOR-MAPPED-
24/// ADDRESS attribute in the STUN Binding response and sends the Binding
25/// response back to the STUN client. As this packet passes back through
26/// a NAT, the NAT will modify the destination transport address in the
27/// IP header, but the transport address in the XOR-MAPPED-ADDRESS
28/// attribute within the body of the STUN response will remain untouched.
29/// In this way, the client can learn its reflexive transport address
30/// allocated by the outermost NAT with respect to the STUN server.
31pub fn process<'a, T: Observer>(req: Requet<'_, 'a, T, MessageRef<'_>>) -> Option<Response<'a>> {
32 {
33 let mut message = MessageEncoder::extend(BINDING_RESPONSE, &req.message, req.bytes);
34 message.append::<XorMappedAddress>(req.address.address);
35 message.append::<MappedAddress>(req.address.address);
36 message.append::<ResponseOrigin>(req.service.interface);
37 message.append::<Software>(&req.service.software);
38 message.flush(None).ok()?;
39 }
40
41 Some(Response {
42 method: ResponseMethod::Stun(BINDING_RESPONSE),
43 bytes: req.bytes,
44 endpoint: None,
45 relay: None,
46 })
47}