coap_option.c
Go to the documentation of this file.
1 /**
2  * @file coap_option.c
3  * @brief CoAP option 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_option.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 List of supported CoAP options
45  **/
46 
48 {
50  {COAP_OPT_URI_HOST, TRUE, TRUE, FALSE, FALSE, "Uri-Host", COAP_OPT_FORMAT_STRING, 1, 255},
52  {COAP_OPT_IF_NONE_MATCH, TRUE, FALSE, FALSE, FALSE, "If-None-Match", COAP_OPT_FORMAT_EMPTY, 0, 0},
54  {COAP_OPT_URI_PORT, TRUE, TRUE, FALSE, FALSE, "Uri-Port", COAP_OPT_FORMAT_UINT, 0, 2},
55  {COAP_OPT_LOCATION_PATH, FALSE, FALSE, FALSE, TRUE, "Location-Path", COAP_OPT_FORMAT_STRING, 0, 255},
56  {COAP_OPT_URI_PATH, TRUE, TRUE, FALSE, TRUE, "Uri-Path", COAP_OPT_FORMAT_STRING, 0, 255},
57  {COAP_OPT_CONTENT_FORMAT, FALSE, FALSE, FALSE, FALSE, "Content-Format", COAP_OPT_FORMAT_UINT, 0, 2},
59  {COAP_OPT_URI_QUERY, TRUE, TRUE, FALSE, TRUE, "Uri-Query", COAP_OPT_FORMAT_STRING, 0, 255},
61  {COAP_OPT_LOCATION_QUERY, FALSE, FALSE, FALSE, TRUE, "Location-Query", COAP_OPT_FORMAT_STRING, 0, 255},
65  {COAP_OPT_PROXY_URI, TRUE, TRUE, FALSE, FALSE, "Proxy-Uri", COAP_OPT_FORMAT_STRING, 1, 1034},
66  {COAP_OPT_PROXY_SCHEME, TRUE, TRUE, FALSE, FALSE, "Proxy-Scheme", COAP_OPT_FORMAT_STRING, 1, 255},
68 };
69 
70 
71 /**
72  * @brief Parse the list of CoAP options
73  * @param[in] p Input stream where to read the CoAP options
74  * @param[in] length Number of bytes available in the input stream
75  * @param[out] consumed Total number of bytes that have been consumed
76  * @return Error code
77  **/
78 
79 error_t coapParseOptions(const uint8_t *p, size_t length, size_t *consumed)
80 {
81  error_t error;
82  size_t n;
83  CoapOption option;
84 
85  //Initialize status code
86  error = NO_ERROR;
87 
88  //Total number of bytes that have been consumed
89  *consumed = 0;
90 
91  //For the first option in a message, a preceding option instance with
92  //Option Number zero is assumed
93  option.number = 0;
94 
95  //Loop through CoAP options
96  while(length > 0)
97  {
98  //Payload marker found?
99  if(*p == COAP_PAYLOAD_MARKER)
100  break;
101 
102  //Parse current option
103  error = coapParseOption(p, length, option.number, &option, &n);
104  //Any error to report?
105  if(error)
106  break;
107 
108  //Total number of bytes that have been consumed
109  *consumed += n;
110 
111  //Jump to the next option
112  p += n;
113  length -= n;
114  }
115 
116  //Return status code
117  return error;
118 }
119 
120 
121 /**
122  * @brief Parse CoAP option
123  * @param[in] p Input stream where to read the CoAP option
124  * @param[in] length Number of bytes available in the input stream
125  * @param[in] prevOptionNum Option number of the previous instance
126  * @param[out] option CoAP option content
127  * @param[out] consumed Total number of bytes that have been consumed
128  * @return Error code
129  **/
130 
131 error_t coapParseOption(const uint8_t *p, size_t length,
132  uint16_t prevOptionNum, CoapOption *option, size_t *consumed)
133 {
134  const CoapOptionHeader *header;
135 
136  //Malformed CoAP option?
137  if(length < sizeof(CoapOptionHeader))
138  return ERROR_BUFFER_UNDERFLOW;
139 
140  //Point to the CoAP option header
141  header = (CoapOptionHeader *) p;
142 
143  //Point to the next field
144  p += sizeof(CoapOptionHeader);
145  length -= sizeof(CoapOptionHeader);
146 
147  //Check the value of the Option Delta field
148  if(header->delta == COAP_OPT_DELTA_RESERVED)
149  {
150  //If the field is set to 15 but the entire byte is not the payload
151  //marker, this must be processed as a message format error
152  return ERROR_INVALID_MESSAGE;
153  }
154  else if(header->delta == COAP_OPT_DELTA_16_BITS)
155  {
156  //Malformed CoAP option?
157  if(length < sizeof(uint16_t))
158  return ERROR_BUFFER_UNDERFLOW;
159 
160  //A 16-bit unsigned integer in network byte order follows the initial
161  //byte and indicates the Option Delta minus 269
163 
164  //Point to the next field
165  p += sizeof(uint16_t);
166  length -= sizeof(uint16_t);
167  }
168  else if(header->delta == COAP_OPT_DELTA_8_BITS)
169  {
170  //Malformed CoAP option?
171  if(length < sizeof(uint8_t))
172  return ERROR_BUFFER_UNDERFLOW;
173 
174  //An 8-bit unsigned integer follows the initial byte and indicates
175  //the Option Delta minus 13
176  option->delta = *p + COAP_OPT_DELTA_MINUS_8_BITS;
177 
178  //Point to the next field
179  p += sizeof(uint8_t);
180  length -= sizeof(uint8_t);
181  }
182  else
183  {
184  //A value between 0 and 12 indicates the Option Delta
185  option->delta = header->delta;
186  }
187 
188  //Check the value of the Option Length field
189  if(header->length == COAP_OPT_LEN_RESERVED)
190  {
191  //If the field is set to this value, it must be processed as a
192  //message format error
193  return ERROR_INVALID_MESSAGE;
194  }
195  else if(header->length == COAP_OPT_LEN_16_BITS)
196  {
197  //Malformed CoAP option?
198  if(length < sizeof(uint16_t))
199  return ERROR_BUFFER_UNDERFLOW;
200 
201  //A 16-bit unsigned integer in network byte order precedes the
202  //Option Value and indicates the Option Length minus 269
204 
205  //Point to the next field
206  p += sizeof(uint16_t);
207  length -= sizeof(uint16_t);
208  }
209  else if(header->length == COAP_OPT_LEN_8_BITS)
210  {
211  //Malformed CoAP option?
212  if(length < sizeof(uint8_t))
213  return ERROR_BUFFER_UNDERFLOW;
214 
215  //An 8-bit unsigned integer precedes the Option Value and indicates
216  //the Option Length minus 13
217  option->length = *p + COAP_OPT_LEN_MINUS_8_BITS;
218 
219  //Point to the next field
220  p += sizeof(uint8_t);
221  length -= sizeof(uint8_t);
222  }
223  else
224  {
225  //A value between 0 and 12 indicates the length of the Option Value,
226  //in bytes
227  option->length = header->length;
228  }
229 
230  //Malformed CoAP option?
231  if(length < option->length)
232  return ERROR_BUFFER_UNDERFLOW;
233 
234  //Save option value
235  option->value = p;
236  //Advance data pointer
237  p += option->length;
238 
239  //the Option Number for each instance is calculated as the sum of its delta
240  //and the Option Number of the preceding instance in the message
241  option->number = option->delta + prevOptionNum;
242 
243  //Total number of bytes that have been consumed
244  *consumed = p - (uint8_t *) header;
245 
246  //Successful processing
247  return NO_ERROR;
248 }
249 
250 
251 /**
252  * @brief Format CoAP option
253  * @param[in] p Buffer where to format the CoAP option (optional parameter)
254  * @param[in] prevOptionNum Option number of the previous instance
255  * @param[in] option CoAP option content
256  * @param[out] written Total number of bytes that have been written
257  * @return Error code
258  **/
259 
260 error_t coapFormatOption(uint8_t *p, uint16_t prevOptionNum,
261  CoapOption *option, size_t *written)
262 {
263  size_t n;
264  CoapOptionHeader *header;
265 
266  //The Option Delta is the difference between the Option Number of this
267  //option and that of the previous option (or zero for the first option)
268  option->delta = option->number - prevOptionNum;
269 
270  //Point to the buffer where to write the CoAP option
271  header = (CoapOptionHeader *) p;
272  //Length of the CoAP option
273  n = sizeof(CoapOptionHeader);
274 
275  //Encode the Option Delta field
276  if(option->delta >= COAP_OPT_DELTA_MINUS_16_BITS)
277  {
278  //The first parameter is optional
279  if(p != NULL)
280  {
281  //Fix the initial byte of the CoAP option
282  header->delta = COAP_OPT_DELTA_16_BITS;
283 
284  //A 16-bit unsigned integer in network byte order follows the
285  //initial byte and indicates the Option Delta minus 269
287  }
288 
289  //Adjust the length of the CoAP option
290  n += sizeof(uint16_t);
291  }
292  else if(option->delta >= COAP_OPT_DELTA_MINUS_8_BITS)
293  {
294  //The first parameter is optional
295  if(p != NULL)
296  {
297  //Fix the initial byte of the CoAP option
298  header->delta = COAP_OPT_DELTA_8_BITS;
299 
300  //An 8-bit unsigned integer follows the initial byte and
301  //indicates the Option Delta minus 13
302  p[n] = (uint8_t) (option->delta - COAP_OPT_DELTA_MINUS_8_BITS);
303  }
304 
305  //Adjust the length of the CoAP option
306  n += sizeof(uint8_t);
307  }
308  else
309  {
310  //The first parameter is optional
311  if(p != NULL)
312  {
313  //The Option Delta is directly encoded in the initial byte
314  header->delta = (uint8_t) option->delta;
315  }
316  }
317 
318  //Encode the Option Length field
319  if(option->length >= COAP_OPT_LEN_MINUS_16_BITS)
320  {
321  //The first parameter is optional
322  if(p != NULL)
323  {
324  //Fix the initial byte of the CoAP option
325  header->length = COAP_OPT_LEN_16_BITS;
326 
327  //A 16-bit unsigned integer in network byte order precedes the
328  //Option Value and indicates the Option Length minus 269
330  }
331 
332  //Adjust the length of the CoAP option
333  n += sizeof(uint16_t);
334  }
335  else if(option->length >= COAP_OPT_LEN_MINUS_8_BITS)
336  {
337  //The first parameter is optional
338  if(p != NULL)
339  {
340  //Fix the initial byte of the CoAP option
341  header->length = COAP_OPT_LEN_8_BITS;
342 
343  //An 8-bit unsigned integer precedes the Option Value and
344  //indicates the Option Length minus 13
345  p[n] = (uint8_t) (option->length - COAP_OPT_LEN_MINUS_8_BITS);
346  }
347 
348  //Adjust the length of the CoAP option
349  n += sizeof(uint8_t);
350  }
351  else
352  {
353  //The first parameter is optional
354  if(p != NULL)
355  {
356  //The Option Length is directly encoded in the initial byte
357  header->length = (uint8_t) option->length;
358  }
359  }
360 
361  //The first parameter is optional
362  if(p != NULL)
363  {
364  //The Option Value is a sequence of exactly Option Length bytes
365  memmove(p + n, option->value, option->length);
366  }
367 
368  //Total number of bytes that have been written
369  *written = n + option->length;
370 
371  //Successful processing
372  return NO_ERROR;
373 }
374 
375 
376 /**
377  * @brief Add an option to the specified CoAP message
378  * @param[in] message Pointer to the CoAP message
379  * @param[in] optionNum Option number
380  * @param[in] optionIndex Occurrence index (for repeatable options only)
381  * @param[in] optionValue Pointer to the first byte of the option value
382  * @param[in] optionLen Length of the option, in bytes
383  * @return Error code
384  **/
385 
387  uint_t optionIndex, const uint8_t *optionValue, size_t optionLen)
388 {
389  error_t error;
390  bool_t replace;
391  size_t n;
392  size_t m;
393  size_t length;
394  uint_t index;
395  uint16_t prevOptionNum;
396  uint8_t *p;
397  CoapOption option;
398 
399  //Initialize variables
400  replace = FALSE;
401  index = 0;
402 
403  //Point to the first byte of the CoAP message
404  p = message->buffer;
405  //Retrieve the length of the message
406  length = message->length;
407 
408  //Parse message header
409  error = coapParseMessageHeader(p, length, &n);
410  //Any error to report?
411  if(error)
412  return error;
413 
414  //Point to the first option of the message
415  p += n;
416  //Number of bytes left to process
417  length -= n;
418 
419  //For the first option in a message, a preceding option instance with
420  //Option Number zero is assumed
421  prevOptionNum = 0;
422 
423  //Loop through CoAP options
424  while(length > 0)
425  {
426  //Payload marker found?
427  if(*p == COAP_PAYLOAD_MARKER)
428  break;
429 
430  //Parse current option
431  error = coapParseOption(p, length, prevOptionNum, &option, &n);
432  //Any error to report?
433  if(error)
434  return error;
435 
436  //Options are inserted in ascending order
437  if(option.number > optionNum)
438  break;
439 
440  //Matching option number?
441  if(option.number == optionNum)
442  {
443  //Matching occurrence found?
444  if(index++ == optionIndex)
445  {
446  //The current option will be replaced
447  replace = TRUE;
448  break;
449  }
450  }
451 
452  //Keep track of the current option number
453  prevOptionNum = option.number;
454 
455  //Jump to the next option
456  p += n;
457  length -= n;
458  }
459 
460  //Check whether the current option should be replaced
461  if(replace)
462  {
463  //Remove the current occurrence of the option
464  memmove(p, p + n, length - n);
465  //Number of bytes left to process
466  length -= n;
467  //Adjust the length of the CoAP message
468  message->length -= n;
469  }
470 
471  //Each option instance in a message specifies the Option Number of the
472  //defined CoAP option, the length of the Option Value, and the Option
473  //Value itself
474  option.number = optionNum;
475  option.length = optionLen;
476  option.value = optionValue;
477 
478  //The first pass calculates the required length
479  error = coapFormatOption(NULL, prevOptionNum, &option, &n);
480  //Any error to report?
481  if(error)
482  return error;
483 
484  //Make sure the output buffer is large enough to hold the new option
485  if((message->length + n) > COAP_MAX_MSG_SIZE)
486  return ERROR_BUFFER_OVERFLOW;
487 
488  //Make room for the new option
489  memmove(p + n, p, length);
490 
491  //The second pass formats the CoAP option
492  error = coapFormatOption(p, prevOptionNum, &option, &n);
493  //Any error to report?
494  if(error)
495  return error;
496 
497  //Advance data pointer
498  p += n;
499  //Adjust the length of the CoAP message
500  message->length += n;
501 
502  //Check whether another CoAP option is following
503  if(length > 0 && *p != COAP_PAYLOAD_MARKER && !replace)
504  {
505  //Parse the following option
506  error = coapParseOption(p, length, prevOptionNum, &option, &n);
507  //Any error to report?
508  if(error)
509  return error;
510 
511  //Fix the Option Delta field
512  error = coapFormatOption(p, optionNum, &option, &m);
513  //Any error to report?
514  if(error)
515  return error;
516 
517  //Test if the length of the option has changed
518  if(m < n)
519  {
520  //Move the rest of the CoAP message
521  memmove(p + m, p + n, length - n);
522  //Fix the length of the message
523  message->length -= n - m;
524  }
525  }
526 
527  //Return status code
528  return NO_ERROR;
529 }
530 
531 
532 /**
533  * @brief Add a uint option to the specified CoAP message
534  * @param[in] message Pointer to the CoAP message
535  * @param[in] optionNum Option number
536  * @param[in] optionIndex Occurrence index (for repeatable options only)
537  * @param[in] optionValue Option value (unsigned integer)
538  * @return Error code
539  **/
540 
542  uint_t optionIndex, uint32_t optionValue)
543 {
544  size_t i;
545  uint8_t buffer[4];
546 
547  //A sender should represent the integer with as few bytes as possible
548  for(i = 4; optionValue != 0; i--)
549  {
550  buffer[i - 1] = optionValue & 0xFF;
551  optionValue >>= 8;
552  }
553 
554  //Add the specified option to the CoAP message
555  return coapSetOption(message, optionNum, optionIndex, buffer + i, 4 - i);
556 }
557 
558 
559 /**
560  * @brief Get the value of the specified option
561  * @param[in] message Pointer to the CoAP message
562  * @param[in] optionNum Option number
563  * @param[in] optionIndex Occurrence index (for repeatable options only)
564  * @param[out] optionValue Pointer to the first byte of the option value
565  * @param[out] optionLen Length of the option, in bytes
566  * @return Error code
567  **/
568 
569 error_t coapGetOption(const CoapMessage *message, uint16_t optionNum,
570  uint_t optionIndex, const uint8_t **optionValue, size_t *optionLen)
571 {
572  error_t error;
573  size_t n;
574  size_t length;
575  uint_t index;
576  const uint8_t *p;
577  CoapOption option;
578 
579  //Initialize index
580  index = 0;
581 
582  //Point to the first byte of the CoAP message
583  p = message->buffer;
584  //Retrieve the length of the message
585  length = message->length;
586 
587  //Parse message header
588  error = coapParseMessageHeader(p, length, &n);
589  //Any error to report?
590  if(error)
591  return error;
592 
593  //Point to the first option of the message
594  p += n;
595  //Number of bytes left to process
596  length -= n;
597 
598  //For the first option in a message, a preceding option instance with
599  //Option Number zero is assumed
600  option.number = 0;
601 
602  //Loop through CoAP options
603  while(length > 0)
604  {
605  //Payload marker found?
606  if(*p == COAP_PAYLOAD_MARKER)
607  break;
608 
609  //Parse current option
610  error = coapParseOption(p, length, option.number, &option, &n);
611  //Any error to report?
612  if(error)
613  return error;
614 
615  //Matching option number?
616  if(option.number == optionNum)
617  {
618  //Matching occurrence found?
619  if(index++ == optionIndex)
620  {
621  //Return option value
622  *optionValue = option.value;
623  *optionLen = option.length;
624 
625  //We are done
626  return NO_ERROR;
627  }
628  }
629 
630  //Jump to the next option
631  p += n;
632  length -= n;
633  }
634 
635  //The specified option number does not exist
636  return ERROR_NOT_FOUND;
637 }
638 
639 
640 /**
641  * @brief Get the value of the specified uint option
642  * @param[in] message Pointer to the CoAP message
643  * @param[in] optionNum Option number to search for
644  * @param[in] optionIndex Occurrence index (for repeatable options only)
645  * @param[out] optionValue Option value (unsigned integer)
646  * @return Error code
647  **/
648 
649 error_t coapGetUintOption(const CoapMessage *message, uint16_t optionNum,
650  uint_t optionIndex, uint32_t *optionValue)
651 {
652  error_t error;
653  size_t i;
654  size_t n;
655  const uint8_t *p;
656 
657  //Search the CoAP message for the specified option number
658  error = coapGetOption(message, optionNum, optionIndex, &p, &n);
659  //Any error to report ?
660  if(error)
661  return error;
662 
663  //Initialize integer value
664  *optionValue = 0;
665 
666  //Convert the integer from network byte order
667  for(i = 0; i < n; i++)
668  {
669  *optionValue <<= 8;
670  *optionValue += p[i];
671  }
672 
673  //Successful processing
674  return NO_ERROR;
675 }
676 
677 
678 /**
679  * @brief Remove an option from the specified CoAP message
680  * @param[in] message Pointer to the CoAP message
681  * @param[in] optionNum Option number
682  * @param[in] optionIndex Occurrence index (for repeatable options only)
683  * @return Error code
684  **/
685 
687  uint_t optionIndex)
688 {
689  error_t error;
690  bool_t found;
691  size_t n;
692  size_t m;
693  size_t length;
694  uint_t index;
695  uint16_t prevOptionNum;
696  uint8_t *p;
697  CoapOption option;
698 
699  //Initialize variables
700  found = FALSE;
701  index = 0;
702 
703  //Point to the first byte of the CoAP message
704  p = message->buffer;
705  //Retrieve the length of the message
706  length = message->length;
707 
708  //Parse message header
709  error = coapParseMessageHeader(p, length, &n);
710  //Any error to report?
711  if(error)
712  return error;
713 
714  //Point to the first option of the message
715  p += n;
716  //Number of bytes left to process
717  length -= n;
718 
719  //For the first option in a message, a preceding option instance with
720  //Option Number zero is assumed
721  prevOptionNum = 0;
722 
723  //Loop through CoAP options
724  while(length > 0)
725  {
726  //Payload marker found?
727  if(*p == COAP_PAYLOAD_MARKER)
728  break;
729 
730  //Parse current option
731  error = coapParseOption(p, length, prevOptionNum, &option, &n);
732  //Any error to report?
733  if(error)
734  return error;
735 
736  //Options are inserted in ascending order
737  if(option.number > optionNum)
738  break;
739 
740  //Matching option number?
741  if(option.number == optionNum)
742  {
743  //Matching occurrence found?
744  if(index++ == optionIndex)
745  {
746  //The current option will be removed
747  found = TRUE;
748  break;
749  }
750  }
751 
752  //Keep track of the current option number
753  prevOptionNum = option.number;
754 
755  //Jump to the next option
756  p += n;
757  length -= n;
758  }
759 
760  //Check whether the option has been found
761  if(found)
762  {
763  //Remove the current occurrence of the option
764  memmove(p, p + n, length - n);
765  //Number of bytes left to process
766  length -= n;
767  //Adjust the length of the CoAP message
768  message->length -= n;
769 
770  //Check whether another CoAP option is following
771  if(length > 0 && *p != COAP_PAYLOAD_MARKER)
772  {
773  //Parse the following option
774  error = coapParseOption(p, length, optionNum, &option, &n);
775  //Any error to report?
776  if(error)
777  return error;
778 
779  //The first pass calculates the required length
780  error = coapFormatOption(NULL, prevOptionNum, &option, &m);
781  //Any error to report?
782  if(error)
783  return error;
784 
785  //Test if the length of the option has changed
786  if(m > n)
787  {
788  //Move the rest of the CoAP message
789  memmove(p + m - option.length, p + n - option.length,
790  length + option.length - n);
791 
792  //Fix the value of the option
793  option.value += m - n;
794  //Fix the length of the message
795  message->length += m - n;
796  }
797 
798  //The second pass fixes the Option Delta field
799  error = coapFormatOption(p, prevOptionNum, &option, &m);
800  //Any error to report?
801  if(error)
802  return error;
803  }
804  }
805 
806  //Return status code
807  return NO_ERROR;
808 }
809 
810 
811 /**
812  * @brief Encode a path or query component into multiple repeatable options
813  * @param[in] message Pointer to the CoAP message
814  * @param[in] optionNum Option number
815  * @param[in] optionValue Path or a query component to be encoded
816  * @param[in] separator Delimiting character
817  * @return Error code
818  **/
819 
821  const char_t *optionValue, char_t separator)
822 {
823  error_t error;
824  size_t i;
825  size_t j;
826  uint_t index;
827 
828  //Initialize status code
829  error = NO_ERROR;
830 
831  //Initialize variables
832  i = 0;
833  j = 0;
834  index = 0;
835 
836  //Split the path or query component into multiple repeatable options
837  do
838  {
839  //Delimiting character found?
840  if(optionValue[i] == separator || optionValue[i] == '\0')
841  {
842  //Discard empty segments
843  if((i - j) > 0)
844  {
845  //Each option specifies one segment of the component
846  error = coapSetOption(message, optionNum, index++,
847  (uint8_t *) optionValue + j, i - j);
848  //Any error to report?
849  if(error)
850  break;
851  }
852 
853  //Move to the next segment
854  j = i + 1;
855  }
856 
857  //Loop until the NULL character is reached
858  } while(optionValue[i++] != '\0');
859 
860  //Return status code
861  return error;
862 }
863 
864 
865 /**
866  * @brief Decode a path or query component from multiple repeatable options
867  * @param[in] message Pointer to the CoAP message
868  * @param[in] optionNum Option number
869  * @param[out] optionValue Buffer where to copy the path or query component
870  * @param[in] maxLen Maximum number of characters the buffer can hold
871  * @param[in] separator Delimiting character
872  * @return Error code
873  **/
874 
876  uint16_t optionNum, char_t *optionValue, size_t maxLen, char_t separator)
877 {
878  error_t error;
879  size_t i;
880  size_t n;
881  uint_t index;
882  const uint8_t *p;
883 
884  //Initialize status code
885  error = NO_ERROR;
886 
887  //Initialize variables
888  i = 0;
889  index = 0;
890 
891  //Build path or query component
892  while(!error)
893  {
894  //Each option specifies one segment of the component
895  error = coapGetOption(message, optionNum, index++, &p, &n);
896 
897  //Check status code
898  if(!error)
899  {
900  //Check separator
901  if(separator != '&' || i != 0)
902  {
903  //Make sure the output buffer is large enough
904  if(i < maxLen)
905  {
906  //Append a delimiting character
907  optionValue[i++] = separator;
908  }
909  }
910 
911  //Make sure the output buffer is large enough
912  if((i + n) <= maxLen)
913  {
914  //Copy option's value
915  memcpy(optionValue + i, p, n);
916  //Update the length of the absolute path
917  i += n;
918  }
919  else
920  {
921  //Report an error
922  error = ERROR_BUFFER_OVERFLOW;
923  }
924  }
925  }
926 
927  //Check status code
928  if(error == ERROR_NOT_FOUND)
929  {
930  //Catch exception
931  error = NO_ERROR;
932  }
933 
934  //Properly terminate the string with a NULL character
935  optionValue[i] = '\0';
936 
937  //Return status code
938  return error;
939 }
940 
941 
942 /**
943  * @brief Retrieve parameters for a given option number
944  * @param[in] optionNum Option number
945  * @return Option parameters
946  **/
947 
949 {
950  uint_t i;
951  const CoapOptionParameters *optionParams;
952 
953  //Initialize variable
954  optionParams = NULL;
955 
956  //Loop through the list of supported options
957  for(i = 0; i < arraysize(coapOptionList); i++)
958  {
959  //Check option number against the expected value
960  if(coapOptionList[i].number == optionNum)
961  {
962  optionParams = &coapOptionList[i];
963  break;
964  }
965  }
966 
967  //Return option parameters
968  return optionParams;
969 }
970 
971 #endif
#define COAP_OPT_DELTA_MINUS_16_BITS
Definition: coap_option.h:42
error_t coapSplitRepeatableOption(CoapMessage *message, uint16_t optionNum, const char_t *optionValue, char_t separator)
Encode a path or query component into multiple repeatable options.
Definition: coap_option.c:820
char char_t
Definition: compiler_port.h:41
error_t coapParseMessageHeader(const uint8_t *p, size_t length, size_t *consumed)
Parse CoAP message header.
Definition: coap_message.c:110
TCP/IP stack core.
Debugging facilities.
uint8_t p
Definition: ndp.h:295
CoAP message.
Definition: coap_message.h:53
uint8_t message[]
Definition: chap.h:150
Opaque sequence of bytes.
Definition: coap_option.h:120
CoAP option formatting and parsing.
__start_packed struct @111 CoapOptionHeader
CoAP option format.
#define COAP_OPT_DELTA_16_BITS
Definition: coap_option.h:39
uint8_t m
Definition: ndp.h:299
#define TRUE
Definition: os_port.h:48
#define COAP_OPT_LEN_MINUS_16_BITS
Definition: coap_option.h:49
#define COAP_OPT_DELTA_MINUS_8_BITS
Definition: coap_option.h:41
#define arraysize(a)
Definition: os_port.h:68
uint16_t number
Definition: coap_option.h:176
Zero-length sequence of bytes.
Definition: coap_option.h:119
#define COAP_OPT_LEN_8_BITS
Definition: coap_option.h:45
#define COAP_OPT_LEN_16_BITS
Definition: coap_option.h:46
size_t length
Definition: coap_option.h:177
error_t coapGetOption(const CoapMessage *message, uint16_t optionNum, uint_t optionIndex, const uint8_t **optionValue, size_t *optionLen)
Get the value of the specified option.
Definition: coap_option.c:569
const CoapOptionParameters * coapGetOptionParameters(uint16_t optionNum)
Retrieve parameters for a given option number.
Definition: coap_option.c:948
#define LOAD16BE(p)
Definition: cpu_endian.h:168
error_t coapParseOptions(const uint8_t *p, size_t length, size_t *consumed)
Parse the list of CoAP options.
Definition: coap_option.c:79
Non-negative integer.
Definition: coap_option.h:121
#define COAP_MAX_MSG_SIZE
Definition: coap_common.h:37
#define COAP_OPT_DELTA_8_BITS
Definition: coap_option.h:38
#define COAP_PAYLOAD_MARKER
Definition: coap_common.h:51
#define COAP_OPT_LEN_RESERVED
Definition: coap_option.h:47
Success.
Definition: error.h:42
error_t coapSetUintOption(CoapMessage *message, uint16_t optionNum, uint_t optionIndex, uint32_t optionValue)
Add a uint option to the specified CoAP message.
Definition: coap_option.c:541
error_t coapSetOption(CoapMessage *message, uint16_t optionNum, uint_t optionIndex, const uint8_t *optionValue, size_t optionLen)
Add an option to the specified CoAP message.
Definition: coap_option.c:386
const uint8_t * value
Definition: coap_option.h:178
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
#define STORE16BE(a, p)
Definition: cpu_endian.h:244
#define COAP_OPT_DELTA_RESERVED
Definition: coap_option.h:40
error_t coapDeleteOption(CoapMessage *message, uint16_t optionNum, uint_t optionIndex)
Remove an option from the specified CoAP message.
Definition: coap_option.c:686
error_t coapGetUintOption(const CoapMessage *message, uint16_t optionNum, uint_t optionIndex, uint32_t *optionValue)
Get the value of the specified uint option.
Definition: coap_option.c:649
error_t coapFormatOption(uint8_t *p, uint16_t prevOptionNum, CoapOption *option, size_t *written)
Format CoAP option.
Definition: coap_option.c:260
CoAP option.
Definition: coap_option.h:173
CoAP client.
error_t coapParseOption(const uint8_t *p, size_t length, uint16_t prevOptionNum, CoapOption *option, size_t *consumed)
Parse CoAP option.
Definition: coap_option.c:131
#define COAP_OPT_LEN_MINUS_8_BITS
Definition: coap_option.h:48
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
#define FALSE
Definition: os_port.h:44
uint16_t delta
Definition: coap_option.h:175
int bool_t
Definition: compiler_port.h:47
UTF-8 string.
Definition: coap_option.h:122
error_t coapJoinRepeatableOption(const CoapMessage *message, uint16_t optionNum, char_t *optionValue, size_t maxLen, char_t separator)
Decode a path or query component from multiple repeatable options.
Definition: coap_option.c:875
CoAP option parameters.
Definition: coap_option.h:186
const CoapOptionParameters coapOptionList[]
List of supported CoAP options.
Definition: coap_option.c:47