turn_rs/processor/
allocate.rs

1use super::{verify_message, Context, Response};
2use crate::{StunClass, SOFTWARE};
3
4use std::{net::SocketAddr, sync::Arc};
5
6use bytes::BytesMut;
7use faster_stun::attribute::ErrKind::*;
8use faster_stun::attribute::*;
9use faster_stun::*;
10
11/// return allocate error response
12#[inline(always)]
13fn reject<'a>(
14    ctx: Context,
15    reader: MessageReader,
16    bytes: &'a mut BytesMut,
17    err: ErrKind,
18) -> Result<Option<Response<'a>>, StunError> {
19    let method = Method::Allocate(Kind::Error);
20    let nonce = ctx.env.router.get_nonce(&ctx.addr);
21    let mut pack = MessageWriter::extend(method, &reader, bytes);
22    pack.append::<ErrorCode>(Error::from(err));
23    pack.append::<Realm>(&ctx.env.realm);
24    pack.append::<Nonce>(&nonce);
25    pack.flush(None)?;
26    Ok(Some(Response::new(bytes, StunClass::Msg, None, None)))
27}
28
29/// return allocate ok response
30///
31/// NOTE: The use of randomized port assignments to avoid certain
32/// types of attacks is described in [RFC6056].  It is RECOMMENDED
33/// that a TURN server implement a randomized port assignment
34/// algorithm from [RFC6056].  This is especially applicable to
35/// servers that choose to pre-allocate a number of ports from the
36/// underlying OS and then later assign them to allocations; for
37/// example, a server may choose this technique to implement the
38/// EVEN-PORT attribute.
39#[inline(always)]
40fn resolve<'a>(
41    ctx: &Context,
42    reader: &MessageReader,
43    key: &[u8; 16],
44    port: u16,
45    bytes: &'a mut BytesMut,
46) -> Result<Option<Response<'a>>, StunError> {
47    let method = Method::Allocate(Kind::Response);
48    let alloc_addr = Arc::new(SocketAddr::new(ctx.env.external.ip(), port));
49    let mut pack = MessageWriter::extend(method, reader, bytes);
50    pack.append::<XorRelayedAddress>(*alloc_addr.as_ref());
51    pack.append::<XorMappedAddress>(ctx.addr);
52    pack.append::<Lifetime>(600);
53    pack.append::<Software>(SOFTWARE);
54    pack.flush(Some(key))?;
55    Ok(Some(Response::new(bytes, StunClass::Msg, None, None)))
56}
57
58/// process allocate request
59///
60/// [rfc8489](https://tools.ietf.org/html/rfc8489)
61///
62/// In all cases, the server SHOULD only allocate ports from the range
63/// 49152 - 65535 (the Dynamic and/or Private Port range [PORT-NUMBERS]),
64/// unless the TURN server application knows, through some means not
65/// specified here, that other applications running on the same host as
66/// the TURN server application will not be impacted by allocating ports
67/// outside this range.  This condition can often be satisfied by running
68/// the TURN server application on a dedicated machine and/or by
69/// arranging that any other applications on the machine allocate ports
70/// before the TURN server application starts.  In any case, the TURN
71/// server SHOULD NOT allocate ports in the range 0 - 1023 (the Well-
72/// Known Port range) to discourage clients from using TURN to run
73/// standard services.
74pub async fn process<'a>(
75    ctx: Context,
76    reader: MessageReader<'_, '_>,
77    bytes: &'a mut BytesMut,
78) -> Result<Option<Response<'a>>, StunError> {
79    if reader.get::<ReqeestedTransport>().is_none() {
80        return reject(ctx, reader, bytes, ServerError);
81    }
82
83    let (username, key) = match verify_message(&ctx, &reader).await {
84        None => return reject(ctx, reader, bytes, Unauthorized),
85        Some(ret) => ret,
86    };
87
88    let port = match ctx.env.router.alloc_port(&ctx.addr) {
89        None => return reject(ctx, reader, bytes, Unauthorized),
90        Some(p) => p,
91    };
92
93    ctx.env.observer.allocated(&ctx.addr, username, port);
94    resolve(&ctx, &reader, &key, port, bytes)
95}