stun_codec-0.3.4/.cargo_vcs_info.json0000644000000001360000000000100131660ustar { "git": { "sha1": "29e1a317dc3ca465eb0d71d4d3e7e863d70b95cf" }, "path_in_vcs": "" }stun_codec-0.3.4/.github/actions-rs/grcov.yml000064400000000000000000000000551046102023000172430ustar 00000000000000ignore-not-existing: true ignore: - "../*" stun_codec-0.3.4/.github/workflows/ci.yml000064400000000000000000000061331046102023000164740ustar 00000000000000# Based on https://github.com/actions-rs/meta/blob/master/recipes/quickstart.md name: CI on: push: branches: [master] pull_request: jobs: check: name: Check runs-on: ubuntu-latest strategy: matrix: toolchain: [stable, beta, nightly] steps: - name: Checkout sources uses: actions/checkout@v2 - name: Install ${{ matrix.toolchain }} toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} override: true - name: Run cargo check uses: actions-rs/cargo@v1 with: command: check args: --all-features --all test: name: Test Suite runs-on: ubuntu-latest strategy: matrix: toolchain: [stable, beta, nightly] steps: - name: Checkout sources uses: actions/checkout@v2 - name: Install ${{ matrix.toolchain }} toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} override: true - name: Run cargo test uses: actions-rs/cargo@v1 with: command: test args: --all-features --all lints: name: Lints runs-on: ubuntu-latest strategy: matrix: toolchain: [stable, beta, nightly] steps: - name: Checkout sources uses: actions/checkout@v2 - name: Install ${{ matrix.toolchain }} toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} override: true components: rustfmt, clippy - name: Run cargo fmt uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check - name: Run cargo clippy uses: actions-rs/cargo@v1 with: command: clippy args: --all-features --all -- -D warnings grcov: name: Coverage runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install toolchain uses: actions-rs/toolchain@v1 with: toolchain: nightly override: true - name: Execute tests uses: actions-rs/cargo@v1 with: command: test args: --all --all-features env: CARGO_INCREMENTAL: 0 RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" RUSTDOCFLAGS: "-Cpanic=abort" - name: Gather coverage data id: coverage uses: actions-rs/grcov@v0.1 - name: Coveralls upload uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel: true path-to-lcov: ${{ steps.coverage.outputs.report }} grcov_finalize: runs-on: ubuntu-latest needs: grcov steps: - name: Coveralls finalization uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel-finished: true stun_codec-0.3.4/.gitignore000064400000000000000000000000361046102023000137450ustar 00000000000000/target **/*.rs.bk Cargo.lock stun_codec-0.3.4/Cargo.toml0000644000000022100000000000100111570ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "stun_codec" version = "0.3.4" authors = ["Takeru Ohta "] description = "Encoders and decoders for STUN (RFC 5389) and its extensions" homepage = "https://github.com/sile/stun_codec" readme = "README.md" keywords = ["STUN"] categories = ["encoding"] license = "MIT" repository = "https://github.com/sile/stun_codec" [dependencies.bytecodec] version = "0.4" [dependencies.byteorder] version = "1" [dependencies.crc] version = "3" [dependencies.hmac] version = "0.12.1" [dependencies.md5] version = "0.7" [dependencies.sha1] version = "0.10.6" [dependencies.trackable] version = "1" [badges.coveralls] repository = "sile/stun_codec" stun_codec-0.3.4/Cargo.toml.orig000064400000000000000000000010411046102023000146410ustar 00000000000000[package] name = "stun_codec" version = "0.3.4" authors = ["Takeru Ohta "] description = "Encoders and decoders for STUN (RFC 5389) and its extensions" homepage = "https://github.com/sile/stun_codec" repository = "https://github.com/sile/stun_codec" readme = "README.md" keywords = ["STUN"] categories = ["encoding"] license = "MIT" edition = "2021" [badges] coveralls = {repository = "sile/stun_codec"} [dependencies] bytecodec = "0.4" byteorder = "1" crc = "3" hmac = "0.12.1" md5 = "0.7" sha1 = "0.10.6" trackable = "1" stun_codec-0.3.4/LICENSE000064400000000000000000000021051046102023000127610ustar 00000000000000The MIT License Copyright (c) 2018 Takeru Ohta Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. stun_codec-0.3.4/README.md000064400000000000000000000050451046102023000132410ustar 00000000000000stun_codec =========== [![stun_codec](https://img.shields.io/crates/v/stun_codec.svg)](https://crates.io/crates/stun_codec) [![Documentation](https://docs.rs/stun_codec/badge.svg)](https://docs.rs/stun_codec) [![Actions Status](https://github.com/sile/stun_codec/workflows/CI/badge.svg)](https://github.com/sile/stun_codec/actions) [![Coverage Status](https://coveralls.io/repos/github/sile/stun_codec/badge.svg?branch=master)](https://coveralls.io/github/sile/stun_codec?branch=master) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) Encoders and decoders for [STUN (RFC 5389)][RFC 5389] and its extensions. [Documentation](https://docs.rs/stun_codec) Examples -------- ```rust use bytecodec::{DecodeExt, EncodeExt, Error}; use stun_codec::{Message, MessageClass, MessageDecoder, MessageEncoder, TransactionId}; use stun_codec::rfc5389::{attributes::Software, methods::BINDING, Attribute}; // Creates a message let mut message = Message::new(MessageClass::Request, BINDING, TransactionId::new([3; 12])); message.add_attribute(Attribute::Software(Software::new("foo".to_owned())?)); // Encodes the message let mut encoder = MessageEncoder::new(); let bytes = encoder.encode_into_bytes(message.clone())?; assert_eq!( bytes, [ 0, 1, 0, 8, 33, 18, 164, 66, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 128, 34, 0, 3, 102, 111, 111, 0 ] ); // Decodes the message let mut decoder = MessageDecoder::::new(); let decoded = decoder.decode_from_bytes(&bytes)?.map_err(Error::from)?; assert_eq!(decoded.class(), message.class()); assert_eq!(decoded.method(), message.method()); assert_eq!(decoded.transaction_id(), message.transaction_id()); assert!(decoded.attributes().eq(message.attributes())); ``` References ---------- - [RFC 5245 - Interactive Connectivity Establishment (ICE)][RFC 5245] - [RFC 5389 - Session Traversal Utilities for NAT (STUN)][RFC 5389] - [RFC 5769 - Test Vectors for Session Traversal Utilities for NAT (STUN)][RFC 5769] - [RFC 5780 - NAT Behavior Discovery Using Session Traversal Utilities for NAT][RFC 5780] - [RFC 8016 - Mobility with Traversal Using Relays around NAT (TURN)][RFC 8016] - [RFC 8656 - Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)][RFC 8656] [RFC 5245]: https://tools.ietf.org/html/rfc5245 [RFC 5389]: https://tools.ietf.org/html/rfc5389 [RFC 5769]: https://tools.ietf.org/html/rfc5769 [RFC 5780]: https://tools.ietf.org/html/rfc5780 [RFC 8016]: https://tools.ietf.org/html/rfc8016 [RFC 8656]: https://tools.ietf.org/html/rfc8656 stun_codec-0.3.4/src/attribute.rs000064400000000000000000000442171046102023000151260ustar 00000000000000use crate::message::Message; use bytecodec::bytes::{BytesDecoder, BytesEncoder, RemainingBytesDecoder}; use bytecodec::combinator::{Length, Peekable}; use bytecodec::fixnum::{U16beDecoder, U16beEncoder}; use bytecodec::{ByteCount, Decode, Encode, Eos, ErrorKind, Result, SizedEncode, TryTaggedDecode}; use std::fmt; use crate::{rfc5389, rfc5766}; #[derive(Debug)] pub enum MyAttribute { Rfc5389(rfc5389::Attribute), Rfc5766(rfc5766::Attribute), } #[derive(Debug, Default)] pub struct MyAttributeDecoder { rfc5389: rfc5389::AttributeDecoder, rfc5766: rfc5766::AttributeDecoder, index: usize, } impl Decode for MyAttributeDecoder { type Item = MyAttribute; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { match self.index { 1 => track!(self.rfc5389.decode(buf, eos)), 2 => track!(self.rfc5766.decode(buf, eos)), _ => track_panic!(ErrorKind::InconsistentState), } } fn finish_decoding(&mut self) -> Result { let item = match self.index { 1 => track!(self.rfc5389.finish_decoding()).map(MyAttribute::Rfc5389)?, 2 => track!(self.rfc5766.finish_decoding()).map(MyAttribute::Rfc5766)?, _ => track_panic!(ErrorKind::InconsistentState), }; self.index = 0; Ok(item) } fn requiring_bytes(&self) -> ByteCount { match self.index { 1 => self.rfc5389.requiring_bytes(), 2 => self.rfc5766.requiring_bytes(), _ => ByteCount::Finite(0), } } fn is_idle(&self) -> bool { match self.index { 1 => self.rfc5389.is_idle(), 2 => self.rfc5766.is_idle(), _ => true, } } } impl TryTaggedDecode for MyAttributeDecoder { type Tag = AttributeType; fn try_start_decoding(&mut self, tag: Self::Tag) -> Result { track_assert_eq!(self.index, 0, ErrorKind::InconsistentState); if track!(self.rfc5389.try_start_decoding(tag))? { self.index = 1; Ok(true) } else if track!(self.rfc5766.try_start_decoding(tag))? { self.index = 2; Ok(true) } else { Ok(false) } } } #[derive(Debug, Default)] pub struct MyAttributeEncoder { rfc5389: rfc5389::AttributeEncoder, rfc5766: rfc5766::AttributeEncoder, } impl Encode for MyAttributeEncoder { type Item = MyAttribute; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { let mut offset = 0; bytecodec_try_encode!(self.rfc5389, offset, buf, eos); bytecodec_try_encode!(self.rfc5766, offset, buf, eos); Ok(offset) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track_assert!(self.is_idle(), ErrorKind::EncoderFull); match item { MyAttribute::Rfc5389(item) => track!(self.rfc5389.start_encoding(item)), MyAttribute::Rfc5766(item) => track!(self.rfc5766.start_encoding(item)), } } fn requiring_bytes(&self) -> ByteCount { self.rfc5389 .requiring_bytes() .add_for_encoding(self.rfc5766.requiring_bytes()) } fn is_idle(&self) -> bool { self.rfc5389.is_idle() && self.rfc5766.is_idle() } } impl SizedEncode for MyAttributeEncoder { fn exact_requiring_bytes(&self) -> u64 { self.rfc5389.exact_requiring_bytes() + self.rfc5766.exact_requiring_bytes() } } /// STUN attribute. /// /// > **Attribute**: The STUN term for a Type-Length-Value (TLV) object that /// > can be added to a STUN message. Attributes are divided into two /// > types: comprehension-required and comprehension-optional. STUN /// > agents can safely ignore comprehension-optional attributes they /// > don't understand, but cannot successfully process a message if it /// > contains comprehension-required attributes that are not /// > understood. /// > /// > [RFC 5389 -- 5. Definitions] /// /// [RFC 5389 -- 5. Definitions]: https://tools.ietf.org/html/rfc5389#section-5 pub trait Attribute: Sized + Clone { /// The decoder of the value part of the attribute. type Decoder: Default + TryTaggedDecode; /// The encoder of the value part of the attribute. type Encoder: Default + SizedEncode; /// Returns the type of the attribute. fn get_type(&self) -> AttributeType; /// This method is called before encoding the attribute. /// /// `message` is the message to which the attribute belongs. /// The message only contains the attributes preceding to `self`. /// /// The default implementation simply returns `Ok(())`. #[allow(unused_variables)] fn before_encode(&mut self, message: &Message) -> Result<()> { Ok(()) } /// This method is called after decoding the attribute and before being appended to the given message. /// /// The default implementation simply returns `Ok(())`. #[allow(unused_variables)] fn after_decode(&mut self, message: &Message) -> Result<()> { Ok(()) } } /// Attribute type. /// /// > Attributes are divided into two /// > types: comprehension-required and comprehension-optional. STUN /// > agents can safely ignore comprehension-optional attributes they /// > don't understand, but cannot successfully process a message if it /// > contains comprehension-required attributes that are not /// > understood. /// > /// > [RFC 5389 -- 5. Definitions] /// > /// > --- /// > /// > A STUN Attribute type is a hex number in the range 0x0000 - 0xFFFF. /// > STUN attribute types in the range 0x0000 - 0x7FFF are considered /// > comprehension-required; STUN attribute types in the range 0x8000 - /// > 0xFFFF are considered comprehension-optional. /// > /// > [RFC 5389 -- 18.2. STUN Attribute Registry] /// /// [RFC 5389 -- 5. Definitions]: https://tools.ietf.org/html/rfc5389#section-5 /// [RFC 5389 -- 18.2. STUN Attribute Registry]: https://tools.ietf.org/html/rfc5389#section-18.2 #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] pub struct AttributeType(u16); impl AttributeType { /// Makes a new `Type` instance which corresponding to `codepoint`. pub fn new(codepoint: u16) -> Self { AttributeType(codepoint) } /// Returns the attribute codepoint corresponding this instance. pub fn as_u16(self) -> u16 { self.0 } /// Returns `true` if this is a comprehension-required type. pub fn is_comprehension_required(self) -> bool { self.0 < 0x8000 } /// Returns `true` if this is a comprehension-optional type. pub fn is_comprehension_optional(self) -> bool { !self.is_comprehension_required() } } impl From for AttributeType { fn from(f: u16) -> Self { Self::new(f) } } /// An [`Attribute`] implementation that has raw value bytes. #[derive(Debug, Clone)] pub struct RawAttribute { attr_type: AttributeType, value: Vec, } impl RawAttribute { /// Makes a new `RawAttribute` instance. pub fn new(attr_type: AttributeType, value: Vec) -> Self { RawAttribute { attr_type, value } } /// Returns a reference to the value bytes of the attribute. pub fn value(&self) -> &[u8] { &self.value } /// Takes ownership of this instance, and returns the value bytes. pub fn into_value(self) -> Vec { self.value } } impl Attribute for RawAttribute { type Decoder = RawAttributeDecoder; type Encoder = RawAttributeEncoder; fn get_type(&self) -> AttributeType { self.attr_type } } /// [`RawAttribute`] decoder. #[derive(Debug, Default)] pub struct RawAttributeDecoder { attr_type: Option, value: RemainingBytesDecoder, } impl RawAttributeDecoder { /// Makes a new `RawAttributeDecoder` instance. pub fn new() -> Self { Self::default() } } impl Decode for RawAttributeDecoder { type Item = RawAttribute; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.value.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { let attr_type = track_assert_some!(self.attr_type.take(), ErrorKind::InconsistentState); let value = track!(self.value.finish_decoding())?; Ok(RawAttribute { attr_type, value }) } fn requiring_bytes(&self) -> ByteCount { self.value.requiring_bytes() } fn is_idle(&self) -> bool { self.value.is_idle() } } impl TryTaggedDecode for RawAttributeDecoder { type Tag = AttributeType; fn try_start_decoding(&mut self, attr_type: Self::Tag) -> Result { self.attr_type = Some(attr_type); Ok(true) } } /// [`RawAttribute`] encoder. #[derive(Debug, Default)] pub struct RawAttributeEncoder { value: BytesEncoder, } impl RawAttributeEncoder { /// Makes a new `RawAttributeEncoder` instance. pub fn new() -> Self { Self::default() } } impl Encode for RawAttributeEncoder { type Item = RawAttribute; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.value.encode(buf, eos)) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.value.start_encoding(item.into_value())) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(self.exact_requiring_bytes()) } fn is_idle(&self) -> bool { self.value.is_idle() } } impl SizedEncode for RawAttributeEncoder { fn exact_requiring_bytes(&self) -> u64 { self.value.exact_requiring_bytes() } } #[derive(Debug, Clone)] pub enum LosslessAttribute { Known { inner: T, padding: Option, }, Unknown { inner: RawAttribute, padding: Option, }, } impl LosslessAttribute { pub fn new(inner: T) -> Self { LosslessAttribute::Known { inner, padding: None, } } pub fn as_known(&self) -> Option<&T> { match self { LosslessAttribute::Known { inner, .. } => Some(inner), LosslessAttribute::Unknown { .. } => None, } } pub fn as_unknown(&self) -> Option<&RawAttribute> { match self { LosslessAttribute::Known { .. } => None, LosslessAttribute::Unknown { inner, .. } => Some(inner), } } pub fn get_type(&self) -> AttributeType { match self { LosslessAttribute::Known { inner, .. } => inner.get_type(), LosslessAttribute::Unknown { inner, .. } => inner.get_type(), } } pub fn before_encode(&mut self, message: &Message) -> Result<()> { match self { LosslessAttribute::Known { inner, .. } => inner.before_encode(message), LosslessAttribute::Unknown { inner, .. } => inner.before_encode(message), } } pub fn after_decode(&mut self, message: &Message) -> Result<()> { match self { LosslessAttribute::Known { inner, .. } => inner.after_decode(message), LosslessAttribute::Unknown { inner, .. } => inner.after_decode(message), } } } pub struct LosslessAttributeDecoder { get_type: U16beDecoder, value_len: Peekable, is_known: bool, known_value: Length, unknown_value: Length, padding: BytesDecoder, } impl fmt::Debug for LosslessAttributeDecoder { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "LosslessAttributeDecoder {{ .. }}") } } impl Default for LosslessAttributeDecoder { fn default() -> Self { LosslessAttributeDecoder { get_type: Default::default(), value_len: Default::default(), is_known: false, known_value: Default::default(), unknown_value: Default::default(), padding: Default::default(), } } } impl Decode for LosslessAttributeDecoder { type Item = LosslessAttribute; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let mut offset = 0; if !self.value_len.is_idle() { bytecodec_try_decode!(self.get_type, offset, buf, eos); bytecodec_try_decode!(self.value_len, offset, buf, eos); let attr_type = AttributeType(track!(self.get_type.finish_decoding())?); let value_len = *self.value_len.peek().expect("never fails"); self.is_known = track!(self.known_value.inner_mut().try_start_decoding(attr_type))?; if self.is_known { track!(self.known_value.set_expected_bytes(u64::from(value_len)))?; } else { track!(self.unknown_value.inner_mut().try_start_decoding(attr_type))?; // must be `true` track!(self.unknown_value.set_expected_bytes(u64::from(value_len)))?; } self.padding.set_bytes(Padding::new(value_len as usize)); } if self.is_known { bytecodec_try_decode!(self.known_value, offset, buf, eos); } else { bytecodec_try_decode!(self.unknown_value, offset, buf, eos); } bytecodec_try_decode!(self.padding, offset, buf, eos); Ok(offset) } fn finish_decoding(&mut self) -> Result { let _ = track!(self.value_len.finish_decoding())?; let padding = track!(self.padding.finish_decoding())?; if self.is_known { let value = track!(self.known_value.finish_decoding())?; Ok(LosslessAttribute::Known { inner: value, padding: Some(padding), }) } else { let value = track!(self.unknown_value.finish_decoding())?; Ok(LosslessAttribute::Unknown { inner: value, padding: Some(padding), }) } } fn requiring_bytes(&self) -> ByteCount { if self.value_len.is_idle() { if self.is_known { self.known_value .requiring_bytes() .add_for_decoding(self.padding.requiring_bytes()) } else { self.unknown_value .requiring_bytes() .add_for_decoding(self.padding.requiring_bytes()) } } else { self.get_type .requiring_bytes() .add_for_decoding(self.value_len.requiring_bytes()) } } fn is_idle(&self) -> bool { self.value_len.is_idle() && if self.is_known { self.known_value.is_idle() } else { self.unknown_value.is_idle() } && self.padding.is_idle() } } pub struct LosslessAttributeEncoder { get_type: U16beEncoder, value_len: U16beEncoder, known_value: T::Encoder, unknown_value: RawAttributeEncoder, padding: BytesEncoder, } impl fmt::Debug for LosslessAttributeEncoder { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "LosslessAttributeEncoder {{ .. }}") } } impl Default for LosslessAttributeEncoder { fn default() -> Self { LosslessAttributeEncoder { get_type: Default::default(), value_len: Default::default(), known_value: Default::default(), unknown_value: Default::default(), padding: Default::default(), } } } impl Encode for LosslessAttributeEncoder { type Item = LosslessAttribute; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { let mut offset = 0; bytecodec_try_encode!(self.get_type, offset, buf, eos); bytecodec_try_encode!(self.value_len, offset, buf, eos); bytecodec_try_encode!(self.known_value, offset, buf, eos); bytecodec_try_encode!(self.unknown_value, offset, buf, eos); bytecodec_try_encode!(self.padding, offset, buf, eos); Ok(offset) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.get_type.start_encoding(item.get_type().as_u16()))?; let padding = match item { LosslessAttribute::Known { inner, padding } => { track!(self.known_value.start_encoding(inner))?; padding } LosslessAttribute::Unknown { inner, padding } => { track!(self.unknown_value.start_encoding(inner))?; padding } }; let value_len = self.known_value.exact_requiring_bytes() + self.unknown_value.exact_requiring_bytes(); track_assert!(value_len < 0x10000, ErrorKind::InvalidInput; value_len); let padding = padding.unwrap_or_else(|| Padding::new(value_len as usize)); track!(self.value_len.start_encoding(value_len as u16))?; track!(self.padding.start_encoding(padding))?; Ok(()) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(self.exact_requiring_bytes()) } fn is_idle(&self) -> bool { self.value_len.is_idle() && self.known_value.is_idle() && self.unknown_value.is_idle() && self.padding.is_idle() } } impl SizedEncode for LosslessAttributeEncoder { fn exact_requiring_bytes(&self) -> u64 { self.get_type.exact_requiring_bytes() + self.value_len.exact_requiring_bytes() + self.known_value.exact_requiring_bytes() + self.unknown_value.exact_requiring_bytes() + self.padding.exact_requiring_bytes() } } #[derive(Default, Clone)] pub struct Padding { buf: [u8; 3], len: usize, } impl Padding { fn new(value_len: usize) -> Self { let len = (4 - value_len % 4) % 4; Padding { buf: [0; 3], len } } } impl fmt::Debug for Padding { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Padding({:?})", self.as_ref()) } } impl AsRef<[u8]> for Padding { fn as_ref(&self) -> &[u8] { &self.buf[..self.len] } } impl AsMut<[u8]> for Padding { fn as_mut(&mut self) -> &mut [u8] { &mut self.buf[..self.len] } } stun_codec-0.3.4/src/constants.rs000064400000000000000000000013321046102023000151260ustar 00000000000000/// The magic cookie value. /// /// > The magic cookie field **MUST** contain the fixed value `0x2112A442` in /// > network byte order. /// > In [RFC 3489](https://tools.ietf.org/html/rfc3489), this field was part of /// > the transaction ID; placing the magic cookie in this location allows /// > a server to detect if the client will understand certain attributes /// > that were added in this revised specification. In addition, it aids /// > in distinguishing STUN packets from packets of other protocols when /// > STUN is multiplexed with those other protocols on the same port. /// > /// > ([RFC 5389 -- 6. STUN Message Structure](https://tools.ietf.org/html/rfc5389#section-6)) pub const MAGIC_COOKIE: u32 = 0x2112_A442; stun_codec-0.3.4/src/convert.rs000064400000000000000000000004561046102023000146000ustar 00000000000000//! Conversion traits. /// This trait allows for attempting to a cheap reference-to-reference conversion. pub trait TryAsRef { /// Attempts to convert `self` to a reference to `T`. /// /// If it is not possible, this method will return `None`. fn try_as_ref(&self) -> Option<&T>; } stun_codec-0.3.4/src/lib.rs000064400000000000000000000267351046102023000136760ustar 00000000000000//! Encoders and decoders for [STUN (RFC 5389)][RFC 5389] and its extensions. //! //! # Examples //! //! ``` //! # extern crate bytecodec; //! # extern crate stun_codec; //! use bytecodec::{DecodeExt, EncodeExt, Error}; //! use stun_codec::{Message, MessageClass, MessageDecoder, MessageEncoder, TransactionId}; //! use stun_codec::rfc5389::{attributes::Software, methods::BINDING, Attribute}; //! //! # fn main() -> bytecodec::Result<()> { //! // Creates a message //! let mut message = Message::::new(MessageClass::Request, BINDING, TransactionId::new([3; 12])); //! message.add_attribute(Software::new("foo".to_owned())?); //! //! // Encodes the message //! let mut encoder = MessageEncoder::new(); //! let bytes = encoder.encode_into_bytes(message.clone())?; //! assert_eq!( //! bytes, //! [ //! 0, 1, 0, 8, 33, 18, 164, 66, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 128, 34, 0, 3, //! 102, 111, 111, 0 //! ] //! ); //! //! // Decodes the message //! let mut decoder = MessageDecoder::::new(); //! let decoded = decoder.decode_from_bytes(&bytes)?.map_err(Error::from)?; //! assert_eq!(decoded.class(), message.class()); //! assert_eq!(decoded.method(), message.method()); //! assert_eq!(decoded.transaction_id(), message.transaction_id()); //! assert!(decoded.attributes().eq(message.attributes())); //! # Ok(()) //! # } //! ``` //! //! # Define your own attribute enum //! //! By using [`define_attribute_enums!`](./macro.define_attribute_enums.html) macro, //! you can easily define an enum that includes arbitrary attributes. //! //! The following is an example taken from [`rusturn`][rusturn-attributes] crate: //! ``` //! #[macro_use] extern crate trackable; //! //! use stun_codec::define_attribute_enums; //! use stun_codec::rfc5389::attributes::*; //! use stun_codec::rfc5766::attributes::*; //! //! define_attribute_enums!( //! Attribute, AttributeDecoder, AttributeEncoder, //! [ //! // RFC 5389 //! MappedAddress, Username, MessageIntegrity, ErrorCode, //! UnknownAttributes, Realm, Nonce, XorMappedAddress, //! Software, AlternateServer, Fingerprint, //! //! // RFC 5766 //! ChannelNumber, Lifetime, XorPeerAddress, Data, //! XorRelayAddress, EvenPort, RequestedTransport, //! DontFragment, ReservationToken //! ] //! ); //! ``` //! //! [rusturn-attributes]: https://github.com/sile/rusturn/blob/8efe92b7b63fa85a77664045f4a3bf172a3083ed/src/attribute.rs //! //! # References //! //! - [RFC 5389 - Session Traversal Utilities for NAT (STUN)][RFC 5389] //! - [RFC 5769 - Test Vectors for Session Traversal Utilities for NAT (STUN)][RFC 5769] //! - [RFC 5245 - Interactive Connectivity Establishment (ICE)][RFC 5245] //! - [RFC 5780 - NAT Behavior Discovery Using Session Traversal Utilities for NAT][RFC 5780] //! - [RFC 8016 - Mobility with Traversal Using Relays around NAT (TURN)][RFC 8016] //! - [RFC 8656 - Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)][RFC 8656] //! //! [RFC 5389]: https://tools.ietf.org/html/rfc5389 //! [RFC 5769]: https://tools.ietf.org/html/rfc5769 //! [RFC 5245]: https://tools.ietf.org/html/rfc5245 //! [RFC 5780]: https://tools.ietf.org/html/rfc5780 //! [RFC 8016]: https://tools.ietf.org/html/rfc8016 //! [RFC 8656]: https://tools.ietf.org/html/rfc8656 #![warn(missing_docs)] #[macro_use] extern crate bytecodec; #[macro_use] extern crate trackable; pub use attribute::{ Attribute, AttributeType, RawAttribute, RawAttributeDecoder, RawAttributeEncoder, }; pub use message::{ BrokenMessage, DecodedMessage, Message, MessageClass, MessageDecoder, MessageEncoder, }; pub use method::Method; pub use transaction_id::TransactionId; /// Macros. #[macro_use] pub mod macros; pub mod convert; pub mod net; pub mod rfc5245; pub mod rfc5389; pub mod rfc5766; pub mod rfc5780; pub mod rfc8016; pub mod rfc8656; mod attribute; mod constants; mod message; mod method; mod transaction_id; #[cfg(test)] mod tests { use bytecodec::{DecodeExt, EncodeExt, Error}; use trackable::error::MainError; use super::*; use rfc5389::attributes::Software; use rfc5389::methods::BINDING; use rfc5389::Attribute; macro_rules! get_attr { ($message:expr, $attr:ident) => { $message .get_attribute::() .unwrap() }; } #[test] fn it_works() -> Result<(), MainError> { let mut message = Message::new(MessageClass::Request, BINDING, TransactionId::new([3; 12])); message.add_attribute(Software::new("foo".to_owned())?); let mut encoder = MessageEncoder::new(); let bytes = encoder.encode_into_bytes(message.clone())?; assert_eq!( bytes, [ 0, 1, 0, 8, 33, 18, 164, 66, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 128, 34, 0, 3, 102, 111, 111, 0 ] ); let mut decoder = MessageDecoder::::new(); let decoded = decoder.decode_from_bytes(&bytes)?.map_err(Error::from)?; assert_eq!(decoded.class(), message.class()); assert_eq!(decoded.method(), message.method()); assert_eq!(decoded.transaction_id(), message.transaction_id()); assert!(decoded.attributes().eq(message.attributes())); Ok(()) } #[test] fn rfc5769_2_1_sample_request() -> Result<(), MainError> { let input = [ 0x00, 0x01, 0x00, 0x58, 0x21, 0x12, 0xa4, 0x42, 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, 0x80, 0x22, 0x00, 0x10, 0x53, 0x54, 0x55, 0x4e, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x00, 0x24, 0x00, 0x04, 0x6e, 0x00, 0x01, 0xff, 0x80, 0x29, 0x00, 0x08, 0x93, 0x2f, 0xf9, 0xb1, 0x51, 0x26, 0x3b, 0x36, 0x00, 0x06, 0x00, 0x09, 0x65, 0x76, 0x74, 0x6a, 0x3a, 0x68, 0x36, 0x76, 0x59, 0x20, 0x20, 0x20, 0x00, 0x08, 0x00, 0x14, 0x9a, 0xea, 0xa7, 0x0c, 0xbf, 0xd8, 0xcb, 0x56, 0x78, 0x1e, 0xf2, 0xb5, 0xb2, 0xd3, 0xf2, 0x49, 0xc1, 0xb5, 0x71, 0xa2, 0x80, 0x28, 0x00, 0x04, 0xe5, 0x7a, 0x3b, 0xcf, ]; let mut decoder = MessageDecoder::::new(); let message = decoder.decode_from_bytes(&input)?.map_err(Error::from)?; assert_eq!(message.class(), MessageClass::Request); let mut encoder = MessageEncoder::new(); assert_eq!(encoder.encode_into_bytes(message.clone())?, &input[..]); // TEST: `MessageIntegrity` let password = "VOkJxbRl1RmTxUk/WvJxBt"; get_attr!(message, MessageIntegrity) .check_short_term_credential(password) .unwrap(); // TEST: `Fingerprint` assert_eq!(get_attr!(message, Fingerprint).crc32(), 0xe57a3bcf); Ok(()) } #[test] fn rfc5769_2_2_sample_ipv4_response() -> Result<(), MainError> { let input = [ 0x01, 0x01, 0x00, 0x3c, 0x21, 0x12, 0xa4, 0x42, 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, 0x80, 0x22, 0x00, 0x0b, 0x74, 0x65, 0x73, 0x74, 0x20, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x00, 0x20, 0x00, 0x08, 0x00, 0x01, 0xa1, 0x47, 0xe1, 0x12, 0xa6, 0x43, 0x00, 0x08, 0x00, 0x14, 0x2b, 0x91, 0xf5, 0x99, 0xfd, 0x9e, 0x90, 0xc3, 0x8c, 0x74, 0x89, 0xf9, 0x2a, 0xf9, 0xba, 0x53, 0xf0, 0x6b, 0xe7, 0xd7, 0x80, 0x28, 0x00, 0x04, 0xc0, 0x7d, 0x4c, 0x96, ]; let mut decoder = MessageDecoder::::new(); let message = decoder.decode_from_bytes(&input)?.map_err(Error::from)?; assert_eq!(message.class(), MessageClass::SuccessResponse); let mut encoder = MessageEncoder::new(); assert_eq!(encoder.encode_into_bytes(message.clone())?, &input[..]); // TEST: `MessageIntegrity` let password = "VOkJxbRl1RmTxUk/WvJxBt"; get_attr!(message, MessageIntegrity) .check_short_term_credential(password) .unwrap(); // TEST: `XorMappedAddress` (IPv4) assert_eq!( get_attr!(message, XorMappedAddress).address(), "192.0.2.1:32853".parse().unwrap() ); // TEST: `Fingerprint` assert_eq!(get_attr!(message, Fingerprint).crc32(), 0xc07d4c96); Ok(()) } #[test] fn rfc5769_2_3_sample_ipv6_response() -> Result<(), MainError> { let input = [ 0x01, 0x01, 0x00, 0x48, 0x21, 0x12, 0xa4, 0x42, 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, 0x80, 0x22, 0x00, 0x0b, 0x74, 0x65, 0x73, 0x74, 0x20, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0xa1, 0x47, 0x01, 0x13, 0xa9, 0xfa, 0xa5, 0xd3, 0xf1, 0x79, 0xbc, 0x25, 0xf4, 0xb5, 0xbe, 0xd2, 0xb9, 0xd9, 0x00, 0x08, 0x00, 0x14, 0xa3, 0x82, 0x95, 0x4e, 0x4b, 0xe6, 0x7b, 0xf1, 0x17, 0x84, 0xc9, 0x7c, 0x82, 0x92, 0xc2, 0x75, 0xbf, 0xe3, 0xed, 0x41, 0x80, 0x28, 0x00, 0x04, 0xc8, 0xfb, 0x0b, 0x4c, ]; let mut decoder = MessageDecoder::::new(); let message = decoder.decode_from_bytes(&input)?.map_err(Error::from)?; assert_eq!(message.class(), MessageClass::SuccessResponse); let mut encoder = MessageEncoder::new(); assert_eq!(encoder.encode_into_bytes(message.clone())?, &input[..]); // TEST: `MessageIntegrity` let password = "VOkJxbRl1RmTxUk/WvJxBt"; get_attr!(message, MessageIntegrity) .check_short_term_credential(password) .unwrap(); // TEST: `XorMappedAddress` (IPv6) assert_eq!( get_attr!(message, XorMappedAddress).address(), "[2001:db8:1234:5678:11:2233:4455:6677]:32853" .parse() .unwrap() ); // TEST: `Fingerprint` assert_eq!(get_attr!(message, Fingerprint).crc32(), 0xc8fb0b4c); Ok(()) } #[test] fn rfc5769_2_4_sample_request_with_long_term_authentication() -> Result<(), MainError> { let input = [ 0x00, 0x01, 0x00, 0x60, 0x21, 0x12, 0xa4, 0x42, 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e, 0x00, 0x06, 0x00, 0x12, 0xe3, 0x83, 0x9e, 0xe3, 0x83, 0x88, 0xe3, 0x83, 0xaa, 0xe3, 0x83, 0x83, 0xe3, 0x82, 0xaf, 0xe3, 0x82, 0xb9, 0x00, 0x00, 0x00, 0x15, 0x00, 0x1c, 0x66, 0x2f, 0x2f, 0x34, 0x39, 0x39, 0x6b, 0x39, 0x35, 0x34, 0x64, 0x36, 0x4f, 0x4c, 0x33, 0x34, 0x6f, 0x4c, 0x39, 0x46, 0x53, 0x54, 0x76, 0x79, 0x36, 0x34, 0x73, 0x41, 0x00, 0x14, 0x00, 0x0b, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x00, 0x00, 0x08, 0x00, 0x14, 0xf6, 0x70, 0x24, 0x65, 0x6d, 0xd6, 0x4a, 0x3e, 0x02, 0xb8, 0xe0, 0x71, 0x2e, 0x85, 0xc9, 0xa2, 0x8c, 0xa8, 0x96, 0x66, ]; let mut decoder = MessageDecoder::::new(); let message = decoder.decode_from_bytes(&input)?.map_err(Error::from)?; assert_eq!(message.class(), MessageClass::Request); let mut encoder = MessageEncoder::new(); assert_eq!(encoder.encode_into_bytes(message.clone())?, &input[..]); // TEST: `MessageIntegrity` let username = get_attr!(message, Username); let realm = get_attr!(message, Realm); let password = "TheMatrIX"; // TODO: Test before SASLprep version get_attr!(message, MessageIntegrity) .check_long_term_credential(username, realm, password) .unwrap(); Ok(()) } } stun_codec-0.3.4/src/macros.rs000064400000000000000000000146641046102023000144120ustar 00000000000000pub use trackable::{track, track_assert, track_panic}; /// Defines an aggregated attribute type and its decoder and encoder. #[macro_export] macro_rules! define_attribute_enums { ($attr:ident, $decoder:ident, $encoder:ident,[$($variant:ident),*]) => { /// Attribute set. #[allow(missing_docs)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum $attr { $($variant($variant)),* } $(impl From<$variant> for $attr { fn from(f: $variant) -> Self { $attr::$variant(f) } })* $(impl $crate::convert::TryAsRef<$variant> for $attr { fn try_as_ref(&self) -> Option<&$variant> { if let $attr::$variant(a) = self { Some(a) } else { None } } })* impl $crate::Attribute for $attr { type Decoder = $decoder; type Encoder = $encoder; fn get_type(&self) -> $crate::AttributeType { match self { $($attr::$variant(a) => a.get_type()),* } } fn before_encode(&mut self, message: &$crate::Message) -> ::bytecodec::Result<()> where A: $crate::Attribute, { match self { $($attr::$variant(a) => $crate::macros::track!(a.before_encode(message), "attr={}", stringify!($variant))),* } } fn after_decode(&mut self, message: &$crate::Message) -> ::bytecodec::Result<()> where A: $crate::Attribute, { match self { $($attr::$variant(a) => $crate::macros::track!(a.after_decode(message), "attr={}", stringify!($variant))),* } } } /// Attribute set decoder. #[allow(missing_docs)] #[derive(Debug)] pub enum $decoder { $($variant(<$variant as $crate::Attribute>::Decoder)),*, None, } impl $decoder { /// Makes a new decoder instance. pub fn new() -> Self { Self::default() } } impl Default for $decoder { fn default() -> Self { $decoder::None } } impl ::bytecodec::Decode for $decoder { type Item = $attr; fn decode(&mut self, buf: &[u8], eos: ::bytecodec::Eos) -> ::bytecodec::Result { match self { $($decoder::$variant(a) => $crate::macros::track!(a.decode(buf, eos), "attr={}", stringify!($variant))),*, $decoder::None => $crate::macros::track_panic!(::bytecodec::ErrorKind::InconsistentState), } } fn finish_decoding(&mut self) -> ::bytecodec::Result { let item = match self { $($decoder::$variant(a) => $crate::macros::track!(a.finish_decoding(), "attr={}", stringify!($variant))?.into()),*, $decoder::None => $crate::macros::track_panic!(::bytecodec::ErrorKind::IncompleteDecoding), }; *self = $decoder::None; Ok(item) } fn requiring_bytes(&self) -> ::bytecodec::ByteCount { match self { $($decoder::$variant(a) => a.requiring_bytes()),*, $decoder::None => ::bytecodec::ByteCount::Finite(0), } } fn is_idle(&self) -> bool { match self { $($decoder::$variant(a) => a.is_idle()),*, $decoder::None => true, } } } impl ::bytecodec::TryTaggedDecode for $decoder { type Tag = $crate::AttributeType; fn try_start_decoding(&mut self, tag: Self::Tag) -> ::bytecodec::Result { *self = match tag.as_u16() { $($variant::CODEPOINT => $decoder::$variant(<$variant as $crate::Attribute>::Decoder::default())),*, _ => return Ok(false), }; Ok(true) } } /// Attribute set encoder. #[allow(missing_docs)] #[derive(Debug)] pub enum $encoder { $($variant(<$variant as $crate::Attribute>::Encoder)),*, None, } impl $encoder { /// Makes a new encoder instance. pub fn new() -> Self { Self::default() } } impl Default for $encoder { fn default() -> Self { $encoder::None } } impl ::bytecodec::Encode for $encoder { type Item = $attr; fn encode(&mut self, buf: &mut [u8], eos: ::bytecodec::Eos) -> ::bytecodec::Result { match self { $($encoder::$variant(a) => $crate::macros::track!(a.encode(buf, eos), "attr={}", stringify!($variant))),*, $encoder::None => Ok(0), } } fn start_encoding(&mut self, item: Self::Item) -> ::bytecodec::Result<()> { $crate::macros::track_assert!(self.is_idle(), ::bytecodec::ErrorKind::EncoderFull; item); *self = match item { $($attr::$variant(a) => { let mut encoder = <$variant as $crate::Attribute>::Encoder::default(); $crate::macros::track!(encoder.start_encoding(a), "attr={}", stringify!($variant))?; $encoder::$variant(encoder) }),* }; Ok(()) } fn requiring_bytes(&self) -> ::bytecodec::ByteCount { use ::bytecodec::SizedEncode; ::bytecodec::ByteCount::Finite(self.exact_requiring_bytes()) } fn is_idle(&self) -> bool { match self { $($encoder::$variant(a) => a.is_idle()),*, $encoder::None => true, } } } impl ::bytecodec::SizedEncode for $encoder { fn exact_requiring_bytes(&self) -> u64 { match self { $($encoder::$variant(a) => a.exact_requiring_bytes()),*, $encoder::None => 0, } } } }; } stun_codec-0.3.4/src/message.rs000064400000000000000000000546161046102023000145530ustar 00000000000000use crate::attribute::{ Attribute, LosslessAttribute, LosslessAttributeDecoder, LosslessAttributeEncoder, RawAttribute, }; use crate::constants::MAGIC_COOKIE; use crate::convert::TryAsRef; use crate::{Method, TransactionId}; use bytecodec::bytes::{BytesEncoder, CopyableBytesDecoder}; use bytecodec::combinator::{Collect, Length, Peekable, PreEncode, Repeat}; use bytecodec::fixnum::{U16beDecoder, U16beEncoder, U32beDecoder, U32beEncoder}; use bytecodec::{ByteCount, Decode, Encode, Eos, Error, ErrorKind, Result, SizedEncode}; use std::{fmt, vec}; use trackable::error::ErrorKindExt; /// Message decoded by [`MessageDecoder`]. pub type DecodedMessage = std::result::Result, BrokenMessage>; /// The class of a message. #[allow(missing_docs)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum MessageClass { Request, Indication, SuccessResponse, ErrorResponse, } impl MessageClass { fn from_u8(value: u8) -> Option { match value { 0b00 => Some(MessageClass::Request), 0b01 => Some(MessageClass::Indication), 0b10 => Some(MessageClass::SuccessResponse), 0b11 => Some(MessageClass::ErrorResponse), _ => None, } } } impl fmt::Display for MessageClass { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { MessageClass::Request => write!(f, "request"), MessageClass::Indication => write!(f, "indication"), MessageClass::SuccessResponse => write!(f, "success response"), MessageClass::ErrorResponse => write!(f, "error response"), } } } /// STUN message. /// /// # NOTE: Binary Format of STUN Messages /// /// > STUN messages are encoded in binary using network-oriented format /// > (most significant byte or octet first, also commonly known as big- /// > endian). The transmission order is described in detail in Appendix B /// > of [RFC 791]. Unless otherwise noted, numeric constants are /// > in decimal (base 10). /// > /// > All STUN messages MUST start with a 20-byte header followed by zero /// > or more Attributes. The STUN header contains a STUN message type, /// > magic cookie, transaction ID, and message length. /// > /// > ```text /// > 0 1 2 3 /// > 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 /// > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// > |0 0| STUN Message Type | Message Length | /// > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// > | Magic Cookie | /// > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// > | | /// > | Transaction ID (96 bits) | /// > | | /// > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// > /// > Figure 2: Format of STUN Message Header /// > ``` /// > /// > The most significant 2 bits of every STUN message MUST be zeroes. /// > This can be used to differentiate STUN packets from other protocols /// > when STUN is multiplexed with other protocols on the same port. /// > /// > The message type defines the message class (request, success /// > response, failure response, or indication) and the message method /// > (the primary function) of the STUN message. Although there are four /// > message classes, there are only two types of transactions in STUN: /// > request/response transactions (which consist of a request message and /// > a response message) and indication transactions (which consist of a /// > single indication message). Response classes are split into error /// > and success responses to aid in quickly processing the STUN message. /// > /// > The message type field is decomposed further into the following structure: /// > /// > ```text /// > 0 1 /// > 2 3 4 5 6 7 8 9 0 1 2 3 4 5 /// > +--+--+-+-+-+-+-+-+-+-+-+-+-+-+ /// > |M |M |M|M|M|C|M|M|M|C|M|M|M|M| /// > |11|10|9|8|7|1|6|5|4|0|3|2|1|0| /// > +--+--+-+-+-+-+-+-+-+-+-+-+-+-+ /// > /// > Figure 3: Format of STUN Message Type Field /// > ``` /// > /// > Here the bits in the message type field are shown as most significant /// > (M11) through least significant (M0). M11 through M0 represent a 12- /// > bit encoding of the method. C1 and C0 represent a 2-bit encoding of /// > the class. A class of 0b00 is a request, a class of 0b01 is an /// > indication, a class of 0b10 is a success response, and a class of /// > 0b11 is an error response. This specification defines a single /// > method, Binding. The method and class are orthogonal, so that for /// > each method, a request, success response, error response, and /// > indication are possible for that method. Extensions defining new /// > methods MUST indicate which classes are permitted for that method. /// > /// > For example, a Binding request has class=0b00 (request) and /// > method=0b000000000001 (Binding) and is encoded into the first 16 bits /// > as 0x0001. A Binding response has class=0b10 (success response) and /// > method=0b000000000001, and is encoded into the first 16 bits as 0x0101. /// > /// > > Note: This unfortunate encoding is due to assignment of values in /// > > [RFC 3489] that did not consider encoding Indications, Success, and /// > > Errors using bit fields. /// > /// > The magic cookie field MUST contain the fixed value 0x2112A442 in /// > network byte order. In [RFC 3489], this field was part of /// > the transaction ID; placing the magic cookie in this location allows /// > a server to detect if the client will understand certain attributes /// > that were added in this revised specification. In addition, it aids /// > in distinguishing STUN packets from packets of other protocols when /// > STUN is multiplexed with those other protocols on the same port. /// > /// > The transaction ID is a 96-bit identifier, used to uniquely identify /// > STUN transactions. For request/response transactions, the /// > transaction ID is chosen by the STUN client for the request and /// > echoed by the server in the response. For indications, it is chosen /// > by the agent sending the indication. It primarily serves to /// > correlate requests with responses, though it also plays a small role /// > in helping to prevent certain types of attacks. The server also uses /// > the transaction ID as a key to identify each transaction uniquely /// > across all clients. As such, the transaction ID MUST be uniformly /// > and randomly chosen from the interval 0 .. 2**96-1, and SHOULD be /// > cryptographically random. Resends of the same request reuse the same /// > transaction ID, but the client MUST choose a new transaction ID for /// > new transactions unless the new request is bit-wise identical to the /// > previous request and sent from the same transport address to the same /// > IP address. Success and error responses MUST carry the same /// > transaction ID as their corresponding request. When an agent is /// > acting as a STUN server and STUN client on the same port, the /// > transaction IDs in requests sent by the agent have no relationship to /// > the transaction IDs in requests received by the agent. /// > /// > The message length MUST contain the size, in bytes, of the message /// > not including the 20-byte STUN header. Since all STUN attributes are /// > padded to a multiple of 4 bytes, the last 2 bits of this field are /// > always zero. This provides another way to distinguish STUN packets /// > from packets of other protocols. /// > /// > Following the STUN fixed portion of the header are zero or more /// > attributes. Each attribute is TLV (Type-Length-Value) encoded. The /// > details of the encoding, and of the attributes themselves are given /// > in Section 15. /// > /// > [RFC 5389 -- 6. STUN Message Structure] /// /// [RFC 5389 -- 6. STUN Message Structure]: https://tools.ietf.org/html/rfc5389#section-6 /// [RFC 791]: https://tools.ietf.org/html/rfc791 /// [RFC 3489]: https://tools.ietf.org/html/rfc3489 #[derive(Debug, Clone)] pub struct Message { class: MessageClass, method: Method, transaction_id: TransactionId, attributes: Vec>, } impl Message { /// Makes a new `Message` instance. pub fn new(class: MessageClass, method: Method, transaction_id: TransactionId) -> Self { Message { class, method, transaction_id, attributes: Vec::new(), } } /// Returns the class of the message. pub fn class(&self) -> MessageClass { self.class } /// Returns the method of the message. pub fn method(&self) -> Method { self.method } /// Returns the transaction ID of the message. pub fn transaction_id(&self) -> TransactionId { self.transaction_id } /// Returns a reference to the first occurance of `T` attribute in the attributes of the message. /// /// If there is no such attribute, this method will return `None`. pub fn get_attribute(&self) -> Option<&T> where T: Attribute, A: TryAsRef, { self.attributes().filter_map(|a| a.try_as_ref()).next() } /// Returns an iterator that iterates over the known attributes in the message. pub fn attributes(&self) -> impl Iterator { self.attributes.iter().filter_map(|a| a.as_known()) } /// Returns an iterator that iterates over the unknown attributes in the message. /// /// Note that it is the responsibility of users to check /// whether the unknown attributes contains comprehension-required ones. pub fn unknown_attributes(&self) -> impl Iterator { self.attributes.iter().filter_map(|a| a.as_unknown()) } /// Adds the given attribute to the tail of the attributes in the message. pub fn add_attribute(&mut self, attribute: impl Into) { self.attributes .push(LosslessAttribute::new(attribute.into())); } } /// STUN message of which [`MessageDecoder`] could not decode the attribute part. #[allow(missing_docs)] #[derive(Debug, Clone)] pub struct BrokenMessage { method: Method, class: MessageClass, transaction_id: TransactionId, error: Error, } impl BrokenMessage { /// Returns the class of the message. pub fn class(&self) -> MessageClass { self.class } /// Returns the method of the message. pub fn method(&self) -> Method { self.method } /// Returns the transaction ID of the message. pub fn transaction_id(&self) -> TransactionId { self.transaction_id } /// Returns a reference to the error object storing the cause of failure to decode the message. pub fn error(&self) -> &Error { &self.error } } impl From for Error { fn from(f: BrokenMessage) -> Self { ErrorKind::InvalidInput.cause(format!("{:?}", f)).into() } } #[derive(Debug, Default)] struct MessageHeaderDecoder { message_type: U16beDecoder, message_len: U16beDecoder, magic_cookie: U32beDecoder, transaction_id: CopyableBytesDecoder<[u8; 12]>, } impl MessageHeaderDecoder { fn check_magic_cookie(&self, magic_cookie: u32) -> Result<()> { track_assert_eq!( magic_cookie, MAGIC_COOKIE, ErrorKind::InvalidInput, "Unexpected MAGIC_COOKIE: actual=0x{:08x}, expected=0x{:08x}", magic_cookie, MAGIC_COOKIE, ); Ok(()) } } impl Decode for MessageHeaderDecoder { type Item = (Type, u16, TransactionId); fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let mut offset = 0; bytecodec_try_decode!(self.message_type, offset, buf, eos); bytecodec_try_decode!(self.message_len, offset, buf, eos); bytecodec_try_decode!(self.magic_cookie, offset, buf, eos); bytecodec_try_decode!(self.transaction_id, offset, buf, eos); Ok(offset) } fn finish_decoding(&mut self) -> Result { let message_type = track!(self.message_type.finish_decoding())?; let message_type = track!(Type::from_u16(message_type))?; let message_len = track!(self.message_len.finish_decoding())?; let magic_cookie = track!(self.magic_cookie.finish_decoding())?; let transaction_id = TransactionId::new(track!(self.transaction_id.finish_decoding())?); track!(self.check_magic_cookie(magic_cookie); message_type, message_len, transaction_id)?; Ok((message_type, message_len, transaction_id)) } fn requiring_bytes(&self) -> ByteCount { self.message_type .requiring_bytes() .add_for_decoding(self.message_len.requiring_bytes()) .add_for_decoding(self.magic_cookie.requiring_bytes()) .add_for_decoding(self.transaction_id.requiring_bytes()) } fn is_idle(&self) -> bool { self.transaction_id.is_idle() } } #[derive(Debug)] struct AttributesDecoder { inner: Collect, Vec>>, last_error: Option, is_eos: bool, } impl Default for AttributesDecoder { fn default() -> Self { AttributesDecoder { inner: Default::default(), last_error: None, is_eos: false, } } } impl Decode for AttributesDecoder { type Item = Vec>; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { if self.last_error.is_none() { match track!(self.inner.decode(buf, eos)) { Err(e) => { self.last_error = Some(e); } Ok(size) => return Ok(size), } } // Skips remaining bytes if an error occurred self.is_eos = eos.is_reached(); Ok(buf.len()) } fn finish_decoding(&mut self) -> Result { self.is_eos = false; if let Some(e) = self.last_error.take() { return Err(track!(e)); } track!(self.inner.finish_decoding()) } fn requiring_bytes(&self) -> ByteCount { if self.last_error.is_none() { self.inner.requiring_bytes() } else if self.is_eos { ByteCount::Finite(0) } else { ByteCount::Unknown } } fn is_idle(&self) -> bool { if self.last_error.is_none() { self.inner.is_idle() } else { self.is_eos } } } /// [`Message`] decoder. #[derive(Debug)] pub struct MessageDecoder { header: Peekable, attributes: Length>, } impl MessageDecoder { /// Makes a new `MessageDecoder` instance. pub fn new() -> Self { Self::default() } fn finish_decoding_with_header( &mut self, method: Method, class: MessageClass, transaction_id: TransactionId, ) -> Result> { let attributes = track!(self.attributes.finish_decoding())?; let mut message = Message { class, method, transaction_id, attributes, }; let attributes_len = message.attributes.len(); for i in 0..attributes_len { unsafe { let message_mut = &mut *(&mut message as *mut Message); let attr = message_mut.attributes.get_unchecked_mut(i); message.attributes.set_len(i); let decode_result = track!(attr.after_decode(&message)); message.attributes.set_len(attributes_len); decode_result?; } } Ok(message) } } impl Default for MessageDecoder { fn default() -> Self { MessageDecoder { header: Default::default(), attributes: Default::default(), } } } impl Decode for MessageDecoder { type Item = DecodedMessage; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let mut offset = 0; if !self.header.is_idle() { bytecodec_try_decode!(self.header, offset, buf, eos); let message_len = self.header.peek().expect("never fails").1; track!(self.attributes.set_expected_bytes(u64::from(message_len)))?; } bytecodec_try_decode!(self.attributes, offset, buf, eos); Ok(offset) } fn finish_decoding(&mut self) -> Result { let (Type { method, class }, _, transaction_id) = track!(self.header.finish_decoding())?; match self.finish_decoding_with_header(method, class, transaction_id) { Err(error) => Ok(Err(BrokenMessage { method, class, transaction_id, error, })), Ok(message) => Ok(Ok(message)), } } fn requiring_bytes(&self) -> ByteCount { self.header .requiring_bytes() .add_for_decoding(self.attributes.requiring_bytes()) } fn is_idle(&self) -> bool { self.header.is_idle() && self.attributes.is_idle() } } /// [`Message`] encoder. #[derive(Debug)] pub struct MessageEncoder { message_type: U16beEncoder, message_len: U16beEncoder, magic_cookie: U32beEncoder, transaction_id: BytesEncoder, attributes: PreEncode, vec::IntoIter>>>, } impl MessageEncoder { /// Makes a new `MessageEncoder` instance. pub fn new() -> Self { Self::default() } } impl Default for MessageEncoder { fn default() -> Self { MessageEncoder { message_type: Default::default(), message_len: Default::default(), magic_cookie: Default::default(), transaction_id: Default::default(), attributes: Default::default(), } } } impl Encode for MessageEncoder { type Item = Message; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { let mut offset = 0; bytecodec_try_encode!(self.message_type, offset, buf, eos); bytecodec_try_encode!(self.message_len, offset, buf, eos); bytecodec_try_encode!(self.magic_cookie, offset, buf, eos); bytecodec_try_encode!(self.transaction_id, offset, buf, eos); bytecodec_try_encode!(self.attributes, offset, buf, eos); Ok(offset) } fn start_encoding(&mut self, mut item: Self::Item) -> Result<()> { let attributes_len = item.attributes.len(); for i in 0..attributes_len { unsafe { let item_mut = &mut *(&mut item as *mut Message); let attr = item_mut.attributes.get_unchecked_mut(i); item.attributes.set_len(i); let encode_result = track!(attr.before_encode(&item)); item.attributes.set_len(attributes_len); encode_result?; } } let message_type = Type { class: item.class, method: item.method, }; track!(self.message_type.start_encoding(message_type.as_u16()))?; track!(self.magic_cookie.start_encoding(MAGIC_COOKIE))?; track!(self.transaction_id.start_encoding(item.transaction_id))?; track!(self.attributes.start_encoding(item.attributes.into_iter()))?; let message_len = self.attributes.exact_requiring_bytes(); track_assert!( message_len < 0x10000, ErrorKind::InvalidInput, "Too large message length: actual={}, limit=0xFFFF", message_len ); track!(self.message_len.start_encoding(message_len as u16))?; Ok(()) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(self.exact_requiring_bytes()) } fn is_idle(&self) -> bool { self.transaction_id.is_idle() && self.attributes.is_idle() } } impl SizedEncode for MessageEncoder { fn exact_requiring_bytes(&self) -> u64 { self.message_type.exact_requiring_bytes() + self.message_len.exact_requiring_bytes() + self.magic_cookie.exact_requiring_bytes() + self.transaction_id.exact_requiring_bytes() + self.attributes.exact_requiring_bytes() } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] struct Type { class: MessageClass, method: Method, } impl Type { fn as_u16(self) -> u16 { let class = self.class as u16; let method = self.method.as_u16(); (method & 0b0000_0000_1111) | ((class & 0b01) << 4) | ((method & 0b0000_0111_0000) << 5) | ((class & 0b10) << 7) | ((method & 0b1111_1000_0000) << 9) } fn from_u16(value: u16) -> Result { track_assert!( value >> 14 == 0, ErrorKind::InvalidInput, "First two-bits of STUN message must be 0" ); let class = ((value >> 4) & 0b01) | ((value >> 7) & 0b10); let class = MessageClass::from_u8(class as u8).unwrap(); let method = (value & 0b0000_0000_1111) | ((value >> 1) & 0b0000_0111_0000) | ((value >> 2) & 0b1111_1000_0000); let method = Method(method); Ok(Type { class, method }) } } #[cfg(test)] mod tests { use super::*; use crate::rfc5389::attributes::MappedAddress; use crate::rfc5389::methods::BINDING; use crate::{MessageClass, TransactionId}; use bytecodec::DecodeExt; use trackable::result::TestResult; #[test] fn message_class_from_u8_works() { assert_eq!(MessageClass::from_u8(0), Some(MessageClass::Request)); assert_eq!(MessageClass::from_u8(9), None); } #[test] fn decoder_fails_when_decoding_attributes() -> TestResult { let bytes = [ 0, 1, 0, 12, 33, 18, 164, 66, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 0, 8, 0, 1, 0, 80, 127, 0, /* 0, */ 1, ]; let mut decoder = MessageDecoder::::new(); let broken_message = decoder.decode_from_bytes(&bytes)?.err().unwrap(); assert_eq!(broken_message.method, BINDING); assert_eq!(broken_message.class, MessageClass::Request); assert_eq!(broken_message.transaction_id, TransactionId::new([3; 12])); Ok(()) } } stun_codec-0.3.4/src/method.rs000064400000000000000000000034001046102023000143700ustar 00000000000000use crate::{rfc5389, rfc5766}; use bytecodec::{ErrorKind, Result}; use std::fmt; /// STUN method. /// /// > All STUN messages start with a fixed header that includes a **method**, a /// > class, and the transaction ID. The **method** indicates which of the /// > various requests or indications this is; /// > /// > [RFC 5389 -- 3. Overview of Operation] /// /// [RFC 5389 -- 3. Overview of Operation]: https://tools.ietf.org/html/rfc5389#section-3 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Method(pub(crate) u16); impl Method { /// Makes a new `Method` instance with the given codepoint. /// /// # Errors /// /// If `codepoint` is greater than `0xFFF`, this will return an `ErrorKind::InvalidInput` error. pub fn new(codepoint: u16) -> Result { track_assert!(codepoint < 0x1000, ErrorKind::InvalidInput; codepoint); Ok(Method(codepoint)) } /// Returns the codepoint corresponding this method. pub fn as_u16(self) -> u16 { self.0 } } impl From for Method { fn from(f: u8) -> Self { Method(u16::from(f)) } } impl fmt::Display for Method { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { rfc5389::methods::BINDING => write!(f, "binding"), rfc5766::methods::ALLOCATE => write!(f, "allocate"), rfc5766::methods::REFRESH => write!(f, "refresh"), rfc5766::methods::CHANNEL_BIND => write!(f, "channel bind"), rfc5766::methods::CREATE_PERMISSION => write!(f, "create permission"), rfc5766::methods::DATA => write!(f, "data"), rfc5766::methods::SEND => write!(f, "send"), Method(code) => write!(f, "unknown ({code})"), } } } stun_codec-0.3.4/src/net.rs000064400000000000000000000202621046102023000137030ustar 00000000000000//! Socket address related components. //! //! # Binary Format of Socket Address //! //! ```text //! 0 1 2 3 //! 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 //! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //! |0 0 0 0 0 0 0 0| Family | Port | //! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //! | | //! | Address (32 bits or 128 bits) | //! | | //! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //! //! Family: IPv4=1, IPv6=2 //! ``` use crate::constants::MAGIC_COOKIE; use crate::TransactionId; use bytecodec::bytes::{BytesDecoder, BytesEncoder}; use bytecodec::combinator::Peekable; use bytecodec::fixnum::{U16beDecoder, U16beEncoder, U8Decoder, U8Encoder}; use bytecodec::{ByteCount, Decode, Encode, Eos, ErrorKind, Result, SizedEncode}; use std::net::{IpAddr, SocketAddr}; const FAMILY_IPV4: u8 = 1; const FAMILY_IPV6: u8 = 2; /// Applies XOR operation on the given socket address. pub fn socket_addr_xor(addr: SocketAddr, transaction_id: TransactionId) -> SocketAddr { let xor_port = addr.port() ^ (MAGIC_COOKIE >> 16) as u16; match addr.ip() { IpAddr::V4(ip) => { let mut octets = ip.octets(); for (i, b) in octets.iter_mut().enumerate() { *b ^= (MAGIC_COOKIE >> (24 - i * 8)) as u8; } let xor_ip = From::from(octets); SocketAddr::new(IpAddr::V4(xor_ip), xor_port) } IpAddr::V6(ip) => { let mut octets = ip.octets(); for (i, b) in octets.iter_mut().enumerate().take(4) { *b ^= (MAGIC_COOKIE >> (24 - i * 8)) as u8; } for (i, b) in octets.iter_mut().enumerate().take(16).skip(4) { *b ^= transaction_id.as_bytes()[i - 4]; } let xor_ip = From::from(octets); SocketAddr::new(IpAddr::V6(xor_ip), xor_port) } } } /// Socket address decoder. #[derive(Debug, Default)] pub struct SocketAddrDecoder { unused: U8Decoder, family: Peekable, port: U16beDecoder, ip: BytesDecoder, } impl SocketAddrDecoder { /// Makes a new `SocketAddrDecoder` instance. pub fn new() -> Self { Self::default() } } impl Decode for SocketAddrDecoder { type Item = SocketAddr; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let mut offset = 0; if !self.family.is_idle() { bytecodec_try_decode!(self.unused, offset, buf, eos); bytecodec_try_decode!(self.family, offset, buf, eos); let family = self.family.peek().expect("never fails"); match *family { FAMILY_IPV4 => self.ip.set_bytes(IpBytes::V4([0; 4])), FAMILY_IPV6 => self.ip.set_bytes(IpBytes::V6([0; 16])), _ => track_panic!( ErrorKind::InvalidInput, "Unknown address family: {}", family ), } } bytecodec_try_decode!(self.port, offset, buf, eos); bytecodec_try_decode!(self.ip, offset, buf, eos); Ok(offset) } fn finish_decoding(&mut self) -> Result { let _ = track!(self.unused.finish_decoding())?; let _ = track!(self.family.finish_decoding())?; let port = track!(self.port.finish_decoding())?; let ip = match track!(self.ip.finish_decoding())? { IpBytes::V4(b) => IpAddr::V4(b.into()), IpBytes::V6(b) => IpAddr::V6(b.into()), }; Ok(SocketAddr::new(ip, port)) } fn requiring_bytes(&self) -> ByteCount { self.unused .requiring_bytes() .add_for_decoding(self.family.requiring_bytes()) .add_for_decoding(self.port.requiring_bytes()) .add_for_decoding(self.ip.requiring_bytes()) } fn is_idle(&self) -> bool { self.port.is_idle() && self.ip.is_idle() } } /// Socket address encoder. #[derive(Debug, Default)] pub struct SocketAddrEncoder { unused: U8Encoder, family: U8Encoder, port: U16beEncoder, ip: BytesEncoder, } impl SocketAddrEncoder { /// Makes a new `SocketAddrEncoder` instance. pub fn new() -> Self { Self::default() } } impl Encode for SocketAddrEncoder { type Item = SocketAddr; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { let mut offset = 0; bytecodec_try_encode!(self.unused, offset, buf, eos); bytecodec_try_encode!(self.family, offset, buf, eos); bytecodec_try_encode!(self.port, offset, buf, eos); bytecodec_try_encode!(self.ip, offset, buf, eos); Ok(offset) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.unused.start_encoding(0))?; if item.ip().is_ipv4() { track!(self.family.start_encoding(FAMILY_IPV4))?; } else { track!(self.family.start_encoding(FAMILY_IPV6))?; } track!(self.port.start_encoding(item.port()))?; track!(self.ip.start_encoding(IpBytes::new(item.ip())))?; Ok(()) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(self.exact_requiring_bytes()) } fn is_idle(&self) -> bool { self.ip.is_idle() } } impl SizedEncode for SocketAddrEncoder { fn exact_requiring_bytes(&self) -> u64 { self.unused.exact_requiring_bytes() + self.family.exact_requiring_bytes() + self.port.exact_requiring_bytes() + self.ip.exact_requiring_bytes() } } #[derive(Debug)] enum IpBytes { V4([u8; 4]), V6([u8; 16]), } impl IpBytes { fn new(ip: IpAddr) -> Self { match ip { IpAddr::V4(ip) => IpBytes::V4(ip.octets()), IpAddr::V6(ip) => IpBytes::V6(ip.octets()), } } } impl AsRef<[u8]> for IpBytes { fn as_ref(&self) -> &[u8] { match self { IpBytes::V4(bytes) => bytes, IpBytes::V6(bytes) => bytes, } } } impl AsMut<[u8]> for IpBytes { fn as_mut(&mut self) -> &mut [u8] { match self { IpBytes::V4(bytes) => bytes, IpBytes::V6(bytes) => bytes, } } } #[cfg(test)] mod tests { use bytecodec::{DecodeExt, EncodeExt}; use super::*; #[test] fn socket_addr_xor_works() { let transaction_id = TransactionId::new([ 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, ]); // IPv4 let addr: SocketAddr = "192.0.2.1:32853".parse().unwrap(); assert_eq!( socket_addr_xor(addr, transaction_id), "225.18.166.67:41287".parse().unwrap() ); // IPv6 let addr: SocketAddr = "[2001:db8:1234:5678:11:2233:4455:6677]:32853" .parse() .unwrap(); assert_eq!( socket_addr_xor(addr, transaction_id), "[113:a9fa:a5d3:f179:bc25:f4b5:bed2:b9d9]:41287" .parse() .unwrap() ); } #[test] fn socket_addr_encoder_works() { let mut encoder = SocketAddrEncoder::new(); let v4addr = "127.0.0.1:80".parse().unwrap(); let bytes = encoder.encode_into_bytes(v4addr).unwrap(); assert_eq!(bytes, [0, 1, 0, 80, 127, 0, 0, 1]); let v6addr = "[::]:90".parse().unwrap(); let bytes = encoder.encode_into_bytes(v6addr).unwrap(); assert_eq!( bytes, [0, 2, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ); } #[test] fn socket_addr_decoder_works() { let mut decoder = SocketAddrDecoder::new(); let v4addr = decoder .decode_from_bytes(&[0, 1, 0, 80, 127, 0, 0, 1]) .unwrap(); assert_eq!(v4addr.to_string(), "127.0.0.1:80"); let v6addr = decoder .decode_from_bytes(&[0, 2, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) .unwrap(); assert_eq!(v6addr.to_string(), "[::]:90"); } } stun_codec-0.3.4/src/rfc5245/attributes.rs000064400000000000000000000172771046102023000164110ustar 00000000000000//! Attributes that are defined in [RFC 5245]. //! //! [RFC 5245]: https://tools.ietf.org/html/rfc5245 use crate::attribute::{Attribute, AttributeType}; use bytecodec::fixnum::{U32beDecoder, U32beEncoder, U64beDecoder, U64beEncoder}; use bytecodec::null::{NullDecoder, NullEncoder}; use bytecodec::{ByteCount, Decode, Encode, Eos, Result, SizedEncode, TryTaggedDecode}; macro_rules! impl_decode { ($decoder:ty, $item:ident, $and_then:expr) => { impl Decode for $decoder { type Item = $item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.0.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { track!(self.0.finish_decoding()).and_then($and_then) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl TryTaggedDecode for $decoder { type Tag = AttributeType; fn try_start_decoding(&mut self, attr_type: Self::Tag) -> Result { Ok(attr_type.as_u16() == $item::CODEPOINT) } } }; } macro_rules! impl_encode { ($encoder:ty, $item:ty, $map_from:expr) => { impl Encode for $encoder { type Item = $item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } #[allow(clippy::redundant_closure_call)] fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.0.start_encoding($map_from(item))) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl SizedEncode for $encoder { fn exact_requiring_bytes(&self) -> u64 { self.0.exact_requiring_bytes() } } }; } /// `PRIORITY` attribute. /// /// See [RFC 5245 -- 7.1.2.1 PRIORITY] about this attribute. /// /// [RFC 5245 -- 7.1.2.1 PRIORITY]: https://tools.ietf.org/html/rfc5245#section-7.1.2.1 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Priority(u32); impl Priority { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0024; /// Makes a new `Priority` instance. pub fn new(prio: u32) -> Self { Priority(prio) } /// Returns the alternate address. pub fn prio(&self) -> u32 { self.0 } } impl Attribute for Priority { type Decoder = PriorityDecoder; type Encoder = PriorityEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`Priority`] decoder. #[derive(Debug, Default)] pub struct PriorityDecoder(U32beDecoder); impl PriorityDecoder { /// Makes a new `PriorityDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(PriorityDecoder, Priority, |prio| Ok(Priority(prio))); /// [`Priority`] encoder. #[derive(Debug, Default)] pub struct PriorityEncoder(U32beEncoder); impl PriorityEncoder { /// Makes a new `PriorityEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(PriorityEncoder, Priority, |item: Self::Item| item.0); /// `USE-CANDIDATE` attribute. /// /// See [RFC 5245 -- 7.1.2.1 USE-CANDIDATE] about this attribute. /// /// [RFC 5245 -- 7.1.2.1 USE-CANDIDATE]: https://tools.ietf.org/html/rfc5245#section-7.1.2.1 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UseCandidate; impl UseCandidate { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0025; /// Makes a new `UseCandidate` instance. pub fn new() -> Self { UseCandidate } } impl Attribute for UseCandidate { type Decoder = UseCandidateDecoder; type Encoder = UseCandidateEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } impl Default for UseCandidate { fn default() -> Self { Self::new() } } /// [`UseCandidate`] decoder. #[derive(Debug, Default)] pub struct UseCandidateDecoder(NullDecoder); impl UseCandidateDecoder { /// Makes a new `UseCandidateDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(UseCandidateDecoder, UseCandidate, |_| Ok(UseCandidate)); /// [`UseCandidate`] encoder. #[derive(Debug, Default)] pub struct UseCandidateEncoder(NullEncoder); impl UseCandidateEncoder { /// Makes a new `UseCandidateEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(UseCandidateEncoder, UseCandidate, |_item: Self::Item| ()); /// `ICE-CONTROLLED` attribute. /// /// See [RFC 5245 -- 7.1.2.1 ICE-CONTROLLED] about this attribute. /// /// [RFC 5245 -- 7.1.2.1 ICE-CONTROLLED]: https://tools.ietf.org/html/rfc5245#section-7.1.2.2 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IceControlled(u64); impl IceControlled { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x8029; /// Makes a new `IceControlled` instance. pub fn new(rnd: u64) -> Self { IceControlled(rnd) } /// Returns the alternate address. pub fn prio(&self) -> u64 { self.0 } } impl Attribute for IceControlled { type Decoder = IceControlledDecoder; type Encoder = IceControlledEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`IceControlled`] decoder. #[derive(Debug, Default)] pub struct IceControlledDecoder(U64beDecoder); impl IceControlledDecoder { /// Makes a new `IceControlledDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(IceControlledDecoder, IceControlled, |prio| Ok( IceControlled(prio) )); /// [`IceControlled`] encoder. #[derive(Debug, Default)] pub struct IceControlledEncoder(U64beEncoder); impl IceControlledEncoder { /// Makes a new `IceControlledEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(IceControlledEncoder, IceControlled, |item: Self::Item| item .0); /// `ICE-CONTROLLING` attribute. /// /// See [RFC 5245 -- 7.1.2.1 ICE-CONTROLLING] about this attribute. /// /// [RFC 5245 -- 7.1.2.1 ICE-CONTROLLING]: https://tools.ietf.org/html/rfc5245#section-7.1.2.2 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IceControlling(u64); impl IceControlling { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x802A; /// Makes a new `IceControlling` instance. pub fn new(rnd: u64) -> Self { IceControlling(rnd) } /// Returns the alternate address. pub fn prio(&self) -> u64 { self.0 } } impl Attribute for IceControlling { type Decoder = IceControllingDecoder; type Encoder = IceControllingEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`IceControlling`] decoder. #[derive(Debug, Default)] pub struct IceControllingDecoder(U64beDecoder); impl IceControllingDecoder { /// Makes a new `IceControllingDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(IceControllingDecoder, IceControlling, |prio| Ok( IceControlling(prio) )); /// [`IceControlling`] encoder. #[derive(Debug, Default)] pub struct IceControllingEncoder(U64beEncoder); impl IceControllingEncoder { /// Makes a new `IceControllingEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(IceControllingEncoder, IceControlling, |item: Self::Item| { item.0 }); stun_codec-0.3.4/src/rfc5245/errors.rs000064400000000000000000000015361046102023000155260ustar 00000000000000//! Error codes that are defined in [RFC 5389 -- 15.6 ERROR-CODE]. //! //! [RFC 5389 -- 15.6 ERROR-CODE]: https://tools.ietf.org/html/rfc5389#section-15.6 use crate::rfc5389::attributes::ErrorCode; /// `487`: "Role Conflict". /// /// > The client asserted an ICE role (controlling or /// > controlled) that is in conflict with the role of the server. /// > /// > [RFC 5245 -- 21.3. STUN Error Responses] /// /// [RFC 5245 -- 21.3. STUN Error Responses]: https://tools.ietf.org/html/rfc5245#section-21.3 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct RoleConflict; impl RoleConflict { /// The codepoint of the error. pub const CODEPOINT: u16 = 487; } impl From for ErrorCode { fn from(_: RoleConflict) -> Self { ErrorCode::new(RoleConflict::CODEPOINT, "Role Conflict".to_string()).expect("never fails") } } stun_codec-0.3.4/src/rfc5245/mod.rs000064400000000000000000000004751046102023000147720ustar 00000000000000//! [RFC 5245(ICE)][RFC 5245] specific components. //! //! [RFC 5245]: https://tools.ietf.org/html/rfc5245 use self::attributes::*; pub mod attributes; pub mod errors; define_attribute_enums!( Attribute, AttributeDecoder, AttributeEncoder, [Priority, UseCandidate, IceControlled, IceControlling] ); stun_codec-0.3.4/src/rfc5389/attributes.rs000064400000000000000000000677011046102023000164170ustar 00000000000000//! Attributes that are defined in [RFC 5389]. //! //! [RFC 5389]: https://tools.ietf.org/html/rfc5389 use crate::attribute::{Attribute, AttributeType}; use crate::message::{Message, MessageEncoder}; use crate::net::{socket_addr_xor, SocketAddrDecoder, SocketAddrEncoder}; use crate::rfc5389::errors; use bytecodec::bytes::{BytesEncoder, CopyableBytesDecoder, Utf8Decoder, Utf8Encoder}; use bytecodec::combinator::{Collect, PreEncode, Repeat}; use bytecodec::fixnum::{U16beDecoder, U16beEncoder, U32beDecoder, U32beEncoder}; use bytecodec::tuple::{TupleDecoder, TupleEncoder}; use bytecodec::{ ByteCount, Decode, Encode, EncodeExt, Eos, Error, ErrorKind, Result, SizedEncode, TryTaggedDecode, }; use byteorder::{BigEndian, ByteOrder}; use hmac::{Hmac, Mac}; use sha1::Sha1; use std::borrow::Cow; use std::net::SocketAddr; use std::vec; macro_rules! impl_decode { ($decoder:ty, $item:ident, $and_then:expr) => { impl Decode for $decoder { type Item = $item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.0.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { track!(self.0.finish_decoding()).and_then($and_then) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl TryTaggedDecode for $decoder { type Tag = AttributeType; fn try_start_decoding(&mut self, attr_type: Self::Tag) -> Result { Ok(attr_type.as_u16() == $item::CODEPOINT) } } }; } macro_rules! impl_encode { ($encoder:ty, $item:ty, $map_from:expr) => { impl Encode for $encoder { type Item = $item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } #[allow(clippy::redundant_closure_call)] fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.0.start_encoding($map_from(item))) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl SizedEncode for $encoder { fn exact_requiring_bytes(&self) -> u64 { self.0.exact_requiring_bytes() } } }; } /// `ALTERNATE-SERVER` attribute. /// /// See [RFC 5389 -- 15.11. ALTERNATE-SERVER] about this attribute. /// /// [RFC 5389 -- 15.11. ALTERNATE-SERVER]: https://tools.ietf.org/html/rfc5389#section-15.11 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AlternateServer(SocketAddr); impl AlternateServer { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x8023; /// Makes a new `AlternateServer` instance. pub fn new(addr: SocketAddr) -> Self { AlternateServer(addr) } /// Returns the alternate address. pub fn address(&self) -> SocketAddr { self.0 } } impl Attribute for AlternateServer { type Decoder = AlternateServerDecoder; type Encoder = AlternateServerEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`AlternateServer`] decoder. #[derive(Debug, Default)] pub struct AlternateServerDecoder(SocketAddrDecoder); impl AlternateServerDecoder { /// Makes a new `AlternateServerDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(AlternateServerDecoder, AlternateServer, |item| Ok( AlternateServer(item) )); /// [`AlternateServer`] encoder. #[derive(Debug, Default)] pub struct AlternateServerEncoder(SocketAddrEncoder); impl AlternateServerEncoder { /// Makes a new `AlternateServerEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( AlternateServerEncoder, AlternateServer, |item: Self::Item| item.0 ); /// `ERROR-CODE` attribute. /// /// See [RFC 5389 -- 15.6. ERROR-CODE] about this attribute. /// /// [RFC 5389 -- 15.6. ERROR-CODE]: https://tools.ietf.org/html/rfc5389#section-15.6 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ErrorCode { code: u16, reason_phrase: String, } impl ErrorCode { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0009; /// Makes a new `ErrorCode` instance. /// /// # Errors /// /// Note that the value of `code` must be in range of `300..600`. /// If the value is out-of-range this will return an `ErrorKind::InvalidInput` error. pub fn new(code: u16, reason_phrase: String) -> Result { track_assert!((300..600).contains(&code), ErrorKind::InvalidInput; code, reason_phrase); Ok(ErrorCode { code, reason_phrase, }) } /// Returns the code of this error. pub fn code(&self) -> u16 { self.code } /// Returns the reason phrase of this error. pub fn reason_phrase(&self) -> &str { &self.reason_phrase } } impl Attribute for ErrorCode { type Decoder = ErrorCodeDecoder; type Encoder = ErrorCodeEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } impl From for ErrorCode { fn from(f: Error) -> Self { match *f.kind() { ErrorKind::InvalidInput => errors::BadRequest.into(), _ => errors::ServerError.into(), } } } /// [`ErrorCode`] decoder. #[derive(Debug, Default)] pub struct ErrorCodeDecoder(TupleDecoder<(U32beDecoder, Utf8Decoder)>); impl ErrorCodeDecoder { /// Makes a new `ErrorCodeDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(ErrorCodeDecoder, ErrorCode, |(value, reason_phrase): ( u32, _ )| { let class = (value >> 8) & 0b111; let number = value & 0b1111_1111; track_assert!((3..6).contains(&class), ErrorKind::InvalidInput); track_assert!(number < 100, ErrorKind::InvalidInput); let code = (class * 100 + number) as u16; Ok(ErrorCode { code, reason_phrase, }) }); /// [`ErrorCode`] encoder. #[derive(Debug, Default)] pub struct ErrorCodeEncoder(TupleEncoder<(U32beEncoder, Utf8Encoder)>); impl ErrorCodeEncoder { /// Makes a new `ErrorCodeEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(ErrorCodeEncoder, ErrorCode, |item: Self::Item| { let class = u32::from(item.code / 100); let number = u32::from(item.code % 100); let value = (class << 8) | number; (value, item.reason_phrase) }); /// `FINGERPRINT` attribute. /// /// See [RFC 5389 -- 15.5. FINGERPRINT] about this attribute. /// /// [RFC 5389 -- 15.5. FINGERPRINT]: https://tools.ietf.org/html/rfc5389#section-15.5 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Fingerprint { crc32: u32, } impl Fingerprint { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x8028; /// Calculates the CRC-32 value of `message` and returns a `Fingerprint` instance containing it. pub fn new(message: &Message) -> Result { let mut bytes = track!(MessageEncoder::default().encode_into_bytes(message.clone()))?; let final_len = bytes.len() as u16 - 20 + 8; // Adds `Fingerprint` attribute length BigEndian::write_u16(&mut bytes[2..4], final_len); let crc32 = crc::Crc::::new(&crc::CRC_32_ISO_HDLC).checksum(&bytes[..]) ^ 0x5354_554e; Ok(Fingerprint { crc32 }) } /// Returns the crc32 value of this instance. pub fn crc32(&self) -> u32 { self.crc32 } } impl Attribute for Fingerprint { type Decoder = FingerprintDecoder; type Encoder = FingerprintEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } fn after_decode(&mut self, message: &Message) -> Result<()> { let actual = track!(Self::new(message))?; track_assert_eq!(actual.crc32, self.crc32, ErrorKind::InvalidInput); Ok(()) } } /// [`Fingerprint`] decoder. #[derive(Debug, Default)] pub struct FingerprintDecoder(U32beDecoder); impl FingerprintDecoder { /// Makes a new `FingerprintDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(FingerprintDecoder, Fingerprint, |crc32| Ok(Fingerprint { crc32 })); /// [`Fingerprint`] encoder. #[derive(Debug, Default)] pub struct FingerprintEncoder(U32beEncoder); impl FingerprintEncoder { /// Makes a new `FingerprintEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(FingerprintEncoder, Fingerprint, |item: Self::Item| item .crc32); /// `MAPPED-ADDRESS` attribute. /// /// See [RFC 5389 -- 15.1. MAPPED-ADDRESS] about this attribute. /// /// [RFC 5389 -- 15.1. MAPPED-ADDRESS]: https://tools.ietf.org/html/rfc5389#section-15.1 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MappedAddress(SocketAddr); impl MappedAddress { /// The codepoint of the tyep of the attribute. pub const CODEPOINT: u16 = 0x0001; /// Makes a new `MappedAddress` instance. pub fn new(addr: SocketAddr) -> Self { MappedAddress(addr) } /// Returns the address of this instance. pub fn address(&self) -> SocketAddr { self.0 } } impl Attribute for MappedAddress { type Decoder = MappedAddressDecoder; type Encoder = MappedAddressEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`MappedAddress`] decoder. #[derive(Debug, Default)] pub struct MappedAddressDecoder(SocketAddrDecoder); impl MappedAddressDecoder { /// Makes a new `MappedAddressDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(MappedAddressDecoder, MappedAddress, |item| Ok( MappedAddress(item) )); /// [`MappedAddress`] encoder. #[derive(Debug, Default)] pub struct MappedAddressEncoder(SocketAddrEncoder); impl MappedAddressEncoder { /// Makes a new `MappedAddressEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(MappedAddressEncoder, MappedAddress, |item: Self::Item| item .0); /// `MESSAGE-INTEGRITY` attribute. /// /// See [RFC 5389 -- 15.3. MESSAGE-INTEGRITY] about this attribute. /// /// [RFC 5389 -- 15.3. MESSAGE-INTEGRITY]: https://tools.ietf.org/html/rfc5389#section-15.4 /// /// # TODO /// /// - Support SASLprep /// #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MessageIntegrity { hmac_sha1: [u8; 20], preceding_message_bytes: Vec, } impl MessageIntegrity { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0008; /// utility function for creating HMAC-SHA1 signatures fn generate_hmac_token(key: &[u8], message: &[u8]) -> [u8; 20] { // Create the hasher with the key. We can use expect for Hmac algorithms as they allow arbitrary key sizes. let mut hasher: Hmac = Mac::new_from_slice(key).expect("HMAC algoritms can take keys of any size"); // hash the message hasher.update(message); // finalize the hash and convert to a static array hasher.finalize().into_bytes().into() } /// Makes a new `MessageIntegrity` instance for short-term credentials. pub fn new_short_term_credential(message: &Message, password: &str) -> Result where A: Attribute, { let key = password.as_bytes(); let preceding_message_bytes = track!(Self::message_into_bytes(message.clone()))?; let hmac_sha1 = Self::generate_hmac_token(key, &preceding_message_bytes); Ok(MessageIntegrity { hmac_sha1, preceding_message_bytes, }) } /// Makes a new `MessageIntegrity` instance for long-term credentials. pub fn new_long_term_credential( message: &Message, username: &Username, realm: &Realm, password: &str, ) -> Result where A: Attribute, { let key = md5::compute(format!("{}:{}:{}", username.name(), realm.text(), password).as_bytes()); let preceding_message_bytes = track!(Self::message_into_bytes(message.clone()))?; let hmac_sha1 = Self::generate_hmac_token(&key.0[..], &preceding_message_bytes); Ok(MessageIntegrity { hmac_sha1, preceding_message_bytes, }) } /// Checks whether this has the valid short-term credential for `password`. pub fn check_short_term_credential( &self, password: &str, ) -> std::result::Result<(), ErrorCode> { let key = password.as_bytes(); let expected = Self::generate_hmac_token(key, &self.preceding_message_bytes); if self.hmac_sha1 == expected { Ok(()) } else { Err(errors::Unauthorized.into()) } } /// Checks whether this has the valid long-term credential for `password`. pub fn check_long_term_credential( &self, username: &Username, realm: &Realm, password: &str, ) -> std::result::Result<(), ErrorCode> { let key = md5::compute(format!("{}:{}:{}", username.name(), realm.text(), password).as_bytes()); let expected = Self::generate_hmac_token(&key.0[..], &self.preceding_message_bytes); if self.hmac_sha1 == expected { Ok(()) } else { Err(errors::Unauthorized.into()) } } /// Returns the HMAC-SHA1 of this instance. pub fn hmac_sha1(&self) -> [u8; 20] { self.hmac_sha1 } fn message_into_bytes(message: Message) -> Result> { let mut bytes = track!(MessageEncoder::default().encode_into_bytes(message))?; let adjusted_len = bytes.len() - 20 /*msg header*/+ 4 /*attr header*/ + 20 /*hmac*/; BigEndian::write_u16(&mut bytes[2..4], adjusted_len as u16); Ok(bytes) } } impl Attribute for MessageIntegrity { type Decoder = MessageIntegrityDecoder; type Encoder = MessageIntegrityEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } fn after_decode(&mut self, message: &Message) -> Result<()> { self.preceding_message_bytes = track!(Self::message_into_bytes(message.clone()))?; Ok(()) } } /// [`MessageIntegrity`] decoder. #[derive(Debug, Default)] pub struct MessageIntegrityDecoder(CopyableBytesDecoder<[u8; 20]>); impl MessageIntegrityDecoder { /// Makes a new `MessageIntegrityDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(MessageIntegrityDecoder, MessageIntegrity, |hmac_sha1| Ok( MessageIntegrity { hmac_sha1, preceding_message_bytes: Vec::new() // dummy } )); /// [`MessageIntegrity`] encoder. #[derive(Debug, Default)] pub struct MessageIntegrityEncoder(BytesEncoder<[u8; 20]>); impl MessageIntegrityEncoder { /// Makes a new `MessageIntegrityEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( MessageIntegrityEncoder, MessageIntegrity, |item: Self::Item| item.hmac_sha1 ); /// `NONCE` attribute. /// /// See [RFC 5389 -- 15.8. NONCE] about this attribute. /// /// [RFC 5389 -- 15.8. NONCE]: https://tools.ietf.org/html/rfc5389#section-15.8 /// /// # TODO /// /// - Support [RFC 3261] and [RFC 2617] /// #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Nonce { value: String, } impl Nonce { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0015; /// Makes a new `Nonce` instance. /// /// # Errors /// /// The length of `value` must be less than `128` characters. /// If it is too long, this will return an `ErrorKind::InvalidInput` error. pub fn new(value: String) -> Result { track_assert!(value.chars().count() < 128, ErrorKind::InvalidInput; value); Ok(Nonce { value }) } /// Returns the value of this instance. pub fn value(&self) -> &str { &self.value } } impl Attribute for Nonce { type Decoder = NonceDecoder; type Encoder = NonceEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`Nonce`] decoder. #[derive(Debug, Default)] pub struct NonceDecoder(Utf8Decoder); impl NonceDecoder { /// Makes a new `NonceDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(NonceDecoder, Nonce, Nonce::new); /// [`Nonce`] encoder. #[derive(Debug, Default)] pub struct NonceEncoder(Utf8Encoder); impl NonceEncoder { /// Makes a new `NonceEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(NonceEncoder, Nonce, |item: Self::Item| item.value); /// `REALM` attribute. /// /// See [RFC 5389 -- 15.7. REALM] about this attribute. /// /// [RFC 5389 -- 15.7. REALM]: https://tools.ietf.org/html/rfc5389#section-15.7 /// /// # TODO /// /// - Support SASLprep [RFC 4013] /// #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Realm { text: String, } impl Realm { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0014; /// Makes a new `Realm` instance. /// /// # Errors /// /// The length of `text` must be less than `128` characters. /// If it is too long, this will return an `ErrorKind::InvalidInput` error. pub fn new(text: String) -> Result { track_assert!( text.chars().count() < 128, ErrorKind::InvalidInput; text); Ok(Realm { text }) } /// Returns the text of this instance. pub fn text(&self) -> &str { &self.text } } impl Attribute for Realm { type Decoder = RealmDecoder; type Encoder = RealmEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`Realm`] decoder. #[derive(Debug, Default)] pub struct RealmDecoder(Utf8Decoder); impl RealmDecoder { /// Makes a new `RealmDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(RealmDecoder, Realm, Realm::new); /// [`Realm`] encoder. #[derive(Debug, Default)] pub struct RealmEncoder(Utf8Encoder); impl RealmEncoder { /// Makes a new `RealmEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(RealmEncoder, Realm, |item: Self::Item| item.text); /// `SOFTWARE` attribute. /// /// See [RFC 5389 -- 15.10. SOFTWARE] about this attribute. /// /// [RFC 5389 -- 15.10. SOFTWARE]: https://tools.ietf.org/html/rfc5389#section-15.10 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Software { description: Cow<'static, str>, } impl Software { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x8022; /// Makes a new `Software` instance. /// /// # Errors /// /// The length of `description` must be less than `128` characters. /// If it is too long, this will return an `ErrorKind::InvalidInput` error. pub fn new(description: String) -> Result { track_assert!(description.chars().count() < 128, ErrorKind::InvalidInput; description); Ok(Software { description: description.into(), }) } /// Makes a new `Software` instance from a static string. /// /// This function is const, so you can create this in a const context. /// /// # Panics /// /// The length of `description` must be less than `128` characters. /// Panics if the string is longer. pub const fn new_static(description: &'static str) -> Self { if description.len() >= 128 { panic!("Description for `Software` cannot be longer than 128 characters."); } Self { description: Cow::Borrowed(description), } } /// Returns the description of this instance. pub fn description(&self) -> &str { &self.description } } impl Attribute for Software { type Decoder = SoftwareDecoder; type Encoder = SoftwareEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`Software`] decoder. #[derive(Debug, Default)] pub struct SoftwareDecoder(Utf8Decoder); impl SoftwareDecoder { /// Makes a new `SoftwareDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(SoftwareDecoder, Software, Software::new); /// [`Software`] encoder. #[derive(Debug, Default)] pub struct SoftwareEncoder(Utf8Encoder>); impl SoftwareEncoder { /// Makes a new `SoftwareEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(SoftwareEncoder, Software, |item: Self::Item| item .description); /// `UNKNOWN-ATTRIBUTES` attribute. /// /// See [RFC 5389 -- 15.9. UNKNOWN-ATTRIBUTES] about this attribute. /// /// [RFC 5389 -- 15.9. UNKNOWN-ATTRIBUTES]: https://tools.ietf.org/html/rfc5389#section-15.9 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UnknownAttributes { unknowns: Vec, } impl UnknownAttributes { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x000A; /// Makes a new `UnknownAttributes` instance. pub fn new(unknowns: Vec) -> Self { UnknownAttributes { unknowns } } /// Returns the unknown attribute types of this instance. pub fn unknowns(&self) -> &[AttributeType] { &self.unknowns } } impl Attribute for UnknownAttributes { type Decoder = UnknownAttributesDecoder; type Encoder = UnknownAttributesEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`UnknownAttributes`] decoder. #[derive(Debug, Default)] pub struct UnknownAttributesDecoder(Collect>); impl UnknownAttributesDecoder { /// Makes a new `UnknownAttributesDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(UnknownAttributesDecoder, UnknownAttributes, |vs: Vec< u16, >| Ok( UnknownAttributes { unknowns: vs.into_iter().map(AttributeType::new).collect() } )); /// [`UnknownAttributes`] encoder. #[derive(Debug, Default)] pub struct UnknownAttributesEncoder(PreEncode>>); impl UnknownAttributesEncoder { /// Makes a new `UnknownAttributesEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( UnknownAttributesEncoder, UnknownAttributes, |item: Self::Item| item .unknowns .into_iter() .map(|ty| ty.as_u16()) .collect::>() .into_iter() ); /// `USERNAME` attribute. /// /// See [RFC 5389 -- 15.3. USERNAME] about this attribute. /// /// [RFC 5389 -- 15.3. USERNAME]: https://tools.ietf.org/html/rfc5389#section-15.3 /// /// # TODO /// /// - Support SASLprep [RFC 4013] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Username { name: String, } impl Username { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0006; /// Makes a new `Username` instance. /// /// # Errors /// /// The length of `name` must be less then `513` bytes. /// If it is too long, this will return an `ErrorKind::InvalidInput` error. pub fn new(name: String) -> Result { track_assert!(name.len() < 513, ErrorKind::InvalidInput; name); Ok(Username { name }) } /// Returns the name of this instance. pub fn name(&self) -> &str { &self.name } } impl Attribute for Username { type Decoder = UsernameDecoder; type Encoder = UsernameEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`Username`] decoder. #[derive(Debug, Default)] pub struct UsernameDecoder(Utf8Decoder); impl UsernameDecoder { /// Makes a new `UsernameDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(UsernameDecoder, Username, Username::new); /// [`Username`] encoder. #[derive(Debug, Default)] pub struct UsernameEncoder(Utf8Encoder); impl UsernameEncoder { /// Makes a new `UsernameEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(UsernameEncoder, Username, |item: Self::Item| item.name); /// `XOR-MAPPED-ADDRESS` attribute. /// /// See [RFC 5389 -- 15.2. XOR-MAPPED-ADDRESS] about this attribute. /// /// [RFC 5389 -- 15.2. XOR-MAPPED-ADDRESS]: https://tools.ietf.org/html/rfc5389#section-15.2 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct XorMappedAddress(SocketAddr); impl XorMappedAddress { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0020; /// Makes a new `XorMappedAddress` instance. pub fn new(addr: SocketAddr) -> Self { XorMappedAddress(addr) } /// Returns the address of this instance. pub fn address(&self) -> SocketAddr { self.0 } } impl Attribute for XorMappedAddress { type Decoder = XorMappedAddressDecoder; type Encoder = XorMappedAddressEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } fn before_encode(&mut self, message: &Message) -> Result<()> { self.0 = socket_addr_xor(self.0, message.transaction_id()); Ok(()) } fn after_decode(&mut self, message: &Message) -> Result<()> { self.0 = socket_addr_xor(self.0, message.transaction_id()); Ok(()) } } /// [`XorMappedAddress`] decoder. #[derive(Debug, Default)] pub struct XorMappedAddressDecoder(SocketAddrDecoder); impl XorMappedAddressDecoder { /// Makes a new `XorMappedAddressDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(XorMappedAddressDecoder, XorMappedAddress, |item| Ok( XorMappedAddress(item) )); /// [`XorMappedAddress`] encoder. #[derive(Debug, Default)] pub struct XorMappedAddressEncoder(SocketAddrEncoder); impl XorMappedAddressEncoder { /// Makes a new `XorMappedAddressEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( XorMappedAddressEncoder, XorMappedAddress, |item: Self::Item| item.0 ); /// `XOR-MAPPED-ADDRESS` attribute with an alternative code. /// /// Such attribute is returned by e.g. "Vovida.org 0.98-CPC" on stun.counterpath.net #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct XorMappedAddress2(SocketAddr); impl XorMappedAddress2 { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x8020; /// Makes a new `XorMappedAddress2` instance. pub fn new(addr: SocketAddr) -> Self { XorMappedAddress2(addr) } /// Returns the address of this instance. pub fn address(&self) -> SocketAddr { self.0 } } impl Attribute for XorMappedAddress2 { type Decoder = XorMappedAddress2Decoder; type Encoder = XorMappedAddress2Encoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } fn before_encode(&mut self, message: &Message) -> Result<()> { self.0 = socket_addr_xor(self.0, message.transaction_id()); Ok(()) } fn after_decode(&mut self, message: &Message) -> Result<()> { self.0 = socket_addr_xor(self.0, message.transaction_id()); Ok(()) } } /// [`XorMappedAddress2`] decoder. #[derive(Debug, Default)] pub struct XorMappedAddress2Decoder(SocketAddrDecoder); impl XorMappedAddress2Decoder { /// Makes a new `XorMappedAddressDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(XorMappedAddress2Decoder, XorMappedAddress2, |item| Ok( XorMappedAddress2(item) )); /// [`XorMappedAddress`] encoder. #[derive(Debug, Default)] pub struct XorMappedAddress2Encoder(SocketAddrEncoder); impl XorMappedAddress2Encoder { /// Makes a new `XorMappedAddressEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( XorMappedAddress2Encoder, XorMappedAddress2, |item: Self::Item| item.0 ); stun_codec-0.3.4/src/rfc5389/errors.rs000064400000000000000000000115431046102023000155360ustar 00000000000000//! Error codes that are defined in [RFC 5389 -- 15.6 ERROR-CODE]. //! //! [RFC 5389 -- 15.6 ERROR-CODE]: https://tools.ietf.org/html/rfc5389#section-15.6 use crate::rfc5389::attributes::ErrorCode; /// `300`: "Try Alternate". /// /// > The client should contact an alternate server for /// > this request. This error response MUST only be sent if the /// > request included a USERNAME attribute and a valid MESSAGE- /// > INTEGRITY attribute; otherwise, it MUST NOT be sent and error /// > code 400 (Bad Request) is suggested. This error response MUST /// > be protected with the MESSAGE-INTEGRITY attribute, and receivers /// > MUST validate the MESSAGE-INTEGRITY of this response before /// > redirecting themselves to an alternate server. /// > /// > > Note: Failure to generate and validate message integrity /// > > for a 300 response allows an on-path attacker to falsify a /// > > 300 response thus causing subsequent STUN messages to be /// > > sent to a victim. /// > /// > [RFC 5389 -- 15.6 ERROR-CODE] /// /// [RFC 5389 -- 15.6 ERROR-CODE]: https://tools.ietf.org/html/rfc5389#section-15.6 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TryAlternate; impl TryAlternate { /// The codepoint of the error. pub const CODEPOINT: u16 = 300; } impl From for ErrorCode { fn from(_: TryAlternate) -> Self { ErrorCode::new(TryAlternate::CODEPOINT, "Try Alternate".to_owned()).expect("never fails") } } /// `400`: "Bad Request". /// /// > The request was malformed. The client SHOULD NOT /// > retry the request without modification from the previous /// > attempt. The server may not be able to generate a valid /// > MESSAGE-INTEGRITY for this error, so the client MUST NOT expect /// > a valid MESSAGE-INTEGRITY attribute on this response. /// > /// > [RFC 5389 -- 15.6 ERROR-CODE] /// /// [RFC 5389 -- 15.6 ERROR-CODE]: https://tools.ietf.org/html/rfc5389#section-15.6 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct BadRequest; impl BadRequest { /// The codepoint of the error. pub const CODEPOINT: u16 = 400; } impl From for ErrorCode { fn from(_: BadRequest) -> Self { ErrorCode::new(BadRequest::CODEPOINT, "Bad Request".to_owned()).expect("never fails") } } /// `401`: "Unauthorized". /// /// > The request did not contain the correct /// > credentials to proceed. The client should retry the request /// > with proper credentials. /// > /// > [RFC 5389 -- 15.6 ERROR-CODE] /// /// [RFC 5389 -- 15.6 ERROR-CODE]: https://tools.ietf.org/html/rfc5389#section-15.6 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Unauthorized; impl Unauthorized { /// The codepoint of the error. pub const CODEPOINT: u16 = 401; } impl From for ErrorCode { fn from(_: Unauthorized) -> Self { ErrorCode::new(Unauthorized::CODEPOINT, "Unauthorized".to_owned()).expect("never fails") } } /// `420`: "Unknown Attribute". /// /// > The server received a STUN packet containing /// > a comprehension-required attribute that it did not understand. /// > The server MUST put this unknown attribute in the UNKNOWN- /// > ATTRIBUTE attribute of its error response. /// > /// > [RFC 5389 -- 15.6 ERROR-CODE] /// /// [RFC 5389 -- 15.6 ERROR-CODE]: https://tools.ietf.org/html/rfc5389#section-15.6 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct UnknownAttribute; impl UnknownAttribute { /// The codepoint of the error. pub const CODEPOINT: u16 = 420; } impl From for ErrorCode { fn from(_: UnknownAttribute) -> Self { ErrorCode::new(UnknownAttribute::CODEPOINT, "Unknown Attribute".to_owned()) .expect("never fails") } } /// `438`: "Stale Nonce". /// /// > The NONCE used by the client was no longer valid. /// > The client should retry, using the NONCE provided in the /// > response. /// > /// > [RFC 5389 -- 15.6 ERROR-CODE] /// /// [RFC 5389 -- 15.6 ERROR-CODE]: https://tools.ietf.org/html/rfc5389#section-15.6 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StaleNonce; impl StaleNonce { /// The codepoint of the error. pub const CODEPOINT: u16 = 438; } impl From for ErrorCode { fn from(_: StaleNonce) -> Self { ErrorCode::new(StaleNonce::CODEPOINT, "Stale Nonce".to_owned()).expect("never fails") } } /// `500`: "Server Error". /// /// > The server has suffered a temporary error. The /// > client should try again. /// > /// > [RFC 5389 -- 15.6 ERROR-CODE] /// /// [RFC 5389 -- 15.6 ERROR-CODE]: https://tools.ietf.org/html/rfc5389#section-15.6 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ServerError; impl ServerError { /// The codepoint of the error. pub const CODEPOINT: u16 = 500; } impl From for ErrorCode { fn from(_: ServerError) -> Self { ErrorCode::new(ServerError::CODEPOINT, "Server Error".to_owned()).expect("never fails") } } stun_codec-0.3.4/src/rfc5389/methods.rs000064400000000000000000000041471046102023000156670ustar 00000000000000//! Methods that are defined in [RFC 5389]. //! //! [RFC 5389]: https://tools.ietf.org/html/rfc5389 use crate::Method; /// Binding method. /// /// > This document defines a single method called Binding. The Binding /// > method can be used either in request/response transactions or in /// > indication transactions. When used in request/response transactions, /// > the Binding method can be used to determine the particular "binding" /// > a NAT has allocated to a STUN client. When used in either request/ /// > response or in indication transactions, the Binding method can also /// > be used to keep these "bindings" alive. /// > /// > In the Binding request/response transaction, a Binding request is /// > sent from a STUN client to a STUN server. When the Binding request /// > arrives at the STUN server, it may have passed through one or more /// > NATs between the STUN client and the STUN server (in Figure 1, there /// > were two such NATs). As the Binding request message passes through a /// > NAT, the NAT will modify the source transport address (that is, the /// > source IP address and the source port) of the packet. As a result, /// > the source transport address of the request received by the server /// > will be the public IP address and port created by the NAT closest to /// > the server. This is called a reflexive transport address. The STUN /// > server copies that source transport address into an XOR-MAPPED- /// > ADDRESS attribute in the STUN Binding response and sends the Binding /// > response back to the STUN client. As this packet passes back through /// > a NAT, the NAT will modify the destination transport address in the /// > IP header, but the transport address in the XOR-MAPPED-ADDRESS /// > attribute within the body of the STUN response will remain untouched. /// > In this way, the client can learn its reflexive transport address /// > allocated by the outermost NAT with respect to the STUN server. /// > /// > [RFC 5389 -- 3. Overview of Operation] /// /// [RFC 5389 -- 3. Overview of Operation]: https://tools.ietf.org/html/rfc5389#section-3 pub const BINDING: Method = Method(0x0001); stun_codec-0.3.4/src/rfc5389/mod.rs000064400000000000000000000010421046102023000147720ustar 00000000000000//! [RFC 5389(STUN)][RFC 5389] specific components. //! //! [RFC 5389]: https://tools.ietf.org/html/rfc5389 use self::attributes::*; pub mod attributes; pub mod errors; pub mod methods; define_attribute_enums!( Attribute, AttributeDecoder, AttributeEncoder, [ MappedAddress, Username, MessageIntegrity, ErrorCode, UnknownAttributes, Realm, Nonce, XorMappedAddress, XorMappedAddress2, Software, AlternateServer, Fingerprint ] ); stun_codec-0.3.4/src/rfc5766/attributes.rs000064400000000000000000000435321046102023000164120ustar 00000000000000//! Attributes that are defined in [RFC 5766 -- 14. New STUN Attributes]. //! //! [RFC 5766 -- 14. New STUN Attributes]: https://tools.ietf.org/html/rfc5766#section-14 use crate::attribute::{Attribute, AttributeType}; use crate::message::Message; use crate::net::{socket_addr_xor, SocketAddrDecoder, SocketAddrEncoder}; use bytecodec::bytes::{BytesEncoder, RemainingBytesDecoder}; use bytecodec::fixnum::{ U32beDecoder, U32beEncoder, U64beDecoder, U64beEncoder, U8Decoder, U8Encoder, }; use bytecodec::null::{NullDecoder, NullEncoder}; use bytecodec::{ByteCount, Decode, Encode, Eos, ErrorKind, Result, SizedEncode, TryTaggedDecode}; use std::net::SocketAddr; use std::time::Duration; macro_rules! impl_decode { ($decoder:ty, $item:ident, $and_then:expr) => { impl Decode for $decoder { type Item = $item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.0.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { track!(self.0.finish_decoding()).and_then($and_then) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl TryTaggedDecode for $decoder { type Tag = AttributeType; fn try_start_decoding(&mut self, attr_type: Self::Tag) -> Result { Ok(attr_type.as_u16() == $item::CODEPOINT) } } }; } macro_rules! impl_encode { ($encoder:ty, $item:ty, $map_from:expr) => { impl Encode for $encoder { type Item = $item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } #[allow(clippy::redundant_closure_call)] fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.0.start_encoding($map_from(item))) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl SizedEncode for $encoder { fn exact_requiring_bytes(&self) -> u64 { self.0.exact_requiring_bytes() } } }; } /// `CHANNEL-NUMBER` attribute. /// /// See [RFC 5766 -- 14.1. CHANNEL-NUMBER] about this attribute. /// /// [RFC 5766 -- 14.1. CHANNEL-NUMBER]: https://tools.ietf.org/html/rfc5766#section-14.1 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ChannelNumber(u16); impl ChannelNumber { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x000C; /// Minimum channel number. pub const MIN: u16 = 0x4000; /// Maximum channel number. pub const MAX: u16 = 0x7FFF; /// Makes a new `ChannelNumber` instance. /// /// /// # Errors /// /// If `n` is not a number between `ChannelNumber::MIN` and `ChannelNumber::MAX`, /// this will return an `ErrorKind::InvalidInput` error. pub fn new(n: u16) -> Result { track_assert!(n >= Self::MIN, ErrorKind::InvalidInput; n); track_assert!(n <= Self::MAX, ErrorKind::InvalidInput; n); Ok(ChannelNumber(n)) } /// Returns the channel number indicated by the attribute. pub fn value(self) -> u16 { self.0 } /// Returns the minimum channel number. pub fn min() -> Self { ChannelNumber(Self::MIN) } /// Returns the maximum channel number. pub fn max() -> Self { ChannelNumber(Self::MAX) } /// Wrapping incrementation. pub fn wrapping_increment(self) -> Self { if self.0 == Self::MAX { Self::min() } else { ChannelNumber(self.0 + 1) } } } impl Attribute for ChannelNumber { type Decoder = ChannelNumberDecoder; type Encoder = ChannelNumberEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`ChannelNumber`] decoder. #[derive(Debug, Default)] pub struct ChannelNumberDecoder(U32beDecoder); impl ChannelNumberDecoder { /// Makes a new `ChannelNumberDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(ChannelNumberDecoder, ChannelNumber, |item| track!( ChannelNumber::new((item >> 16) as u16) )); /// [`ChannelNumber`] encoder. #[derive(Debug, Default)] pub struct ChannelNumberEncoder(U32beEncoder); impl ChannelNumberEncoder { /// Makes a new `ChannelNumberEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( ChannelNumberEncoder, ChannelNumber, |item: Self::Item| u32::from(item.0) << 16 ); /// `LIFETIME` attribute. /// /// See [RFC 5766 -- 14.2. LIFETIME] about this attribute. /// /// [RFC 5766 -- 14.2. LIFETIME]: https://tools.ietf.org/html/rfc5766#section-14.2 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Lifetime(Duration); impl Lifetime { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x000D; /// Makes a new `Lifetime` instance. /// /// Note that the nanoseconds part of `lifetime` is ignored and always set to `0`. /// /// # Errors /// /// If the seconds part of `lifetime` is greater than `0xFFFF_FFFF`, /// this function will return an `ErrorKind::InvalidInput` error. pub fn new(lifetime: Duration) -> Result { let lifetime_seconds = lifetime.as_secs(); track_assert!(lifetime_seconds <= 0xFFFF_FFFF, ErrorKind::InvalidInput); Ok(Lifetime(Duration::from_secs(lifetime_seconds))) } /// Makes a new `Lifetime` instance from `u32` value. pub fn from_u32(lifetime_seconds: u32) -> Self { Lifetime(Duration::from_secs(u64::from(lifetime_seconds))) } /// Returns the lifetime indicated by the attribute. pub fn lifetime(&self) -> Duration { self.0 } } impl Attribute for Lifetime { type Decoder = LifetimeDecoder; type Encoder = LifetimeEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`Lifetime`] decoder. #[derive(Debug, Default)] pub struct LifetimeDecoder(U32beDecoder); impl LifetimeDecoder { /// Makes a new `LifetimeDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(LifetimeDecoder, Lifetime, |item| Ok(Lifetime( Duration::from_secs(u64::from(item)) ))); /// [`Lifetime`] encoder. #[derive(Debug, Default)] pub struct LifetimeEncoder(U32beEncoder); impl LifetimeEncoder { /// Makes a new `LifetimeEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( LifetimeEncoder, Lifetime, |item: Self::Item| item.0.as_secs() as u32 ); /// `XOR-PEER-ADDRESS` attribute. /// /// See [RFC 5766 -- 14.3. XOR-PEER-ADDRESS] about this attribute. /// /// [RFC 5766 -- 14.3. XOR-PEER-ADDRESS]: https://tools.ietf.org/html/rfc5766#section-14.3 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct XorPeerAddress(SocketAddr); impl XorPeerAddress { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0012; /// Makes a new `XorPeerAddress` instance. pub fn new(addr: SocketAddr) -> Self { XorPeerAddress(addr) } /// Returns the address specified by the attribute. pub fn address(&self) -> SocketAddr { self.0 } } impl Attribute for XorPeerAddress { type Decoder = XorPeerAddressDecoder; type Encoder = XorPeerAddressEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } fn before_encode(&mut self, message: &Message) -> Result<()> { self.0 = socket_addr_xor(self.0, message.transaction_id()); Ok(()) } fn after_decode(&mut self, message: &Message) -> Result<()> { self.0 = socket_addr_xor(self.0, message.transaction_id()); Ok(()) } } /// [`XorPeerAddress`] decoder. #[derive(Debug, Default)] pub struct XorPeerAddressDecoder(SocketAddrDecoder); impl XorPeerAddressDecoder { /// Makes a new `XorPeerAddressDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(XorPeerAddressDecoder, XorPeerAddress, |item| Ok( XorPeerAddress(item) )); /// [`XorPeerAddress`] encoder. #[derive(Debug, Default)] pub struct XorPeerAddressEncoder(SocketAddrEncoder); impl XorPeerAddressEncoder { /// Makes a new `XorPeerAddressEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(XorPeerAddressEncoder, XorPeerAddress, |item: Self::Item| { item.0 }); /// `DATA` attribute. /// /// See [RFC 5766 -- 14.4. DATA] about this attribute. /// /// [RFC 5766 -- 14.4. DATA]: https://tools.ietf.org/html/rfc5766#section-14.4 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Data(Vec); impl Data { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0013; /// Makes a new `Data` instance. /// /// # Errors /// /// If the length of `data` is greater than `0xFFFF`, /// this function will return an `ErrorKind::InvalidInput` error. pub fn new(data: Vec) -> Result { track_assert!(data.len() <= 0xFFFF, ErrorKind::InvalidInput); Ok(Data(data)) } /// Returns a reference the data held by the attribute. pub fn data(&self) -> &[u8] { &self.0 } } impl Attribute for Data { type Decoder = DataDecoder; type Encoder = DataEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`Data`] decoder. #[derive(Debug, Default)] pub struct DataDecoder(RemainingBytesDecoder); impl DataDecoder { /// Makes a new `DataDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(DataDecoder, Data, |item| Ok(Data(item))); /// [`Data`] encoder. #[derive(Debug, Default)] pub struct DataEncoder(BytesEncoder); impl DataEncoder { /// Makes a new `DataEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(DataEncoder, Data, |item: Self::Item| item.0); /// `XOR-RELAY-ADDRESS` attribute. /// /// See [RFC 5766 -- 14.5. XOR-RELAY-ADDRESS] about this attribute. /// /// [RFC 5766 -- 14.5. XOR-RELAY-ADDRESS]: https://tools.ietf.org/html/rfc5766#section-14.5 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct XorRelayAddress(SocketAddr); impl XorRelayAddress { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0016; /// Makes a new `XorRelayAddress` instance. pub fn new(addr: SocketAddr) -> Self { XorRelayAddress(addr) } /// Returns the address specified by the attribute. pub fn address(&self) -> SocketAddr { self.0 } } impl Attribute for XorRelayAddress { type Decoder = XorRelayAddressDecoder; type Encoder = XorRelayAddressEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } fn before_encode(&mut self, message: &Message) -> Result<()> { self.0 = socket_addr_xor(self.0, message.transaction_id()); Ok(()) } fn after_decode(&mut self, message: &Message) -> Result<()> { self.0 = socket_addr_xor(self.0, message.transaction_id()); Ok(()) } } /// [`XorRelayAddress`] decoder. #[derive(Debug, Default)] pub struct XorRelayAddressDecoder(SocketAddrDecoder); impl XorRelayAddressDecoder { /// Makes a new `XorRelayAddressDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(XorRelayAddressDecoder, XorRelayAddress, |item| Ok( XorRelayAddress(item) )); /// [`XorRelayAddress`] encoder. #[derive(Debug, Default)] pub struct XorRelayAddressEncoder(SocketAddrEncoder); impl XorRelayAddressEncoder { /// Makes a new `XorRelayAddressEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( XorRelayAddressEncoder, XorRelayAddress, |item: Self::Item| item.0 ); /// `EVEN-PORT` attribute. /// /// See [RFC 5766 -- 14.6. EVEN-PORT] about this attribute. /// /// [RFC 5766 -- 14.6. EVEN-PORT]: https://tools.ietf.org/html/rfc5766#section-14.6 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct EvenPort(bool); impl EvenPort { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0018; /// Makes a new `EvenPort` instance. pub fn new(is_requested: bool) -> Self { EvenPort(is_requested) } /// Returns whether the client requested that the port in the relayed transport address be even. pub fn is_requested(&self) -> bool { self.0 } } impl Attribute for EvenPort { type Decoder = EvenPortDecoder; type Encoder = EvenPortEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`EvenPort`] decoder. #[derive(Debug, Default)] pub struct EvenPortDecoder(U8Decoder); impl EvenPortDecoder { /// Makes a new `EvenPortDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(EvenPortDecoder, EvenPort, |item| Ok(EvenPort( (item & 0b1000_0000) != 0 ))); /// [`EvenPort`] encoder. #[derive(Debug, Default)] pub struct EvenPortEncoder(U8Encoder); impl EvenPortEncoder { /// Makes a new `EvenPortEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(EvenPortEncoder, EvenPort, |item: Self::Item| u8::from( item.0 ) << 7); /// `REQUESTED-TRANSPORT` attribute. /// /// See [RFC 5766 -- 14.7. REQUESTED-TRANSPORT] about this attribute. /// /// [RFC 5766 -- 14.7. REQUESTED-TRANSPORT]: https://tools.ietf.org/html/rfc5766#section-14.7 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RequestedTransport(u8); impl RequestedTransport { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0019; /// Makes a new `RequestedTransport` instance. pub fn new(protocol: u8) -> Self { RequestedTransport(protocol) } /// Returns the transport protocol requested by the client. pub fn protocol(&self) -> u8 { self.0 } } impl Attribute for RequestedTransport { type Decoder = RequestedTransportDecoder; type Encoder = RequestedTransportEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`RequestedTransport`] decoder. #[derive(Debug, Default)] pub struct RequestedTransportDecoder(U32beDecoder); impl RequestedTransportDecoder { /// Makes a new `RequestedTransportDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(RequestedTransportDecoder, RequestedTransport, |item| Ok( RequestedTransport((item >> 24) as u8) )); /// [`RequestedTransport`] encoder. #[derive(Debug, Default)] pub struct RequestedTransportEncoder(U32beEncoder); impl RequestedTransportEncoder { /// Makes a new `RequestedTransportEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( RequestedTransportEncoder, RequestedTransport, |item: Self::Item| u32::from(item.0) << 24 ); /// `DONT-FRAGMENT` attribute. /// /// See [RFC 5766 -- 14.8. DONT-FRAGMENT] about this attribute. /// /// [RFC 5766 -- 14.8. DONT-FRAGMENT]: https://tools.ietf.org/html/rfc5766#section-14.8 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct DontFragment; impl DontFragment { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x001A; } impl Attribute for DontFragment { type Decoder = DontFragmentDecoder; type Encoder = DontFragmentEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`DontFragment`] decoder. #[derive(Debug, Default)] pub struct DontFragmentDecoder(NullDecoder); impl DontFragmentDecoder { /// Makes a new `DontFragmentDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(DontFragmentDecoder, DontFragment, |()| Ok(DontFragment)); /// [`DontFragment`] encoder. #[derive(Debug, Default)] pub struct DontFragmentEncoder(NullEncoder); impl DontFragmentEncoder { /// Makes a new `DontFragmentEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(DontFragmentEncoder, DontFragment, |_: Self::Item| ()); /// `RESERVATION-TOKEN` attribute. /// /// See [RFC 5766 -- 14.9. RESERVATION-TOKEN] about this attribute. /// /// [RFC 5766 -- 14.9. RESERVATION-TOKEN]: https://tools.ietf.org/html/rfc5766#section-14.9 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ReservationToken(u64); impl ReservationToken { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0022; /// Makes a new `ReservationToken` instance. pub fn new(token: u64) -> Self { ReservationToken(token) } /// Returns the token value contained by the attribute. pub fn token(&self) -> u64 { self.0 } } impl Attribute for ReservationToken { type Decoder = ReservationTokenDecoder; type Encoder = ReservationTokenEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`ReservationToken`] decoder. #[derive(Debug, Default)] pub struct ReservationTokenDecoder(U64beDecoder); impl ReservationTokenDecoder { /// Makes a new `ReservationTokenDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(ReservationTokenDecoder, ReservationToken, |item| Ok( ReservationToken(item) )); /// [`ReservationToken`] encoder. #[derive(Debug, Default)] pub struct ReservationTokenEncoder(U64beEncoder); impl ReservationTokenEncoder { /// Makes a new `ReservationTokenEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( ReservationTokenEncoder, ReservationToken, |item: Self::Item| item.0 ); stun_codec-0.3.4/src/rfc5766/errors.rs000064400000000000000000000117331046102023000155360ustar 00000000000000//! Error codes that are defined in [RFC 5766 -- 15. New STUN Error Response Codes]. //! //! [RFC 5766 -- 15. New STUN Error Response Codes]: https://tools.ietf.org/html/rfc5766#section-15 use crate::rfc5389::attributes::ErrorCode; /// `403`: "Forbidden". /// /// > The request was valid but cannot be performed due to administrative or similar restrictions. /// > /// > [RFC 5766 -- 15. New STUN Error Response Codes] /// /// [RFC 5766 -- 15. New STUN Error Response Codes]: https://tools.ietf.org/html/rfc5766#section-15 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Forbidden; impl Forbidden { /// The codepoint of the error. pub const CODEPOINT: u16 = 403; } impl From for ErrorCode { fn from(_: Forbidden) -> Self { ErrorCode::new(Forbidden::CODEPOINT, "Forbidden".to_owned()).expect("never fails") } } /// `437`: "Allocation Mismatch". /// /// > A request was received by the server that requires an allocation to be in place, but no allocation exists, /// > or a request was received that requires no allocation, but an allocation exists. /// > /// > [RFC 5766 -- 15. New STUN Error Response Codes] /// /// [RFC 5766 -- 15. New STUN Error Response Codes]: https://tools.ietf.org/html/rfc5766#section-15 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct AllocationMismatch; impl AllocationMismatch { /// The codepoint of the error. pub const CODEPOINT: u16 = 437; } impl From for ErrorCode { fn from(_: AllocationMismatch) -> Self { ErrorCode::new( AllocationMismatch::CODEPOINT, "Allocation Mismatch".to_owned(), ) .expect("never fails") } } /// `441`: "Wrong Credentials". /// /// > The credentials in the (non-Allocate) request do not match those used to create the allocation. /// > /// > [RFC 5766 -- 15. New STUN Error Response Codes] /// /// [RFC 5766 -- 15. New STUN Error Response Codes]: https://tools.ietf.org/html/rfc5766#section-15 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct WrongCredentials; impl WrongCredentials { /// The codepoint of the error. pub const CODEPOINT: u16 = 441; } impl From for ErrorCode { fn from(_: WrongCredentials) -> Self { ErrorCode::new(WrongCredentials::CODEPOINT, "Wrong Credentials".to_owned()) .expect("never fails") } } /// `442`: "Unsupported Transport Protocol". /// /// > The Allocate request asked the server to use a transport protocol between the server and the peer /// > that the server does not support. NOTE: This does NOT refer to the transport protocol used in the 5-tuple. /// > /// > [RFC 5766 -- 15. New STUN Error Response Codes] /// /// [RFC 5766 -- 15. New STUN Error Response Codes]: https://tools.ietf.org/html/rfc5766#section-15 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct UnsupportedTransportProtocol; impl UnsupportedTransportProtocol { /// The codepoint of the error. pub const CODEPOINT: u16 = 442; } impl From for ErrorCode { fn from(_: UnsupportedTransportProtocol) -> Self { ErrorCode::new( UnsupportedTransportProtocol::CODEPOINT, "Unsupported Transport Protocol".to_owned(), ) .expect("never fails") } } /// `486`: "Allocation Quota Reached". /// /// > No more allocations using this username can be created at the present time. /// > /// > [RFC 5766 -- 15. New STUN Error Response Codes] /// /// [RFC 5766 -- 15. New STUN Error Response Codes]: https://tools.ietf.org/html/rfc5766#section-15 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct AllocationQuotaReached; impl AllocationQuotaReached { /// The codepoint of the error. pub const CODEPOINT: u16 = 486; } impl From for ErrorCode { fn from(_: AllocationQuotaReached) -> Self { ErrorCode::new( AllocationQuotaReached::CODEPOINT, "Allocation Quota Reached".to_owned(), ) .expect("never fails") } } /// `508`: "Insufficient Capacity". /// /// > The server is unable to carry out the request due to some capacity limit being reached. /// > In an Allocate response, this could be due to the server having no more relayed transport /// > addresses available at that time, having none with the requested properties, /// > or the one that corresponds to the specified reservation token is not available. /// > /// > [RFC 5766 -- 15. New STUN Error Response Codes] /// /// [RFC 5766 -- 15. New STUN Error Response Codes]: https://tools.ietf.org/html/rfc5766#section-15 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct InsufficientCapacity; impl InsufficientCapacity { /// The codepoint of the error. pub const CODEPOINT: u16 = 508; } impl From for ErrorCode { fn from(_: InsufficientCapacity) -> Self { ErrorCode::new( InsufficientCapacity::CODEPOINT, "Insufficient Capacity".to_owned(), ) .expect("never fails") } } stun_codec-0.3.4/src/rfc5766/methods.rs000064400000000000000000000015401046102023000156600ustar 00000000000000//! Methods that are defined in [RFC 5766 -- 13. New STUN Methods]. //! //! [RFC 5766 -- 13. New STUN Methods]: https://tools.ietf.org/html/rfc5766#section-13 use crate::Method; /// Allocate method. /// /// Only request/response semantics defined. pub const ALLOCATE: Method = Method(0x003); /// Reference method. /// /// Only request/response semantics defined. pub const REFRESH: Method = Method(0x004); /// Send method. /// /// Only indication semantics defined. pub const SEND: Method = Method(0x006); /// Data method. /// /// only indication semantics defined. pub const DATA: Method = Method(0x007); /// CreatePermission method. /// /// Only request/response semantics defined. pub const CREATE_PERMISSION: Method = Method(0x008); /// ChannelBind method. /// /// Only request/response semantics defined. pub const CHANNEL_BIND: Method = Method(0x009); stun_codec-0.3.4/src/rfc5766/mod.rs000064400000000000000000000007441046102023000150010ustar 00000000000000//! [RFC 5766(TURN)][RFC 5766] specific components. //! //! [RFC 5766]: https://tools.ietf.org/html/rfc5766 use self::attributes::*; pub mod attributes; pub mod errors; pub mod methods; define_attribute_enums!( Attribute, AttributeDecoder, AttributeEncoder, [ ChannelNumber, Lifetime, XorPeerAddress, Data, XorRelayAddress, EvenPort, RequestedTransport, DontFragment, ReservationToken ] ); stun_codec-0.3.4/src/rfc5780/attributes.rs000064400000000000000000000207221046102023000164020ustar 00000000000000//! Attributes that are defined in [RFC 5780]. //! //! [RFC 5780]: https://tools.ietf.org/html/rfc5780 use std::net::SocketAddr; use bytecodec::fixnum::{U32beDecoder, U32beEncoder}; use bytecodec::{ByteCount, Decode, Encode, Eos, Result, SizedEncode, TryTaggedDecode}; use crate::attribute::{Attribute, AttributeType}; use crate::net::{SocketAddrDecoder, SocketAddrEncoder}; macro_rules! impl_decode { ($decoder:ty, $item:ident, $and_then:expr) => { impl Decode for $decoder { type Item = $item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.0.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { track!(self.0.finish_decoding()).and_then($and_then) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl TryTaggedDecode for $decoder { type Tag = AttributeType; fn try_start_decoding(&mut self, attr_type: Self::Tag) -> Result { Ok(attr_type.as_u16() == $item::CODEPOINT) } } }; } macro_rules! impl_encode { ($encoder:ty, $item:ty, $map_from:expr) => { impl Encode for $encoder { type Item = $item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } #[allow(clippy::redundant_closure_call)] fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.0.start_encoding($map_from(item).into())) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl SizedEncode for $encoder { fn exact_requiring_bytes(&self) -> u64 { self.0.exact_requiring_bytes() } } }; } /// `CHANGE-REQUEST` attribute. /// /// See [RFC 5780 -- 7.2. CHANGE-REQUEST] about this attribute. /// /// [RFC 5780 -- 7.2. CHANGE-REQUEST]: https://tools.ietf.org/html/rfc5780#section-7.2 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ChangeRequest(bool, bool); impl ChangeRequest { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0003; /// Makes a new `ChangeRequest` instance. pub fn new(ip: bool, port: bool) -> Self { ChangeRequest(ip, port) } /// Returns whether the client requested the server to send the Binding Response with a /// different IP address than the one the Binding Request was received on pub fn ip(&self) -> bool { self.0 } /// Returns whether the client requested the server to send the Binding Response with a /// different port than the one the Binding Request was received on pub fn port(&self) -> bool { self.1 } } impl Attribute for ChangeRequest { type Decoder = ChangeRequestDecoder; type Encoder = ChangeRequestEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`ChangeRequest`] decoder. #[derive(Debug, Default)] pub struct ChangeRequestDecoder(U32beDecoder); impl ChangeRequestDecoder { /// Makes a new `ChangeRequestDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(ChangeRequestDecoder, ChangeRequest, |item| { Ok(ChangeRequest((item & 0x2) != 0, (item & 0x1) != 0)) }); /// [`ChangeRequest`] encoder. #[derive(Debug, Default)] pub struct ChangeRequestEncoder(U32beEncoder); impl ChangeRequestEncoder { /// Makes a new `ChangeRequestEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(ChangeRequestEncoder, ChangeRequest, |item: Self::Item| { let ip = item.0 as u8; let port = item.1 as u8; ((ip << 1 | port) << 1) as u32 }); /// `RESPONSE-ORIGIN` attribute. /// /// See [RFC 5780 -- 7.3. RESPONSE-ORIGIN] about this attribute. /// /// [RFC 5780 -- 7.3. RESPONSE-ORIGIN]: https://tools.ietf.org/html/rfc5780#section-7.3 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ResponseOrigin(SocketAddr); impl ResponseOrigin { /// The codepoint of the tyep of the attribute. pub const CODEPOINT: u16 = 0x802b; /// Makes a new `ResponseOrigin` instance. pub fn new(addr: SocketAddr) -> Self { ResponseOrigin(addr) } /// Returns the address of this instance. pub fn address(&self) -> SocketAddr { self.0 } } impl Attribute for ResponseOrigin { type Decoder = ResponseOriginDecoder; type Encoder = ResponseOriginEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`ResponseOrigin`] decoder. #[derive(Debug, Default)] pub struct ResponseOriginDecoder(SocketAddrDecoder); impl ResponseOriginDecoder { /// Makes a new `ResponseOriginDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(ResponseOriginDecoder, ResponseOrigin, |item| Ok( ResponseOrigin(item) )); /// [`ResponseOrigin`] encoder. /// /// [`ResponseOrigin`]: ./struct.ResponseOrigin.html #[derive(Debug, Default)] pub struct ResponseOriginEncoder(SocketAddrEncoder); impl ResponseOriginEncoder { /// Makes a new `ResponseOriginEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(ResponseOriginEncoder, ResponseOrigin, |item: Self::Item| { item.0 }); /// `OTHER-ADDRESS` attribute. /// /// See [RFC 5780 -- 7.4. OTHER-ADDRESS] about this attribute. /// /// [RFC 5780 -- 7.4. OTHER-ADDRESS]: https://tools.ietf.org/html/rfc5780#section-7.4 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct OtherAddress(SocketAddr); impl OtherAddress { /// The codepoint of the tyep of the attribute. pub const CODEPOINT: u16 = 0x802c; /// Makes a new `OtherAddress` instance. pub fn new(addr: SocketAddr) -> Self { OtherAddress(addr) } /// Returns the address of this instance. pub fn address(&self) -> SocketAddr { self.0 } } impl Attribute for OtherAddress { type Decoder = OtherAddressDecoder; type Encoder = OtherAddressEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`OtherAddress`] decoder. #[derive(Debug, Default)] pub struct OtherAddressDecoder(SocketAddrDecoder); impl OtherAddressDecoder { /// Makes a new `OtherAddressDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(OtherAddressDecoder, OtherAddress, |item| Ok(OtherAddress( item ))); /// [`OtherAddress`] encoder. #[derive(Debug, Default)] pub struct OtherAddressEncoder(SocketAddrEncoder); impl OtherAddressEncoder { /// Makes a new `OtherAddressEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(OtherAddressEncoder, OtherAddress, |item: Self::Item| item.0); /// `RESPONSE-PORT` attribute. /// /// See [RFC 5780 -- 7.5. RESPONSE-PORT] about this attribute. /// /// [RFC 5780 -- 7.5. RESPONSE-PORT]: https://tools.ietf.org/html/rfc5780#section-7.5 #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ResponsePort(u16); impl ResponsePort { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0027; /// Makes a new `ResponsePort` instance. pub fn new(port: u16) -> Self { ResponsePort(port) } /// Returns the address of this instance. pub fn port(&self) -> u16 { self.0 } } impl Attribute for ResponsePort { type Decoder = ResponsePortDecoder; type Encoder = ResponsePortEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`ResponsePort`] decoder. #[derive(Debug, Default)] pub struct ResponsePortDecoder(U32beDecoder); impl ResponsePortDecoder { /// Makes a new `ResponsePortDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(ResponsePortDecoder, ResponsePort, |item| Ok( ResponsePort::new((item >> 16) as u16) )); /// [`ResponsePort`] encoder. #[derive(Debug, Default)] pub struct ResponsePortEncoder(U32beEncoder); impl ResponsePortEncoder { /// Makes a new `ResponsePortEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(ResponsePortEncoder, ResponsePort, |_item: Self::Item| 0u16); stun_codec-0.3.4/src/rfc5780/mod.rs000064400000000000000000000005041046102023000147670ustar 00000000000000//! [RFC 5780(NAT Behavior Discovery)][RFC 5780] specific components. //! //! [RFC 5780]: https://tools.ietf.org/html/rfc5780 use self::attributes::*; pub mod attributes; define_attribute_enums!( Attribute, AttributeDecoder, AttributeEncoder, [ChangeRequest, ResponseOrigin, ResponsePort, OtherAddress] ); stun_codec-0.3.4/src/rfc8016/attributes.rs000064400000000000000000000074131046102023000163770ustar 00000000000000//! Attributes that are defined in [RFC 8016]. //! //! [RFC 8016]: https://tools.ietf.org/html/rfc8016 use bytecodec::bytes::{BytesEncoder, RemainingBytesDecoder}; use bytecodec::{ByteCount, Decode, Encode, Eos, Result, SizedEncode, TryTaggedDecode}; use crate::attribute::{Attribute, AttributeType}; macro_rules! impl_decode { ($decoder:ty, $item:ident, $and_then:expr) => { impl Decode for $decoder { type Item = $item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.0.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { track!(self.0.finish_decoding()).and_then($and_then) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl TryTaggedDecode for $decoder { type Tag = AttributeType; fn try_start_decoding(&mut self, attr_type: Self::Tag) -> Result { Ok(attr_type.as_u16() == $item::CODEPOINT) } } }; } macro_rules! impl_encode { ($encoder:ty, $item:ty, $map_from:expr) => { impl Encode for $encoder { type Item = $item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } #[allow(clippy::redundant_closure_call)] fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.0.start_encoding($map_from(item).into())) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl SizedEncode for $encoder { fn exact_requiring_bytes(&self) -> u64 { self.0.exact_requiring_bytes() } } }; } /// `MOBILITY-TICKET` attribute. /// /// See [Mobility with TURN RFC] about this attribute. /// /// [Mobility with TURN RFC]: https://www.rfc-editor.org/rfc/rfc8016.html #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MobilityTicket(Vec); impl MobilityTicket { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x8030; /// Makes a new, filled `MobilityTicket` instance. /// /// Fails on exceeding length. pub fn new(data: Vec) -> Result { //track_assert!(data.len() <= 0xFFFF, ErrorKind::InvalidInput); Ok(MobilityTicket(data)) } /// Makes a new, empty `MobilityTicket` for requesting mobility during creating allocation. pub fn empty() -> Self { MobilityTicket(Vec::new()) } /// Returns a reference the data held by the attribute. pub fn data(&self) -> &[u8] { &self.0 } } impl Attribute for MobilityTicket { type Decoder = MobilityTicketDecoder; type Encoder = MobilityTicketEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`Data`] decoder. #[derive(Debug, Default)] pub struct MobilityTicketDecoder(RemainingBytesDecoder); impl MobilityTicketDecoder { /// Makes a new `DataDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!(MobilityTicketDecoder, MobilityTicket, |item| Ok( MobilityTicket(item) )); /// [`Data`] encoder. #[derive(Debug, Default)] pub struct MobilityTicketEncoder(BytesEncoder); impl MobilityTicketEncoder { /// Makes a new `DataEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!(MobilityTicketEncoder, MobilityTicket, |item: Self::Item| { item.0 }); stun_codec-0.3.4/src/rfc8016/errors.rs000064400000000000000000000014401046102023000155170ustar 00000000000000//! Error codes that are defined in RFC 8016. use crate::rfc5389::attributes::ErrorCode; /// `405`: "Mobility Forbidden". /// /// > 405 (Mobility Forbidden): Mobility request was valid but cannot be performed due to administrative or similar restrictions. /// > /// > [RFC 8016 -- 3.4] /// /// [RFC 8016 -- 3.4]: https://www.rfc-editor.org/rfc/rfc8016.html#section-3.4 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MobilityForbidden; impl MobilityForbidden { /// The codepoint of the error. pub const CODEPOINT: u16 = 405; } impl From for ErrorCode { fn from(_: MobilityForbidden) -> Self { ErrorCode::new( MobilityForbidden::CODEPOINT, "Mobility Forbidden".to_owned(), ) .expect("never fails") } } stun_codec-0.3.4/src/rfc8016/mod.rs000064400000000000000000000003031046102023000147570ustar 00000000000000//! [RFC 8016(Mobility with Traversal Using Relays around NAT (TURN))][RFC 8016] specific components. //! //! [RFC 8016]: https://tools.ietf.org/html/rfc8016 pub mod attributes; pub mod errors; stun_codec-0.3.4/src/rfc8656/attributes.rs000064400000000000000000000202671046102023000164130ustar 00000000000000//! Attributes that are defined in [RFC 8656]. //! //! [RFC 8656]: https://tools.ietf.org/html/rfc8656 use bytecodec::fixnum::{U32beDecoder, U32beEncoder}; use bytecodec::{ByteCount, Decode, Encode, Eos, Result, SizedEncode, TryTaggedDecode}; use std::fmt; use crate::attribute::{Attribute, AttributeType}; macro_rules! impl_decode { ($decoder:ty, $item:ident, $and_then:expr) => { impl Decode for $decoder { type Item = $item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.0.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { track!(self.0.finish_decoding()).and_then($and_then) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl TryTaggedDecode for $decoder { type Tag = AttributeType; fn try_start_decoding(&mut self, attr_type: Self::Tag) -> Result { Ok(attr_type.as_u16() == $item::CODEPOINT) } } }; } macro_rules! impl_encode { ($encoder:ty, $item:ty, $map_from:expr) => { impl Encode for $encoder { type Item = $item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } #[allow(clippy::redundant_closure_call)] fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.0.start_encoding($map_from(item).into())) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl SizedEncode for $encoder { fn exact_requiring_bytes(&self) -> u64 { self.0.exact_requiring_bytes() } } }; } /// The family of an IP address, either IPv4 or IPv6. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum AddressFamily { /// Version 4 of IP V4, /// Version 6 of IP V6, } impl fmt::Display for AddressFamily { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { AddressFamily::V4 => write!(f, "IPv4"), AddressFamily::V6 => write!(f, "IPv6"), } } } const FAMILY_IPV4: u8 = 1; const FAMILY_IPV6: u8 = 2; /// This attribute is used in Allocate and Refresh requests to specify the address type requested by the client. /// /// See for details. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RequestedAddressFamily(AddressFamily); impl RequestedAddressFamily { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x0017; /// Makes a new `RequestedAddressFamily` instance. pub fn new(fam: AddressFamily) -> Self { RequestedAddressFamily(fam) } /// Returns the requested address family. pub fn address_family(&self) -> AddressFamily { self.0 } } impl Attribute for RequestedAddressFamily { type Decoder = RequestedAddressFamilyDecoder; type Encoder = RequestedAddressFamilyEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`RequestedAddressFamily`] decoder. #[derive(Debug, Default)] pub struct RequestedAddressFamilyDecoder(AddressFamilyDecoder); impl RequestedAddressFamilyDecoder { /// Makes a new `RequestedAddressFamilyDecoder` instance. pub fn new() -> Self { Self::default() } } impl_decode!( RequestedAddressFamilyDecoder, RequestedAddressFamily, |item| Ok(RequestedAddressFamily(item)) ); /// [`RequestedAddressFamily`] encoder. #[derive(Debug, Default)] pub struct RequestedAddressFamilyEncoder(AddressFamilyEncoder); impl RequestedAddressFamilyEncoder { /// Makes a new `RequestedAddressFamilyEncoder` instance. pub fn new() -> Self { Self::default() } } impl_encode!( RequestedAddressFamilyEncoder, RequestedAddressFamily, |item: Self::Item| { item.0 } ); /// This attribute is used by clients to request the allocation of an IPv4 and IPv6 address type from a server. /// /// See for details. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AdditionalAddressFamily(AddressFamily); impl AdditionalAddressFamily { /// The codepoint of the type of the attribute. pub const CODEPOINT: u16 = 0x8000; /// Makes a new `AdditionalAddressFamily` instance. pub fn new(fam: AddressFamily) -> Self { AdditionalAddressFamily(fam) } /// Returns the requested address family. pub fn address_family(&self) -> AddressFamily { self.0 } } impl Attribute for AdditionalAddressFamily { type Decoder = AdditionalAddressFamilyDecoder; type Encoder = AdditionalAddressFamilyEncoder; fn get_type(&self) -> AttributeType { AttributeType::new(Self::CODEPOINT) } } /// [`AdditionalAddressFamily`] decoder. #[derive(Debug, Default)] pub struct AdditionalAddressFamilyDecoder(AddressFamilyDecoder); impl_decode!( AdditionalAddressFamilyDecoder, AdditionalAddressFamily, |item| Ok(AdditionalAddressFamily(item)) ); /// [`AdditionalAddressFamily`] encoder. #[derive(Debug, Default)] pub struct AdditionalAddressFamilyEncoder(AddressFamilyEncoder); impl_encode!( AdditionalAddressFamilyEncoder, AdditionalAddressFamily, |item: Self::Item| { item.0 } ); /// [`RequestedAddressFamily`] decoder. #[derive(Debug, Default)] pub struct AddressFamilyDecoder { family: U32beDecoder, } impl Decode for AddressFamilyDecoder { type Item = AddressFamily; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { self.family.decode(buf, eos) } fn finish_decoding(&mut self) -> Result { let [fam, _, _, _] = self.family.finish_decoding()?.to_be_bytes(); match fam { FAMILY_IPV4 => Ok(AddressFamily::V4), FAMILY_IPV6 => Ok(AddressFamily::V6), family => track_panic!( bytecodec::ErrorKind::InvalidInput, "Unknown address family: {}", family ), } } fn requiring_bytes(&self) -> ByteCount { self.family.requiring_bytes() } fn is_idle(&self) -> bool { self.family.is_idle() } } /// [`RequestedAddressFamily`] decoder. #[derive(Debug, Default)] pub struct AddressFamilyEncoder { family: U32beEncoder, } impl Encode for AddressFamilyEncoder { type Item = AddressFamily; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { self.family.encode(buf, eos) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { let fam_byte = match item { AddressFamily::V4 => FAMILY_IPV4, AddressFamily::V6 => FAMILY_IPV6, }; let bytes = [fam_byte, 0, 0, 0]; self.family.start_encoding(u32::from_be_bytes(bytes)) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(self.exact_requiring_bytes()) } } impl SizedEncode for AddressFamilyEncoder { fn exact_requiring_bytes(&self) -> u64 { self.family.exact_requiring_bytes() } } #[cfg(test)] mod tests { use super::*; use bytecodec::{DecodeExt, EncodeExt}; #[test] fn address_family_encoder_works() { let mut encoder = AddressFamilyEncoder::default(); let bytes = encoder.encode_into_bytes(AddressFamily::V4).unwrap(); assert_eq!(bytes, [1, 0, 0, 0]); let bytes = encoder.encode_into_bytes(AddressFamily::V6).unwrap(); assert_eq!(bytes, [2, 0, 0, 0]); } #[test] fn address_family_decoder_works() { let mut decoder = AddressFamilyDecoder::default(); let fam = decoder.decode_from_bytes(&[1, 0, 0, 0]).unwrap(); assert_eq!(fam, AddressFamily::V4); let fam = decoder.decode_from_bytes(&[2, 0, 0, 0]).unwrap(); assert_eq!(fam, AddressFamily::V6); } } stun_codec-0.3.4/src/rfc8656/errors.rs000064400000000000000000000026171046102023000155400ustar 00000000000000//! Error codes that are defined in RFC 8656. use crate::rfc5389::attributes::ErrorCode; /// The server does not support the address family requested by the client. /// /// See for details. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct AddressFamilyNotSupported; impl AddressFamilyNotSupported { /// The codepoint of the error. pub const CODEPOINT: u16 = 440; } impl From for ErrorCode { fn from(_: AddressFamilyNotSupported) -> Self { ErrorCode::new( AddressFamilyNotSupported::CODEPOINT, "Address Family not Supported".to_string(), ) .expect("never fails") } } /// A peer address is part of a different address family than that of the relayed transport address of the allocation. /// /// See for details. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct PeerAddressFamilyMismatch; impl PeerAddressFamilyMismatch { /// The codepoint of the error. pub const CODEPOINT: u16 = 443; } impl From for ErrorCode { fn from(_: PeerAddressFamilyMismatch) -> Self { ErrorCode::new( PeerAddressFamilyMismatch::CODEPOINT, "Peer Address Family Mismatch".to_owned(), ) .expect("never fails") } } stun_codec-0.3.4/src/rfc8656/mod.rs000064400000000000000000000003651046102023000150010ustar 00000000000000//! [RFC 8656(Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN))][RFC 8656] specific components. //! //! [RFC 8656]: https://tools.ietf.org/html/rfc8656 pub mod attributes; pub mod errors; stun_codec-0.3.4/src/transaction_id.rs000064400000000000000000000031111046102023000161100ustar 00000000000000use std::fmt; /// Transaction ID. /// /// > STUN is a client-server protocol. It supports two types of /// > transactions. One is a request/response transaction in which a /// > client sends a request to a server, and the server returns a /// > response. The second is an indication transaction in which either /// > agent -- client or server -- sends an indication that generates no /// > response. Both types of transactions include a **transaction ID**, which /// > is a randomly selected 96-bit number. For request/response /// > transactions, this transaction ID allows the client to associate the /// > response with the request that generated it; for indications, the /// > transaction ID serves as a debugging aid. /// > /// > [RFC 5389 -- 3. Overview of Operation] /// /// [RFC 5389 -- 3. Overview of Operation]: https://tools.ietf.org/html/rfc5389#section-3 #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct TransactionId([u8; 12]); impl TransactionId { /// Makes a new `TransactionId` instance. pub fn new(id: [u8; 12]) -> Self { TransactionId(id) } /// Returns a reference to the bytes that represents the identifier. pub fn as_bytes(&self) -> &[u8; 12] { &self.0 } } impl fmt::Debug for TransactionId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "TransactionId(0x")?; for b in self.as_ref() { write!(f, "{:02X}", b)?; } write!(f, ")")?; Ok(()) } } impl AsRef<[u8]> for TransactionId { fn as_ref(&self) -> &[u8] { &self.0[..] } } stun_codec-0.3.4/src/types.rs000064400000000000000000000011771046102023000142650ustar 00000000000000//! Miscellaneous types. /// Unsigned 12 bit integer. #[derive(Debug, Default, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] pub struct U12(u16); impl U12 { /// Converts from `u8` value. pub fn from_u8(value: u8) -> Self { U12(value as u16) } /// Tries to convert from `u16` value. /// /// If `value` is greater than `0xFFF`, this will return `None`. pub fn from_u16(value: u16) -> Option { if value < 0x1000 { Some(U12(value)) } else { None } } /// Converts to `u16` value. pub fn as_u16(&self) -> u16 { self.0 } }