stun_coder/message/message.rs
1pub use super::errors::{IntegrityKeyGenerationError, MessageDecodeError, MessageEncodeError};
2
3use crate::attribute::StunAttribute;
4use crate::header::StunHeader;
5
6/// [STUN message](https://tools.ietf.org/html/rfc5389#section-6).
7///
8/// An example of creating and encoding a STUN binding request:
9///```
10/// // Create a request message
11/// let message = stun_coder::StunMessage::create_request()
12/// .add_attribute(stun_coder::StunAttribute::Software {
13/// description: String::from("rust-stun-coder"),
14/// })
15/// .add_message_integrity()
16/// .add_fingerprint();
17///
18/// // Encode it into bytes
19/// let encoded_message = message.encode(Some("TEST_PASS")).unwrap();
20///
21/// println!("{:#X?}", encoded_message);
22///
23///```
24///
25/// An example that decodes a sample request with Long-Term Authentication
26/// ```
27/// // Encoded message
28/// let msg_bytes: Vec<u8> = vec![
29/// 0x01, 0x01, 0x00, 0x48, 0x21, 0x12, 0xa4, 0x42, 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34,
30/// 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, 0x80, 0x22, 0x00, 0x0b, 0x74, 0x65, 0x73, 0x74,
31/// 0x20, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02,
32/// 0xa1, 0x47, 0x01, 0x13, 0xa9, 0xfa, 0xa5, 0xd3, 0xf1, 0x79, 0xbc, 0x25, 0xf4, 0xb5,
33/// 0xbe, 0xd2, 0xb9, 0xd9, 0x00, 0x08, 0x00, 0x14, 0xBD, 0x3, 0x6D, 0x6A, 0x33, 0x17,
34/// 0x50, 0xDF, 0xE2, 0xED, 0xC5, 0x8E, 0x64, 0x34, 0x55, 0xCF, 0xF5, 0xC8, 0xE2, 0x64,
35/// 0x80, 0x28, 0x00, 0x04, 0x4F, 0x26, 0x02, 0x93,
36/// ];
37///
38/// // Integrity key used for verification
39/// let integrity_key = Some("VOkJxbRl1RmTxUk/WvJxBt");
40///
41/// // Decode the message
42/// let decoded_msg = stun_coder::StunMessage::decode(&msg_bytes, integrity_key).unwrap();
43///
44/// println!("{:?}", decoded_msg);
45///```
46///
47///
48/// STUN messages are encoded in binary using network-oriented format
49/// (most significant byte or octet first, also commonly known as big-
50/// endian). The transmission order is described in detail in Appendix B
51/// of [RFC0791](https://tools.ietf.org/html/rfc791). Unless otherwise noted, numeric constants are
52/// in decimal (base 10).
53///
54/// All STUN messages MUST start with a 20-byte header followed by zero
55/// or more Attributes. The STUN header contains a STUN message type,
56/// magic cookie, transaction ID, and message length.
57///```text
58/// 0 1 2 3
59/// 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
60/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61/// |0 0| STUN Message Type | Message Length |
62/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63/// | Magic Cookie |
64/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65/// | |
66/// | Transaction ID (96 bits) |
67/// | |
68/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69///
70/// Figure 2: Format of STUN Message Header
71///```
72/// The most significant 2 bits of every STUN message MUST be zeroes.
73/// This can be used to differentiate STUN packets from other protocols
74/// when STUN is multiplexed with other protocols on the same port.
75///
76/// The message type defines the message class (request, success
77/// response, failure response, or indication) and the message method
78/// (the primary function) of the STUN message. Although there are four
79/// message classes, there are only two types of transactions in STUN:
80/// request/response transactions (which consist of a request message and
81/// a response message) and indication transactions (which consist of a
82/// single indication message). Response classes are split into error
83/// and success responses to aid in quickly processing the STUN message.
84///
85/// The message type field is decomposed further into the following
86/// structure:
87///```text
88/// 0 1
89/// 2 3 4 5 6 7 8 9 0 1 2 3 4 5
90///
91/// +--+--+-+-+-+-+-+-+-+-+-+-+-+-+
92/// |M |M |M|M|M|C|M|M|M|C|M|M|M|M|
93/// |11|10|9|8|7|1|6|5|4|0|3|2|1|0|
94/// +--+--+-+-+-+-+-+-+-+-+-+-+-+-+
95///
96/// Figure 3: Format of STUN Message Type Field
97///```
98/// Here the bits in the message type field are shown as most significant
99/// (M11) through least significant (M0). M11 through M0 represent a 12-
100/// bit encoding of the method. C1 and C0 represent a 2-bit encoding of
101/// the class. A class of 0b00 is a request, a class of 0b01 is an
102/// indication, a class of 0b10 is a success response, and a class of
103/// 0b11 is an error response. This specification defines a single
104/// method, Binding. The method and class are orthogonal, so that for
105/// each method, a request, success response, error response, and
106/// indication are possible for that method. Extensions defining new
107/// methods MUST indicate which classes are permitted for that method.
108///
109/// For example, a Binding request has class=0b00 (request) and
110/// method=0b000000000001 (Binding) and is encoded into the first 16 bits
111/// as 0x0001. A Binding response has class=0b10 (success response) and
112/// method=0b000000000001, and is encoded into the first 16 bits as
113/// 0x0101.
114///```text
115/// Note: This unfortunate encoding is due to assignment of values in
116/// [RFC3489](https://tools.ietf.org/html/rfc3489) that did not consider encoding Indications, Success, and
117/// Errors using bit fields.
118///```
119/// The magic cookie field MUST contain the fixed value 0x2112A442 in
120/// network byte order. In [RFC3489](https://tools.ietf.org/html/rfc3489), this field was part of
121/// the transaction ID; placing the magic cookie in this location allows
122/// a server to detect if the client will understand certain attributes
123/// that were added in this revised specification. In addition, it aids
124/// in distinguishing STUN packets from packets of other protocols when
125/// STUN is multiplexed with those other protocols on the same port.
126///
127/// The transaction ID is a 96-bit identifier, used to uniquely identify
128/// STUN transactions. For request/response transactions, the
129/// transaction ID is chosen by the STUN client for the request and
130/// echoed by the server in the response. For indications, it is chosen
131/// by the agent sending the indication. It primarily serves to
132/// correlate requests with responses, though it also plays a small role
133///
134/// in helping to prevent certain types of attacks. The server also uses
135/// the transaction ID as a key to identify each transaction uniquely
136/// across all clients. As such, the transaction ID MUST be uniformly
137/// and randomly chosen from the interval 0 .. 2**96-1, and SHOULD be
138/// cryptographically random. Resends of the same request reuse the same
139/// transaction ID, but the client MUST choose a new transaction ID for
140/// new transactions unless the new request is bit-wise identical to the
141/// previous request and sent from the same transport address to the same
142/// IP address. Success and error responses MUST carry the same
143/// transaction ID as their corresponding request. When an agent is
144/// acting as a STUN server and STUN client on the same port, the
145/// transaction IDs in requests sent by the agent have no relationship to
146/// the transaction IDs in requests received by the agent.
147///
148/// The message length MUST contain the size, in bytes, of the message
149/// not including the 20-byte STUN header. Since all STUN attributes are
150/// padded to a multiple of 4 bytes, the last 2 bits of this field are
151/// always zero. This provides another way to distinguish STUN packets
152/// from packets of other protocols.
153///
154/// Following the STUN fixed portion of the header are zero or more
155/// attributes. Each attribute is TLV (Type-Length-Value) encoded. The
156/// details of the encoding, and of the attributes themselves are given
157/// in [Section 15](https://tools.ietf.org/html/rfc5389#section-15).
158
159#[derive(Debug, Clone)]
160pub struct StunMessage {
161 /// STUN message header
162 pub(super) header: StunHeader,
163 /// STUN message attributes
164 pub(super) attributes: Vec<StunAttribute>,
165}