turn_rs/processor/
refresh.rs

1use super::{verify_message, Context, Response};
2use crate::StunClass;
3
4use bytes::BytesMut;
5use faster_stun::attribute::ErrKind::*;
6use faster_stun::attribute::*;
7use faster_stun::*;
8
9/// return refresh error response
10#[inline(always)]
11fn reject<'a>(
12    reader: MessageReader,
13    bytes: &'a mut BytesMut,
14    err: ErrKind,
15) -> Result<Option<Response<'a>>, StunError> {
16    let method = Method::Refresh(Kind::Error);
17    let mut pack = MessageWriter::extend(method, &reader, bytes);
18    pack.append::<ErrorCode>(Error::from(err));
19    pack.flush(None)?;
20    Ok(Some(Response::new(bytes, StunClass::Msg, None, None)))
21}
22
23/// return refresh ok response
24#[inline(always)]
25pub fn resolve<'a>(
26    reader: &MessageReader,
27    lifetime: u32,
28    key: &[u8; 16],
29    bytes: &'a mut BytesMut,
30) -> Result<Option<Response<'a>>, StunError> {
31    let method = Method::Refresh(Kind::Response);
32    let mut pack = MessageWriter::extend(method, reader, bytes);
33    pack.append::<Lifetime>(lifetime);
34    pack.flush(Some(key))?;
35    Ok(Some(Response::new(bytes, StunClass::Msg, None, None)))
36}
37
38/// process refresh request
39///
40/// If the server receives a Refresh Request with a REQUESTED-ADDRESS-
41/// FAMILY attribute and the attribute value does not match the address
42/// family of the allocation, the server MUST reply with a 443 (Peer
43/// Address Family Mismatch) Refresh error response.
44///
45/// The server computes a value called the "desired lifetime" as follows:
46/// if the request contains a LIFETIME attribute and the attribute value
47/// is zero, then the "desired lifetime" is zero.  Otherwise, if the
48/// request contains a LIFETIME attribute, then the server computes the
49/// minimum of the client's requested lifetime and the server's maximum
50/// allowed lifetime.  If this computed value is greater than the default
51/// lifetime, then the "desired lifetime" is the computed value.
52/// Otherwise, the "desired lifetime" is the default lifetime.
53///
54/// Subsequent processing depends on the "desired lifetime" value:
55///
56/// * If the "desired lifetime" is zero, then the request succeeds and
57/// the allocation is deleted.
58///
59/// * If the "desired lifetime" is non-zero, then the request succeeds
60/// and the allocation's time-to-expiry is set to the "desired
61/// lifetime".
62///
63/// If the request succeeds, then the server sends a success response
64/// containing:
65///
66/// * A LIFETIME attribute containing the current value of the time-to-
67/// expiry timer.
68///
69/// NOTE: A server need not do anything special to implement
70/// idempotency of Refresh requests over UDP using the "stateless
71/// stack approach".  Retransmitted Refresh requests with a non-
72/// zero "desired lifetime" will simply refresh the allocation.  A
73/// retransmitted Refresh request with a zero "desired lifetime"
74/// will cause a 437 (Allocation Mismatch) response if the
75/// allocation has already been deleted, but the client will treat
76/// this as equivalent to a success response (see below).
77pub async fn process<'a>(
78    ctx: Context,
79    reader: MessageReader<'_, '_>,
80    bytes: &'a mut BytesMut,
81) -> Result<Option<Response<'a>>, StunError> {
82    let (username, key) = match verify_message(&ctx, &reader).await {
83        None => return reject(reader, bytes, Unauthorized),
84        Some(ret) => ret,
85    };
86
87    let time = reader.get::<Lifetime>().unwrap_or(600);
88    ctx.env.observer.refresh(&ctx.addr, username, time);
89    ctx.env.router.refresh(&ctx.addr, time);
90    resolve(&reader, time, &key, bytes)
91}