async_coap/message/
std_parser.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16use super::*;
17use std::borrow::Borrow;
18
19/// A class for parsing a stand-alone UDP CoAP message from a given buffer.
20#[derive(Debug)]
21pub struct StandardMessageParser<'buf> {
22    buffer: &'buf [u8],
23    msg_code: MsgCode,
24    msg_type: MsgType,
25    msg_id: u16,
26    token: MsgToken,
27    content_format: Option<ContentFormat>,
28    accept: Option<ContentFormat>,
29    block2: Option<BlockInfo>,
30    block1: Option<BlockInfo>,
31    option_start: usize,
32    payload_start: usize,
33}
34
35impl<'buf> std::fmt::Display for StandardMessageParser<'buf> {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        MessageDisplay(self).fmt(f)
38    }
39}
40
41impl<'buf> StandardMessageParser<'buf> {
42    /// The minimum buffer size that can be passed into `new()`.
43    pub const MIN_MESSAGE_BUFFER_LEN: usize = 4;
44
45    /// Creates a new `StandardMessageParser` instance with the given `buffer`.
46    pub fn new(buffer: &'buf [u8]) -> Result<StandardMessageParser<'buf>, Error> {
47        if buffer.len() < StandardMessageParser::MIN_MESSAGE_BUFFER_LEN {
48            return Err(Error::ParseFailure);
49        }
50
51        let msg_code = MsgCode::try_from(buffer[1]).ok_or(Error::UnknownMessageCode)?;
52
53        let msg_type = MsgType::from((buffer[0] & COAP_MSG_T_MASK) >> COAP_MSG_T_OFFS);
54        let msg_id = buffer[3] as u16 | ((buffer[2] as u16) << 8);
55        let token_len = (buffer[0] & COAP_MSG_TKL_MASK) as usize;
56        if token_len > 8 {
57            return Err(Error::ParseFailure);
58        }
59        let token = MsgToken::new(&buffer[4..4 + token_len]);
60
61        let mut content_format = None;
62        let mut accept = None;
63        let mut block2 = None;
64        let mut block1 = None;
65
66        let mut iter = OptionIterator::new(&buffer[4 + token_len..]);
67
68        for result in &mut iter {
69            match result {
70                Ok((OptionNumber::CONTENT_FORMAT, value)) => {
71                    content_format = Some(ContentFormat(
72                        try_decode_u16(value).ok_or(Error::ParseFailure)?,
73                    ));
74                }
75                Ok((OptionNumber::ACCEPT, value)) => match try_decode_u16(value) {
76                    Some(x) => accept = Some(ContentFormat(x)),
77                    None => return Err(Error::ParseFailure),
78                },
79                Ok((OptionNumber::BLOCK2, value)) => match try_decode_u32(value) {
80                    Some(x) => block2 = Some(BlockInfo(x).valid().ok_or(Error::ParseFailure)?),
81                    None => return Err(Error::ParseFailure),
82                },
83                Ok((OptionNumber::BLOCK1, value)) => match try_decode_u32(value) {
84                    Some(x) => block1 = Some(BlockInfo(x).valid().ok_or(Error::ParseFailure)?),
85                    None => return Err(Error::ParseFailure),
86                },
87                Ok((_key, _value)) => {
88                    // Skip.
89                }
90                Err(e) => {
91                    return Err(e);
92                }
93            }
94        }
95
96        let payload_start = iter.as_slice().as_ptr() as usize - buffer.as_ptr() as usize;
97
98        let ret = StandardMessageParser {
99            buffer,
100            msg_code,
101            msg_type,
102            msg_id,
103            token,
104            content_format,
105            accept,
106            block2,
107            block1,
108            option_start: 4 + token_len,
109            payload_start,
110        };
111
112        Ok(ret)
113    }
114
115    /// Returns a byte slice containing the encoded message.
116    pub fn as_bytes(&self) -> &'buf [u8] {
117        self.buffer
118    }
119}
120
121impl<'buf> MessageRead for StandardMessageParser<'buf> {
122    fn msg_code(&self) -> MsgCode {
123        self.msg_code
124    }
125
126    fn msg_type(&self) -> MsgType {
127        self.msg_type
128    }
129
130    fn msg_id(&self) -> u16 {
131        self.msg_id
132    }
133
134    fn msg_token(&self) -> MsgToken {
135        self.token
136    }
137
138    fn payload(&self) -> &[u8] {
139        &self.buffer[self.payload_start..]
140    }
141
142    fn content_format(&self) -> Option<ContentFormat> {
143        self.content_format
144    }
145
146    fn accept(&self) -> Option<ContentFormat> {
147        self.accept
148    }
149
150    fn block2(&self) -> Option<BlockInfo> {
151        self.block2
152    }
153
154    fn block1(&self) -> Option<BlockInfo> {
155        self.block1
156    }
157
158    fn options(&self) -> OptionIterator<'_> {
159        OptionIterator::new(&self.buffer[4 + self.token.len()..])
160    }
161}
162
163/// A class representing an immutable heap-allocated UDP CoAP message.
164#[derive(Debug, Clone, Eq, PartialEq)]
165pub struct OwnedImmutableMessage {
166    buffer: Vec<u8>,
167    msg_code: MsgCode,
168    msg_type: MsgType,
169    msg_id: u16,
170    token: MsgToken,
171    content_format: Option<ContentFormat>,
172    accept: Option<ContentFormat>,
173    block2: Option<BlockInfo>,
174    block1: Option<BlockInfo>,
175    option_start: usize,
176    payload_start: usize,
177}
178
179impl std::fmt::Display for OwnedImmutableMessage {
180    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181        MessageDisplay(self).fmt(f)
182    }
183}
184
185impl<'a> Borrow<dyn MessageRead + 'a> for OwnedImmutableMessage {
186    fn borrow(&self) -> &(dyn MessageRead + 'a) {
187        self
188    }
189}
190
191impl OwnedImmutableMessage {
192    /// The minimum size of a buffer that can be passed into `new()`.
193    pub const MIN_MESSAGE_BUFFER_LEN: usize = 4;
194
195    /// Creates a new `OwnedImmutableMessage` instance with the given `buffer`.
196    pub fn new(buffer: Vec<u8>) -> Result<OwnedImmutableMessage, Error> {
197        let msg_code = MsgCode::try_from(buffer[1]).ok_or(Error::UnknownMessageCode)?;
198
199        let msg_type = MsgType::from((buffer[0] & COAP_MSG_T_MASK) >> COAP_MSG_T_OFFS);
200        let msg_id = buffer[3] as u16 | ((buffer[2] as u16) << 8);
201        let token_len = (buffer[0] & COAP_MSG_TKL_MASK) as usize;
202        if token_len > 8 {
203            return Err(Error::ParseFailure);
204        }
205        let token = MsgToken::new(&buffer[4..4 + token_len]);
206
207        let mut content_format = None;
208        let mut accept = None;
209        let mut block2 = None;
210        let mut block1 = None;
211
212        let mut iter = OptionIterator::new(&buffer[4 + token_len..]);
213
214        for result in &mut iter {
215            match result {
216                Ok((OptionNumber::CONTENT_FORMAT, value)) => {
217                    content_format = Some(ContentFormat(
218                        try_decode_u16(value).ok_or(Error::ParseFailure)?,
219                    ));
220                }
221                Ok((OptionNumber::ACCEPT, value)) => match try_decode_u16(value) {
222                    Some(x) => accept = Some(ContentFormat(x)),
223                    None => return Err(Error::ParseFailure),
224                },
225                Ok((OptionNumber::BLOCK2, value)) => match try_decode_u32(value) {
226                    Some(x) => block2 = Some(BlockInfo(x).valid().ok_or(Error::ParseFailure)?),
227                    None => return Err(Error::ParseFailure),
228                },
229                Ok((OptionNumber::BLOCK1, value)) => match try_decode_u32(value) {
230                    Some(x) => block1 = Some(BlockInfo(x).valid().ok_or(Error::ParseFailure)?),
231                    None => return Err(Error::ParseFailure),
232                },
233                Ok((_key, _value)) => {
234                    // Skip.
235                }
236                Err(e) => {
237                    return Err(e);
238                }
239            }
240        }
241
242        let payload_start = iter.as_slice().as_ptr() as usize - buffer.as_ptr() as usize;
243
244        let ret = OwnedImmutableMessage {
245            buffer,
246            msg_code,
247            msg_type,
248            msg_id,
249            token,
250            content_format,
251            accept,
252            block2,
253            block1,
254            option_start: 4 + token_len,
255            payload_start,
256        };
257
258        Ok(ret)
259    }
260
261    /// Returns a byte slice containing the encoded message.
262    pub fn as_bytes(&self) -> &[u8] {
263        &self.buffer
264    }
265}
266
267impl MessageRead for OwnedImmutableMessage {
268    fn msg_code(&self) -> MsgCode {
269        self.msg_code
270    }
271
272    fn msg_type(&self) -> MsgType {
273        self.msg_type
274    }
275
276    fn msg_id(&self) -> u16 {
277        self.msg_id
278    }
279
280    fn msg_token(&self) -> MsgToken {
281        self.token
282    }
283
284    fn payload(&self) -> &[u8] {
285        &self.buffer[self.payload_start..]
286    }
287
288    fn content_format(&self) -> Option<ContentFormat> {
289        self.content_format
290    }
291
292    fn accept(&self) -> Option<ContentFormat> {
293        self.accept
294    }
295
296    fn block2(&self) -> Option<BlockInfo> {
297        self.block2
298    }
299
300    fn block1(&self) -> Option<BlockInfo> {
301        self.block1
302    }
303
304    fn options(&self) -> OptionIterator<'_> {
305        OptionIterator::new(&self.buffer[4 + self.token.len()..])
306    }
307}