Skip to main content

rtc_stun/
message.rs

1//! The STUN message: header, attributes, and encoding.
2//!
3//! A [`Message`](crate::message::Message) is a class and method ([`MessageType`](crate::message::MessageType)), a 96-bit [`TransactionId`](crate::message::TransactionId), and a
4//! list of attributes. Build one by applying [`Setter`](crate::message::Setter)s, read one back with [`Getter`](crate::message::Getter)s, and
5//! move it across the wire with `marshal`/`unmarshal`.
6//!
7//! Two attributes are special, because their value covers the *encoded* message: `FINGERPRINT`
8//! and `MESSAGE-INTEGRITY` must be appended last and are validated through [`Checker`](crate::message::Checker). That is
9//! why [`Message::raw`](crate::message::Message::raw) is kept alongside the parsed attributes — those checks are computed over
10//! it rather than over a re-encoding.
11
12#[cfg(test)]
13mod message_test;
14
15use crate::attributes::*;
16use shared::error::*;
17
18use base64::prelude::*;
19use rand::RngExt;
20use std::fmt;
21use std::io::{Read, Write};
22
23/// Fixed value that aids in distinguishing STUN packets
24/// from packets of other protocols when STUN is multiplexed with those
25/// other protocols on the same Port.
26///
27/// The magic cookie field MUST contain the fixed value 0x2112A442 in
28/// network byte order.
29///
30/// Defined in "STUN Message Structure", section 6.
31pub const MAGIC_COOKIE: u32 = 0x2112A442;
32/// Bytes of type and length preceding each attribute value.
33pub const ATTRIBUTE_HEADER_SIZE: usize = 4;
34/// Bytes in the STUN message header.
35pub const MESSAGE_HEADER_SIZE: usize = 20;
36
37/// Length of transaction id array (in bytes).
38/// 96 bit.
39pub const TRANSACTION_ID_SIZE: usize = 12;
40
41#[derive(PartialEq, Eq, Hash, Copy, Clone, Default, Debug)]
42/// A 96-bit transaction id, which pairs a response with its request.
43pub struct TransactionId(pub [u8; TRANSACTION_ID_SIZE]);
44
45impl TransactionId {
46    /// Creates a random transaction ID with `rand`'s cryptographically secure thread RNG.
47    ///
48    /// Transaction IDs remain independent of [`crypto::RTCCryptoProvider`] because ordinary STUN
49    /// message construction does not otherwise own a provider.
50    pub fn new() -> Self {
51        let mut b = TransactionId([0u8; TRANSACTION_ID_SIZE]);
52        rand::rng().fill(&mut b.0);
53        b
54    }
55}
56
57impl Setter for TransactionId {
58    fn add_to(&self, m: &mut Message) -> Result<()> {
59        m.transaction_id = *self;
60        m.write_transaction_id();
61        Ok(())
62    }
63}
64
65/// Interfaces that are implemented by message attributes, shorthands for them,
66/// or helpers for message fields as type or transaction id.
67pub trait Setter {
68    // Setter sets *Message attribute.
69    /// Encodes this value into `m` as an attribute.
70    ///
71    /// # Errors
72    ///
73    /// Fails if the value cannot be encoded, or the message has no room for it.
74    fn add_to(&self, m: &mut Message) -> Result<()>;
75}
76
77/// Getter parses attribute from *Message.
78pub trait Getter {
79    /// Decodes this value from the corresponding attribute of `m`.
80    ///
81    /// # Errors
82    ///
83    /// Fails if the attribute is absent or malformed.
84    fn get_from(&mut self, m: &Message) -> Result<()>;
85}
86
87/// Checker checks *Message attribute.
88pub trait Checker {
89    /// Validates this value against `m`.
90    ///
91    /// Used by attributes whose value depends on the encoded message, such as
92    /// `MESSAGE-INTEGRITY` and `FINGERPRINT`.
93    ///
94    /// # Errors
95    ///
96    /// Fails if the check does not hold.
97    fn check(&self, m: &Message) -> Result<()>;
98}
99
100/// Is_stun_message returns true if b looks like STUN message.
101/// Useful for multiplexing. is_stun_message does not guarantee
102/// that decoding will be successful.
103pub fn is_stun_message(b: &[u8]) -> bool {
104    b.len() >= MESSAGE_HEADER_SIZE && u32::from_be_bytes([b[4], b[5], b[6], b[7]]) == MAGIC_COOKIE
105}
106// Message represents a single STUN packet. It uses aggressive internal
107// buffering to enable zero-allocation encoding and decoding,
108// so there are some usage constraints:
109//
110// 	Message, its fields, results of m.Get or any attribute a.GetFrom
111//	are valid only until Message.Raw is not modified.
112#[derive(Default, Debug, Clone)]
113/// A STUN message: type, transaction id, and attributes, plus the encoded bytes.
114pub struct Message {
115    /// The message class and method — request, response or indication, and which method.
116    pub typ: MessageType,
117    /// The attribute section's length in bytes, header excluded.
118    pub length: u32, // len(Raw) not including header
119    /// The transaction id, echoed by the responder.
120    pub transaction_id: TransactionId,
121    /// The message's attributes.
122    pub attributes: Attributes,
123    /// The encoded message. Attributes whose value covers the message are computed over this.
124    pub raw: Vec<u8>,
125}
126
127impl fmt::Display for Message {
128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129        let t_id = BASE64_STANDARD.encode(self.transaction_id.0);
130        write!(
131            f,
132            "{} l={} attrs={} id={}",
133            self.typ,
134            self.length,
135            self.attributes.0.len(),
136            t_id
137        )
138    }
139}
140
141// Equal returns true if Message b equals to m.
142// Ignores m.Raw.
143impl PartialEq for Message {
144    fn eq(&self, other: &Self) -> bool {
145        if self.typ != other.typ {
146            return false;
147        }
148        if self.transaction_id != other.transaction_id {
149            return false;
150        }
151        if self.length != other.length {
152            return false;
153        }
154        if self.attributes != other.attributes {
155            return false;
156        }
157        true
158    }
159}
160
161const DEFAULT_RAW_CAPACITY: usize = 120;
162
163impl Setter for Message {
164    // add_to sets b.TransactionID to m.TransactionID.
165    //
166    // Implements Setter to aid in crafting responses.
167    fn add_to(&self, b: &mut Message) -> Result<()> {
168        b.transaction_id = self.transaction_id;
169        b.write_transaction_id();
170        Ok(())
171    }
172}
173
174impl Message {
175    /// New returns *Message with pre-allocated Raw.
176    pub fn new() -> Self {
177        Message {
178            raw: {
179                let mut raw = Vec::with_capacity(DEFAULT_RAW_CAPACITY);
180                raw.extend_from_slice(&[0; MESSAGE_HEADER_SIZE]);
181                raw
182            },
183            ..Default::default()
184        }
185    }
186
187    /// Marshal_binary implements the encoding.BinaryMarshaler interface.
188    pub fn marshal_binary(&self) -> Result<Vec<u8>> {
189        // We can't return m.Raw, allocation is expected by implicit interface
190        // contract induced by other implementations.
191        Ok(self.raw.clone())
192    }
193
194    /// Unmarshal_binary implements the encoding.BinaryUnmarshaler interface.
195    pub fn unmarshal_binary(&mut self, data: &[u8]) -> Result<()> {
196        // We can't retain data, copy is expected by interface contract.
197        self.raw.clear();
198        self.raw.extend_from_slice(data);
199        self.decode()
200    }
201
202    /// Replaces the transaction ID using `rand`'s cryptographically secure thread RNG.
203    ///
204    /// Transaction IDs remain independent of [`crypto::RTCCryptoProvider`] because a general
205    /// [`Message`] does not otherwise own a provider.
206    pub fn new_transaction_id(&mut self) -> Result<()> {
207        rand::rng().fill(&mut self.transaction_id.0);
208        self.write_transaction_id();
209        Ok(())
210    }
211
212    /// Reset resets Message, attributes and underlying buffer length.
213    pub fn reset(&mut self) {
214        self.raw.clear();
215        self.length = 0;
216        self.attributes.0.clear();
217    }
218
219    // grow ensures that internal buffer has n length.
220    fn grow(&mut self, n: usize, resize: bool) {
221        if self.raw.len() >= n {
222            if resize {
223                self.raw.resize(n, 0);
224            }
225            return;
226        }
227        self.raw.extend_from_slice(&vec![0; n - self.raw.len()]);
228    }
229
230    /// Add appends new attribute to message. Not goroutine-safe.
231    ///
232    /// Value of attribute is copied to internal buffer so
233    /// it is safe to reuse v.
234    pub fn add(&mut self, t: AttrType, v: &[u8]) {
235        // Allocating buffer for TLV (type-length-value).
236        // T = t, L = len(v), V = v.
237        // m.Raw will look like:
238        // [0:20]                               <- message header
239        // [20:20+m.Length]                     <- existing message attributes
240        // [20+m.Length:20+m.Length+len(v) + 4] <- allocated buffer for new TLV
241        // [first:last]                         <- same as previous
242        // [0 1|2 3|4    4 + len(v)]            <- mapping for allocated buffer
243        //   T   L        V
244        let alloc_size = ATTRIBUTE_HEADER_SIZE + v.len(); // ~ len(TLV) = len(TL) + len(V)
245        let first = MESSAGE_HEADER_SIZE + self.length as usize; // first byte number
246        let mut last = first + alloc_size; // last byte number
247        self.grow(last, true); // growing cap(Raw) to fit TLV
248        self.length += alloc_size as u32; // rendering length change
249
250        // Encoding attribute TLV to allocated buffer.
251        let buf = &mut self.raw[first..last];
252        buf[0..2].copy_from_slice(&t.value().to_be_bytes()); // T
253        buf[2..4].copy_from_slice(&(v.len() as u16).to_be_bytes()); // L
254
255        let value = &mut buf[ATTRIBUTE_HEADER_SIZE..];
256        value.copy_from_slice(v); // V
257
258        let attr = RawAttribute {
259            typ: t,                 // T
260            length: v.len() as u16, // L
261            value: value.to_vec(),  // V
262        };
263
264        // Checking that attribute value needs padding.
265        if !(attr.length as usize).is_multiple_of(PADDING) {
266            // Performing padding.
267            let bytes_to_add = nearest_padded_value_length(v.len()) - v.len();
268            last += bytes_to_add;
269            self.grow(last, true);
270            // setting all padding bytes to zero
271            // to prevent data leak from previous
272            // data in next bytes_to_add bytes
273            let buf = &mut self.raw[last - bytes_to_add..last];
274            for b in buf {
275                *b = 0;
276            }
277            self.length += bytes_to_add as u32; // rendering length change
278        }
279        self.attributes.0.push(attr);
280        self.write_length();
281    }
282
283    /// WriteLength writes m.Length to m.Raw.
284    pub fn write_length(&mut self) {
285        self.grow(4, false);
286        self.raw[2..4].copy_from_slice(&(self.length as u16).to_be_bytes());
287    }
288
289    /// WriteHeader writes header to underlying buffer. Not goroutine-safe.
290    pub fn write_header(&mut self) {
291        self.grow(MESSAGE_HEADER_SIZE, false);
292
293        self.write_type();
294        self.write_length();
295        self.raw[4..8].copy_from_slice(&MAGIC_COOKIE.to_be_bytes()); // magic cookie
296        self.raw[8..MESSAGE_HEADER_SIZE].copy_from_slice(&self.transaction_id.0);
297        // transaction ID
298    }
299
300    /// WriteTransactionID writes m.TransactionID to m.Raw.
301    pub fn write_transaction_id(&mut self) {
302        self.raw[8..MESSAGE_HEADER_SIZE].copy_from_slice(&self.transaction_id.0);
303        // transaction ID
304    }
305
306    /// WriteAttributes encodes all m.Attributes to m.
307    pub fn write_attributes(&mut self) {
308        let attributes: Vec<RawAttribute> = self.attributes.0.drain(..).collect();
309        for a in &attributes {
310            self.add(a.typ, &a.value);
311        }
312        self.attributes = Attributes(attributes);
313    }
314
315    /// WriteType writes m.Type to m.Raw.
316    pub fn write_type(&mut self) {
317        self.grow(2, false);
318        self.raw[..2].copy_from_slice(&self.typ.value().to_be_bytes()); // message type
319    }
320
321    /// SetType sets m.Type and writes it to m.Raw.
322    pub fn set_type(&mut self, t: MessageType) {
323        self.typ = t;
324        self.write_type();
325    }
326
327    /// Encode re-encodes message into m.Raw.
328    pub fn encode(&mut self) {
329        self.raw.clear();
330        self.write_header();
331        self.length = 0;
332        self.write_attributes();
333    }
334
335    /// Decode decodes m.Raw into m.
336    pub fn decode(&mut self) -> Result<()> {
337        // decoding message header
338        let buf = &self.raw;
339        if buf.len() < MESSAGE_HEADER_SIZE {
340            return Err(Error::ErrUnexpectedHeaderEof);
341        }
342
343        let t = u16::from_be_bytes([buf[0], buf[1]]); // first 2 bytes
344        let size = u16::from_be_bytes([buf[2], buf[3]]) as usize; // second 2 bytes
345        let cookie = u32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]); // last 4 bytes
346        let full_size = MESSAGE_HEADER_SIZE + size; // len(m.Raw)
347
348        if cookie != MAGIC_COOKIE {
349            return Err(Error::Other(format!(
350                "{cookie:x} is invalid magic cookie (should be {MAGIC_COOKIE:x})"
351            )));
352        }
353        if buf.len() < full_size {
354            return Err(Error::Other(format!(
355                "buffer length {} is less than {} (expected message size)",
356                buf.len(),
357                full_size
358            )));
359        }
360
361        // saving header data
362        self.typ.read_value(t);
363        self.length = size as u32;
364        self.transaction_id
365            .0
366            .copy_from_slice(&buf[8..MESSAGE_HEADER_SIZE]);
367
368        self.attributes.0.clear();
369        let mut offset = 0;
370        let mut b = &buf[MESSAGE_HEADER_SIZE..full_size];
371
372        while offset < size {
373            // checking that we have enough bytes to read header
374            if b.len() < ATTRIBUTE_HEADER_SIZE {
375                return Err(Error::Other(format!(
376                    "buffer length {} is less than {} (expected header size)",
377                    b.len(),
378                    ATTRIBUTE_HEADER_SIZE
379                )));
380            }
381
382            let mut a = RawAttribute {
383                typ: compat_attr_type(u16::from_be_bytes([b[0], b[1]])), // first 2 bytes
384                length: u16::from_be_bytes([b[2], b[3]]),                // second 2 bytes
385                ..Default::default()
386            };
387            let a_l = a.length as usize; // attribute length
388            let a_buff_l = nearest_padded_value_length(a_l); // expected buffer length (with padding)
389
390            b = &b[ATTRIBUTE_HEADER_SIZE..]; // slicing again to simplify value read
391            offset += ATTRIBUTE_HEADER_SIZE;
392            if b.len() < a_buff_l {
393                // checking size
394                return Err(Error::Other(format!(
395                    "buffer length {} is less than {} (expected value size for {})",
396                    b.len(),
397                    a_buff_l,
398                    a.typ
399                )));
400            }
401            a.value = b[..a_l].to_vec();
402            offset += a_buff_l;
403            b = &b[a_buff_l..];
404
405            self.attributes.0.push(a);
406        }
407
408        Ok(())
409    }
410
411    /// WriteTo implements WriterTo via calling Write(m.Raw) on w and returning
412    /// call result.
413    pub fn write_to<W: Write>(&self, writer: &mut W) -> Result<usize> {
414        let n = writer.write(&self.raw)?;
415        Ok(n)
416    }
417
418    /// ReadFrom implements ReaderFrom. Reads message from r into m.Raw,
419    /// Decodes it and return error if any. If m.Raw is too small, will return
420    /// ErrUnexpectedEOF, ErrUnexpectedHeaderEOF or *DecodeErr.
421    ///
422    /// Can return *DecodeErr while decoding too.
423    pub fn read_from<R: Read>(&mut self, reader: &mut R) -> Result<usize> {
424        let mut t_buf = vec![0; DEFAULT_RAW_CAPACITY];
425        let n = reader.read(&mut t_buf)?;
426        self.raw = t_buf[..n].to_vec();
427        self.decode()?;
428        Ok(n)
429    }
430
431    /// Write decodes message and return error if any.
432    ///
433    /// Any error is unrecoverable, but message could be partially decoded.
434    pub fn write(&mut self, t_buf: &[u8]) -> Result<usize> {
435        self.raw.clear();
436        self.raw.extend_from_slice(t_buf);
437        self.decode()?;
438        Ok(t_buf.len())
439    }
440
441    /// CloneTo clones m to b securing any further m mutations.
442    pub fn clone_to(&self, b: &mut Message) -> Result<()> {
443        b.raw.clear();
444        b.raw.extend_from_slice(&self.raw);
445        b.decode()
446    }
447
448    /// Contains return true if message contain t attribute.
449    pub fn contains(&self, t: AttrType) -> bool {
450        for a in &self.attributes.0 {
451            if a.typ == t {
452                return true;
453            }
454        }
455        false
456    }
457
458    /// Get returns byte slice that represents attribute value,
459    /// if there is no attribute with such type,
460    /// ErrAttributeNotFound is returned.
461    pub fn get(&self, t: AttrType) -> Result<Vec<u8>> {
462        let (v, ok) = self.attributes.get(t);
463        if ok {
464            Ok(v.value)
465        } else {
466            Err(Error::ErrAttributeNotFound)
467        }
468    }
469
470    /// Resets the message and applies `setters` to it in order, returning on the first
471    /// error.
472    ///
473    /// Each setter writes its attribute into the message as it is applied, so the encoded
474    /// [`raw`](Self::raw) bytes are complete once this returns. Order matters for setters
475    /// that cover the attributes before them — a
476    /// [`MessageIntegrity`](crate::integrity::MessageIntegrity) or
477    /// [`FINGERPRINT`](crate::fingerprint::FINGERPRINT) therefore goes last.
478    ///
479    /// ```
480    /// use rtc_stun::attributes::ATTR_SOFTWARE;
481    /// use rtc_stun::message::{BINDING_REQUEST, Message, TransactionId};
482    /// use rtc_stun::textattrs::TextAttribute;
483    ///
484    /// # fn example() -> Result<(), Box<dyn std::error::Error>> {
485    /// let mut m = Message::new();
486    /// m.build(&[
487    ///     Box::new(BINDING_REQUEST),
488    ///     Box::new(TransactionId::new()),
489    ///     Box::new(TextAttribute::new(ATTR_SOFTWARE, "webrtc-rs".to_owned())),
490    /// ])?;
491    ///
492    /// assert!(!m.raw.is_empty());
493    /// # Ok(())
494    /// # }
495    /// ```
496    pub fn build(&mut self, setters: &[Box<dyn Setter + '_>]) -> Result<()> {
497        self.reset();
498        self.write_header();
499        for s in setters {
500            s.add_to(self)?;
501        }
502        Ok(())
503    }
504
505    /// Check applies checkers to message in batch, returning on first error.
506    pub fn check<C: Checker>(&self, checkers: &[C]) -> Result<()> {
507        for c in checkers {
508            c.check(self)?;
509        }
510        Ok(())
511    }
512
513    /// Parse applies getters to message in batch, returning on first error.
514    pub fn parse<G: Getter>(&self, getters: &mut [G]) -> Result<()> {
515        for c in getters {
516            c.get_from(self)?;
517        }
518        Ok(())
519    }
520}
521
522// MessageClass is 8-bit representation of 2-bit class of STUN Message Class.
523#[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
524/// A STUN message class: request, indication, success response or error response.
525pub struct MessageClass(u8);
526
527/// Possible values for message class in STUN Message Type.
528/// 0b00.
529pub const CLASS_REQUEST: MessageClass = MessageClass(0x00);
530/// 0b01.
531pub const CLASS_INDICATION: MessageClass = MessageClass(0x01);
532/// 0b10.
533pub const CLASS_SUCCESS_RESPONSE: MessageClass = MessageClass(0x02);
534/// 0b11.
535pub const CLASS_ERROR_RESPONSE: MessageClass = MessageClass(0x03);
536
537impl fmt::Display for MessageClass {
538    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539        let s = match *self {
540            CLASS_REQUEST => "request",
541            CLASS_INDICATION => "indication",
542            CLASS_SUCCESS_RESPONSE => "success response",
543            CLASS_ERROR_RESPONSE => "error response",
544            _ => "unknown message class",
545        };
546
547        write!(f, "{s}")
548    }
549}
550
551// Method is uint16 representation of 12-bit STUN method.
552#[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
553/// A STUN method, such as Binding or one of TURN's.
554pub struct Method(u16);
555
556/// Possible methods for STUN Message.
557pub const METHOD_BINDING: Method = Method(0x001);
558/// TURN Allocate: asks a relay for a public address.
559pub const METHOD_ALLOCATE: Method = Method(0x003);
560/// TURN Refresh: extends or releases an allocation.
561pub const METHOD_REFRESH: Method = Method(0x004);
562/// TURN Send: an indication carrying data to a peer through the relay.
563pub const METHOD_SEND: Method = Method(0x006);
564/// TURN Data: an indication carrying data from a peer through the relay.
565pub const METHOD_DATA: Method = Method(0x007);
566/// TURN CreatePermission: authorizes traffic to and from a peer address.
567pub const METHOD_CREATE_PERMISSION: Method = Method(0x008);
568/// TURN ChannelBind: binds a channel number to a peer for compact framing.
569pub const METHOD_CHANNEL_BIND: Method = Method(0x009);
570
571/// Methods from RFC 6062.
572pub const METHOD_CONNECT: Method = Method(0x000a);
573/// TURN-TCP ConnectionBind: associates a new TCP connection with an allocation.
574pub const METHOD_CONNECTION_BIND: Method = Method(0x000b);
575/// TURN-TCP ConnectionAttempt: notifies the client of an inbound TCP connection.
576pub const METHOD_CONNECTION_ATTEMPT: Method = Method(0x000c);
577
578impl fmt::Display for Method {
579    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
580        let unknown = format!("0x{:x}", self.0);
581
582        let s = match *self {
583            METHOD_BINDING => "Binding",
584            METHOD_ALLOCATE => "Allocate",
585            METHOD_REFRESH => "Refresh",
586            METHOD_SEND => "Send",
587            METHOD_DATA => "Data",
588            METHOD_CREATE_PERMISSION => "CreatePermission",
589            METHOD_CHANNEL_BIND => "ChannelBind",
590
591            // RFC 6062.
592            METHOD_CONNECT => "Connect",
593            METHOD_CONNECTION_BIND => "ConnectionBind",
594            METHOD_CONNECTION_ATTEMPT => "ConnectionAttempt",
595            _ => unknown.as_str(),
596        };
597
598        write!(f, "{s}")
599    }
600}
601
602// MessageType is STUN Message Type Field.
603#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
604/// A message's class and method together, as encoded in the first two header bytes.
605pub struct MessageType {
606    /// The method, such as Binding or Allocate.
607    pub method: Method, // e.g. binding
608    /// The class: request, indication, success response, or error response.
609    pub class: MessageClass, // e.g. request
610}
611
612/// Common STUN message types.
613/// Binding request message type.
614pub const BINDING_REQUEST: MessageType = MessageType {
615    method: METHOD_BINDING,
616    class: CLASS_REQUEST,
617};
618/// Binding success response message type.
619pub const BINDING_SUCCESS: MessageType = MessageType {
620    method: METHOD_BINDING,
621    class: CLASS_SUCCESS_RESPONSE,
622};
623/// Binding error response message type.
624pub const BINDING_ERROR: MessageType = MessageType {
625    method: METHOD_BINDING,
626    class: CLASS_ERROR_RESPONSE,
627};
628
629impl fmt::Display for MessageType {
630    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
631        write!(f, "{} {}", self.method, self.class)
632    }
633}
634
635const METHOD_ABITS: u16 = 0xf; // 0b0000000000001111
636const METHOD_BBITS: u16 = 0x70; // 0b0000000001110000
637const METHOD_DBITS: u16 = 0xf80; // 0b0000111110000000
638
639const METHOD_BSHIFT: u16 = 1;
640const METHOD_DSHIFT: u16 = 2;
641
642const FIRST_BIT: u16 = 0x1;
643const SECOND_BIT: u16 = 0x2;
644
645const C0BIT: u16 = FIRST_BIT;
646const C1BIT: u16 = SECOND_BIT;
647
648const CLASS_C0SHIFT: u16 = 4;
649const CLASS_C1SHIFT: u16 = 7;
650
651impl Setter for MessageType {
652    // add_to sets m type to t.
653    fn add_to(&self, m: &mut Message) -> Result<()> {
654        m.set_type(*self);
655        Ok(())
656    }
657}
658
659impl MessageType {
660    /// NewType returns new message type with provided method and class.
661    pub fn new(method: Method, class: MessageClass) -> Self {
662        MessageType { method, class }
663    }
664
665    /// Value returns bit representation of messageType.
666    pub fn value(&self) -> u16 {
667        //	 0                 1
668        //	 2  3  4 5 6 7 8 9 0 1 2 3 4 5
669        //	+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
670        //	|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
671        //	|11|10|9|8|7|1|6|5|4|0|3|2|1|0|
672        //	+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
673        // Figure 3: Format of STUN Message Type Field
674
675        // Warning: Abandon all hope ye who enter here.
676        // Splitting M into A(M0-M3), B(M4-M6), D(M7-M11).
677        let method = self.method.0;
678        let a = method & METHOD_ABITS; // A = M * 0b0000000000001111 (right 4 bits)
679        let b = method & METHOD_BBITS; // B = M * 0b0000000001110000 (3 bits after A)
680        let d = method & METHOD_DBITS; // D = M * 0b0000111110000000 (5 bits after B)
681
682        // Shifting to add "holes" for C0 (at 4 bit) and C1 (8 bit).
683        let method = a + (b << METHOD_BSHIFT) + (d << METHOD_DSHIFT);
684
685        // C0 is zero bit of C, C1 is first bit.
686        // C0 = C * 0b01, C1 = (C * 0b10) >> 1
687        // Ct = C0 << 4 + C1 << 8.
688        // Optimizations: "((C * 0b10) >> 1) << 8" as "(C * 0b10) << 7"
689        // We need C0 shifted by 4, and C1 by 8 to fit "11" and "7" positions
690        // (see figure 3).
691        let c = self.class.0 as u16;
692        let c0 = (c & C0BIT) << CLASS_C0SHIFT;
693        let c1 = (c & C1BIT) << CLASS_C1SHIFT;
694        let class = c0 + c1;
695
696        method + class
697    }
698
699    /// ReadValue decodes uint16 into MessageType.
700    pub fn read_value(&mut self, value: u16) {
701        // Decoding class.
702        // We are taking first bit from v >> 4 and second from v >> 7.
703        let c0 = (value >> CLASS_C0SHIFT) & C0BIT;
704        let c1 = (value >> CLASS_C1SHIFT) & C1BIT;
705        let class = c0 + c1;
706        self.class = MessageClass(class as u8);
707
708        // Decoding method.
709        let a = value & METHOD_ABITS; // A(M0-M3)
710        let b = (value >> METHOD_BSHIFT) & METHOD_BBITS; // B(M4-M6)
711        let d = (value >> METHOD_DSHIFT) & METHOD_DBITS; // D(M7-M11)
712        let m = a + b + d;
713        self.method = Method(m);
714    }
715}