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}