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