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