turn_rs/processor/
channel_bind.rs1use 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#[inline(always)]
11fn reject<'a>(
12 ctx: Context,
13 reader: MessageReader,
14 bytes: &'a mut BytesMut,
15 err: ErrKind,
16) -> Result<Option<Response<'a>>, StunError> {
17 let method = Method::ChannelBind(Kind::Error);
18 let mut pack = MessageWriter::extend(method, &reader, bytes);
19 pack.append::<ErrorCode>(Error::from(err));
20 pack.append::<Realm>(&ctx.env.realm);
21 pack.flush(None)?;
22 Ok(Some(Response::new(bytes, StunClass::Msg, None, None)))
23}
24
25#[inline(always)]
27fn resolve<'a>(
28 reader: &MessageReader,
29 key: &[u8; 16],
30 bytes: &'a mut BytesMut,
31) -> Result<Option<Response<'a>>, StunError> {
32 let method = Method::ChannelBind(Kind::Response);
33 MessageWriter::extend(method, reader, bytes).flush(Some(key))?;
34 Ok(Some(Response::new(bytes, StunClass::Msg, None, None)))
35}
36
37pub async fn process<'a>(
68 ctx: Context,
69 reader: MessageReader<'_, '_>,
70 bytes: &'a mut BytesMut,
71) -> Result<Option<Response<'a>>, StunError> {
72 let peer = match reader.get::<XorPeerAddress>() {
73 None => return reject(ctx, reader, bytes, BadRequest),
74 Some(a) => a,
75 };
76
77 let number = match reader.get::<ChannelNumber>() {
78 None => return reject(ctx, reader, bytes, BadRequest),
79 Some(c) => c,
80 };
81
82 if ctx.env.external.ip() != peer.ip() {
83 return reject(ctx, reader, bytes, Forbidden);
84 }
85
86 if !(0x4000..=0x7FFF).contains(&number) {
87 return reject(ctx, reader, bytes, BadRequest);
88 }
89
90 let (username, key) = match verify_message(&ctx, &reader).await {
91 None => return reject(ctx, reader, bytes, Unauthorized),
92 Some(ret) => ret,
93 };
94
95 if ctx
96 .env
97 .router
98 .bind_channel(&ctx.addr, peer.port(), number)
99 .is_none()
100 {
101 return reject(ctx, reader, bytes, InsufficientCapacity);
102 }
103
104 ctx.env.observer.channel_bind(&ctx.addr, username, number);
105 resolve(&reader, &key, bytes)
106}