coap_message.c
Go to the documentation of this file.
1 /**
2  * @file coap_message.c
3  * @brief CoAP message formatting and parsing
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL COAP_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/net.h"
34 #include "coap/coap_client.h"
35 //#include "coap/coap_server.h"
36 #include "coap/coap_message.h"
37 #include "debug.h"
38 
39 //Check TCP/IP stack configuration
40 #if (COAP_CLIENT_SUPPORT == ENABLED || COAP_SERVER_SUPPORT == ENABLED)
41 
42 
43 /**
44  * @brief Parse CoAP message
45  * @param[in] message Pointer to the CoAP message
46  * @return Error code
47  **/
48 
50 {
51  error_t error;
52  size_t n;
53  size_t length;
54  const uint8_t *p;
55 
56  //Point to the first byte of the CoAP message
57  p = message->buffer;
58  //Retrieve the length of the message
59  length = message->length;
60 
61  //Parse message header
62  error = coapParseMessageHeader(p, length, &n);
63  //Any error to report?
64  if(error)
65  return error;
66 
67  //Point to the first option of the message
68  p += n;
69  //Number of bytes left to process
70  length -= n;
71 
72  //Parse the list of options
73  error = coapParseOptions(p, length, &n);
74  //Any error to report?
75  if(error)
76  return error;
77 
78  //Point to the payload
79  p += n;
80  //Number of bytes left to process
81  length -= n;
82 
83  //The payload is optional
84  if(length > 0)
85  {
86  //The payload is prefixed by a fixed, one-byte payload marker
87  p++;
88  //Retrieve the length of the payload
89  length--;
90 
91  //The presence of a marker followed by a zero-length payload must be
92  //processed as a message format error
93  if(length == 0)
94  return ERROR_INVALID_MESSAGE;
95  }
96 
97  //Successful processing
98  return NO_ERROR;
99 }
100 
101 
102 /**
103  * @brief Parse CoAP message header
104  * @param[in] p Input stream where to read the CoAP message header
105  * @param[in] length Number of bytes available in the input stream
106  * @param[out] consumed Total number of bytes that have been consumed
107  * @return Error code
108  **/
109 
110 error_t coapParseMessageHeader(const uint8_t *p, size_t length,
111  size_t *consumed)
112 {
113  CoapMessageHeader *header;
114 
115  //Malformed CoAP message?
116  if(length < sizeof(CoapMessageHeader))
117  return ERROR_INVALID_MESSAGE;
118 
119  //Point to the CoAP message header
120  header = (CoapMessageHeader *) p;
121 
122  //Check version field
123  if(header->version != COAP_VERSION_1)
124  return ERROR_INVALID_VERSION;
125 
126  //The length of the Token field must 0-8 bytes
127  if(header->tokenLen > COAP_MAX_TOKEN_LEN)
128  return ERROR_INVALID_MESSAGE;
129 
130  //Malformed CoAP message?
131  if(length < (sizeof(CoapMessageHeader) + header->tokenLen))
132  return ERROR_INVALID_MESSAGE;
133 
134  //Total number of bytes that have been consumed
135  *consumed = sizeof(CoapMessageHeader) + header->tokenLen;
136 
137  //Successful processing
138  return NO_ERROR;
139 }
140 
141 
142 /**
143  * @brief Set message type
144  * @param[in] message Pointer to the CoAP message
145  * @param[in] type Message type (Confirmable or Non-confirmable)
146  * @return Error code
147  **/
148 
150 {
151  CoapMessageHeader *header;
152 
153  //Malformed CoAP message?
154  if(message->length < sizeof(CoapMessageHeader))
155  return ERROR_INVALID_MESSAGE;
156 
157  //Point to the CoAP message header
158  header = (CoapMessageHeader *) message->buffer;
159  //Set message type
160  header->type = type;
161 
162  //Successful processing
163  return NO_ERROR;
164 }
165 
166 
167 /**
168  * @brief Get message type
169  * @param[in] message Pointer to the CoAP message
170  * @param[out] type Message type
171  * @return Error code
172  **/
173 
175 {
176  CoapMessageHeader *header;
177 
178  //Malformed CoAP message?
179  if(message->length < sizeof(CoapMessageHeader))
180  return ERROR_INVALID_MESSAGE;
181 
182  //Point to the CoAP message header
183  header = (CoapMessageHeader *) message->buffer;
184  //Retrieve message type
185  *type = (CoapMessageType) header->type;
186 
187  //Successful processing
188  return NO_ERROR;
189 }
190 
191 
192 /**
193  * @brief Set method or response code
194  * @param[in] message Pointer to the CoAP message
195  * @param[in] code Method or response code
196  * @return Error code
197  **/
198 
200 {
201  CoapMessageHeader *header;
202 
203  //Malformed CoAP message?
204  if(message->length < sizeof(CoapMessageHeader))
205  return ERROR_INVALID_MESSAGE;
206 
207  //Point to the CoAP message header
208  header = (CoapMessageHeader *) message->buffer;
209  //Set method or response code
210  header->code = code;
211 
212  //Successful processing
213  return NO_ERROR;
214 }
215 
216 
217 /**
218  * @brief Get method or response code
219  * @param[in] message Pointer to the CoAP message
220  * @param[out] code Method or response code
221  * @return Error code
222  **/
223 
225 {
226  CoapMessageHeader *header;
227 
228  //Malformed CoAP message?
229  if(message->length < sizeof(CoapMessageHeader))
230  return ERROR_INVALID_MESSAGE;
231 
232  //Point to the CoAP message header
233  header = (CoapMessageHeader *) message->buffer;
234  //Retrieve method or response code
235  *code = (CoapCode) header->code;
236 
237  //Successful processing
238  return NO_ERROR;
239 }
240 
241 
242 /**
243  * @brief Set CoAP message payload
244  * @param[in] message Pointer to the CoAP message
245  * @param[out] payload Pointer to payload data
246  * @param[out] payloadLen Length of the payload, in bytes
247  * @return Error code
248  **/
249 
251  size_t payloadLen)
252 {
253  error_t error;
254  size_t n;
255  size_t length;
256  uint8_t *p;
257 
258  //Point to the first byte of the CoAP message
259  p = message->buffer;
260  //Retrieve the length of the message
261  length = message->length;
262 
263  //Parse message header
264  error = coapParseMessageHeader(p, length, &n);
265  //Any error to report?
266  if(error)
267  return error;
268 
269  //Point to the first option of the message
270  p += n;
271  //Number of bytes left to process
272  length -= n;
273 
274  //Parse the list of options
275  error = coapParseOptions(p, length, &n);
276  //Any error to report?
277  if(error)
278  return error;
279 
280  //Point to the payload
281  p += n;
282  //Number of bytes left to process
283  length -= n;
284 
285  //Trim the existing payload
286  message->length -= length;
287 
288  //The payload is optional
289  if(payloadLen > 0)
290  {
291  //Make sure the output buffer is large enough to hold the payload
292  if((message->length + payloadLen + 1) > COAP_MAX_MSG_SIZE)
293  return ERROR_BUFFER_OVERFLOW;
294 
295  //The payload is prefixed by a fixed, one-byte payload marker
296  p[0] = COAP_PAYLOAD_MARKER;
297 
298  //The payload data extends from after the marker to the end of the
299  //UDP datagram
300  memcpy(p + 1, payload, payloadLen);
301 
302  //Terminate the payload with a NULL character
303  p[payloadLen + 1] = '\0';
304 
305  //Adjust the length of the CoAP message
306  message->length += payloadLen + 1;
307  }
308 
309  //Successful processing
310  return NO_ERROR;
311 }
312 
313 
314 /**
315  * @brief Get CoAP message payload
316  * @param[in] message Pointer to the CoAP message
317  * @param[out] payload Pointer to the first byte of the payload
318  * @param[out] payloadLen Length of the payload, in bytes
319  * @return Error code
320  **/
321 
322 error_t coapGetPayload(const CoapMessage *message, const uint8_t **payload,
323  size_t *payloadLen)
324 {
325  error_t error;
326  size_t n;
327  size_t length;
328  const uint8_t *p;
329 
330  //Point to the first byte of the CoAP message
331  p = message->buffer;
332  //Retrieve the length of the message
333  length = message->length;
334 
335  //Parse message header
336  error = coapParseMessageHeader(p, length, &n);
337  //Any error to report?
338  if(error)
339  return error;
340 
341  //Point to the first option of the message
342  p += n;
343  //Number of bytes left to process
344  length -= n;
345 
346  //Parse the list of options
347  error = coapParseOptions(p, length, &n);
348  //Any error to report?
349  if(error)
350  return error;
351 
352  //Point to the payload
353  p += n;
354  //Number of bytes left to process
355  length -= n;
356 
357  //The payload is optional
358  if(length > 0)
359  {
360  //The payload is prefixed by a fixed, one-byte payload marker
361  p++;
362  //Retrieve the length of the payload
363  length--;
364  }
365 
366  //Point to the first byte of the payload, if any
367  *payload = p;
368  //Save the length of the payload
369  *payloadLen = length;
370 
371  //Successful processing
372  return NO_ERROR;
373 }
374 
375 
376 /**
377  * @brief Write payload data
378  * @param[in] message Pointer to the CoAP message
379  * @param[in] data Pointer to a buffer containing the data to be written
380  * @param[in] length Number of bytes to written
381  * @return Error code
382  **/
383 
385  size_t length)
386 {
387  error_t error;
388  size_t k;
389  size_t n;
390  uint8_t *p;
391 
392  //Point to the first byte of the CoAP message
393  p = message->buffer;
394  //Retrieve the length of the message
395  n = message->length;
396 
397  //Parse message header
398  error = coapParseMessageHeader(p, n, &k);
399  //Any error to report?
400  if(error)
401  return error;
402 
403  //Point to the first option of the message
404  p += k;
405  //Number of bytes left to process
406  n -= k;
407 
408  //Parse the list of options
409  error = coapParseOptions(p, n, &k);
410  //Any error to report?
411  if(error)
412  return error;
413 
414  //Point to the payload
415  p += k;
416  //Number of bytes left to process
417  n -= k;
418 
419  //Any data to write?
420  if(length > 0)
421  {
422  //The absence of the payload marker denotes a zero-length payload
423  if(n == 0)
424  {
425  //Make sure the output buffer is large enough to hold the payload
426  if((message->length + length + 1) > COAP_MAX_MSG_SIZE)
427  return ERROR_BUFFER_OVERFLOW;
428 
429  //The payload is prefixed by a fixed, one-byte payload marker
430  p[n++] = COAP_PAYLOAD_MARKER;
431 
432  //Adjust the length of the CoAP message
433  message->length++;
434  }
435  else
436  {
437  //Make sure the output buffer is large enough to hold the payload
438  if((message->length + length) > COAP_MAX_MSG_SIZE)
439  return ERROR_BUFFER_OVERFLOW;
440  }
441 
442  //Copy data
443  memcpy(p + n, data, length);
444 
445  //Terminate the payload with a NULL character
446  p[n + length] = '\0';
447 
448  //Adjust the length of the CoAP message
449  message->length += length;
450  }
451 
452  //Successful processing
453  return NO_ERROR;
454 }
455 
456 
457 /**
458  * @brief Read payload data
459  * @param[in] message Pointer to the CoAP message
460  * @param[out] data Buffer into which received data will be placed
461  * @param[in] size Maximum number of bytes that can be received
462  * @param[out] length Number of bytes that have been received
463  * @return Error code
464  **/
465 
467  size_t *length)
468 {
469  error_t error;
470  size_t k;
471  size_t n;
472  const uint8_t *p;
473 
474  //Point to the first byte of the CoAP message
475  p = message->buffer;
476  //Retrieve the length of the message
477  n = message->length;
478 
479  //Parse message header
480  error = coapParseMessageHeader(p, n, &k);
481  //Any error to report?
482  if(error)
483  return error;
484 
485  //Point to the first option of the message
486  p += k;
487  //Number of bytes left to process
488  n -= k;
489 
490  //Parse the list of options
491  error = coapParseOptions(p, n, &k);
492  //Any error to report?
493  if(error)
494  return error;
495 
496  //Point to the payload
497  p += k;
498  //Number of bytes left to process
499  n -= k;
500 
501  //The payload is optional
502  if(n > 0)
503  {
504  //The payload is prefixed by a fixed, one-byte payload marker
505  p++;
506  //Retrieve the length of the payload
507  n--;
508  }
509 
510  //Any data to be copied?
511  if(message->pos < n)
512  {
513  //Limit the number of bytes to copy at a time
514  n = MIN(n - message->pos, size);
515 
516  //Copy data
517  memcpy(data, p + message->pos, n);
518 
519  //Advance current position
520  message->pos += n;
521  //Total number of data that have been read
522  *length = n;
523 
524  //Successful processing
525  error = NO_ERROR;
526  }
527  else
528  {
529  //No more data available
530  error = ERROR_END_OF_STREAM;
531  }
532 
533  //Return status code
534  return error;
535 }
536 
537 
538 /**
539  * @brief Token comparison
540  * @param[in] header1 Pointer to the first CoAP message header
541  * @param[in] header2 Pointer to the second CoAP message header
542  * @return TRUE if the tokens match, else FALSE
543  **/
544 
546  const CoapMessageHeader *header2)
547 {
548  bool_t res = FALSE;
549 
550  //Check token lengths
551  if(header1->tokenLen == header2->tokenLen)
552  {
553  //Compare tokens
554  if(!memcmp(header1->token, header2->token, header1->tokenLen))
555  {
556  //The tokens match
557  res = TRUE;
558  }
559  }
560 
561  //Return comparison result
562  return res;
563 }
564 
565 #endif
uint8_t payloadLen
Definition: ipv6.h:341
CoapMessageType
CoAP message types.
Definition: coap_common.h:90
error_t coapSetCode(CoapMessage *message, CoapCode code)
Set method or response code.
Definition: coap_message.c:199
error_t coapParseMessageHeader(const uint8_t *p, size_t length, size_t *consumed)
Parse CoAP message header.
Definition: coap_message.c:110
error_t coapReadPayload(CoapMessage *message, void *data, size_t size, size_t *length)
Read payload data.
Definition: coap_message.c:466
#define COAP_MAX_TOKEN_LEN
Definition: coap_common.h:48
TCP/IP stack core.
Debugging facilities.
uint8_t res[]
error_t coapSetPayload(CoapMessage *message, const void *payload, size_t payloadLen)
Set CoAP message payload.
Definition: coap_message.c:250
uint8_t p
Definition: ndp.h:295
CoAP message.
Definition: coap_message.h:53
uint8_t message[]
Definition: chap.h:150
char_t type
CoapCode
CoAP method and response codes.
Definition: coap_common.h:115
error_t coapGetType(const CoapMessage *message, CoapMessageType *type)
Get message type.
Definition: coap_message.c:174
#define TRUE
Definition: os_port.h:48
CoAP version 1.
Definition: coap_common.h:72
bool_t coapCompareToken(const CoapMessageHeader *header1, const CoapMessageHeader *header2)
Token comparison.
Definition: coap_message.c:545
error_t coapParseOptions(const uint8_t *p, size_t length, size_t *consumed)
Parse the list of CoAP options.
Definition: coap_option.c:79
#define COAP_MAX_MSG_SIZE
Definition: coap_common.h:37
#define COAP_PAYLOAD_MARKER
Definition: coap_common.h:51
#define MIN(a, b)
Definition: os_port.h:60
CoAP message formatting and parsing.
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
uint8_t code
Definition: coap_common.h:179
uint8_t data[]
Definition: dtls_misc.h:167
CoAP client.
error_t coapGetCode(const CoapMessage *message, CoapCode *code)
Get method or response code.
Definition: coap_message.c:224
error_t coapWritePayload(CoapMessage *message, const void *data, size_t length)
Write payload data.
Definition: coap_message.c:384
error_t coapGetPayload(const CoapMessage *message, const uint8_t **payload, size_t *payloadLen)
Get CoAP message payload.
Definition: coap_message.c:322
error_t coapClientParseMessage(const CoapMessage *message)
Parse CoAP message.
Definition: coap_message.c:49
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
__start_packed struct @110 CoapMessageHeader
CoAP message format.
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
error_t coapSetType(CoapMessage *message, CoapMessageType type)
Set message type.
Definition: coap_message.c:149