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