• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * option.h -- helpers for handling options in CoAP PDUs
3  *
4  * Copyright (C) 2010-2013 Olaf Bergmann <bergmann@tzi.org>
5  *
6  * This file is part of the CoAP library libcoap. Please see README for terms
7  * of use.
8  */
9 
10 /**
11  * @file option.h
12  * @brief Helpers for handling options in CoAP PDUs
13  */
14 
15 #ifndef COAP_OPTION_H_
16 #define COAP_OPTION_H_
17 
18 #include "bits.h"
19 #include "pdu.h"
20 
21 /**
22  * Use byte-oriented access methods here because sliding a complex struct
23  * coap_opt_t over the data buffer may cause bus error on certain platforms.
24  */
25 typedef uint8_t coap_opt_t;
26 #define PCHAR(p) ((coap_opt_t *)(p))
27 
28 /**
29  * Representation of CoAP options.
30  */
31 typedef struct {
32   uint16_t delta;
33   size_t length;
34   const uint8_t *value;
35 } coap_option_t;
36 
37 /**
38  * Parses the option pointed to by @p opt into @p result. This function returns
39  * the number of bytes that have been parsed, or @c 0 on error. An error is
40  * signaled when illegal delta or length values are encountered or when option
41  * parsing would result in reading past the option (i.e. beyond opt + length).
42  *
43  * @param opt    The beginning of the option to parse.
44  * @param length The maximum length of @p opt.
45  * @param result A pointer to the coap_option_t structure that is filled with
46  *               actual values iff coap_opt_parse() > 0.
47  * @return       The number of bytes parsed or @c 0 on error.
48  */
49 size_t coap_opt_parse(const coap_opt_t *opt,
50                       size_t length,
51                       coap_option_t *result);
52 
53 /**
54  * Returns the size of the given option, taking into account a possible option
55  * jump.
56  *
57  * @param opt An option jump or the beginning of the option.
58  * @return    The number of bytes between @p opt and the end of the option
59  *            starting at @p opt. In case of an error, this function returns
60  *            @c 0 as options need at least one byte storage space.
61  */
62 size_t coap_opt_size(const coap_opt_t *opt);
63 
64 /**
65  * @defgroup opt_filter Option Filters
66  * API functions for access option filters
67  * @{
68  */
69 
70 /**
71  * The number of option types below 256 that can be stored in an
72  * option filter. COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be
73  * at most 16. Each coap_option_filter_t object reserves
74  * ((COAP_OPT_FILTER_SHORT + 1) / 2) * 2 bytes for short options.
75  */
76 #define COAP_OPT_FILTER_SHORT 6
77 
78 /**
79  * The number of option types above 255 that can be stored in an
80  * option filter. COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be
81  * at most 16. Each coap_option_filter_t object reserves
82  * COAP_OPT_FILTER_LONG * 2 bytes for short options.
83  */
84 #define COAP_OPT_FILTER_LONG  2
85 
86 /* Ensure that COAP_OPT_FILTER_SHORT and COAP_OPT_FILTER_LONG are set
87  * correctly. */
88 #if (COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG > 16)
89 #error COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be less or equal 16
90 #endif /* (COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG > 16) */
91 
92 /** The number of elements in coap_opt_filter_t. */
93 #define COAP_OPT_FILTER_SIZE                                        \
94   (((COAP_OPT_FILTER_SHORT + 1) >> 1) + COAP_OPT_FILTER_LONG) +1
95 
96 /**
97  * Fixed-size vector we use for option filtering. It is large enough
98  * to hold COAP_OPT_FILTER_SHORT entries with an option number between
99  * 0 and 255, and COAP_OPT_FILTER_LONG entries with an option number
100  * between 256 and 65535. Its internal structure is
101  *
102  * @code
103 struct {
104   uint16_t mask;
105   uint16_t long_opts[COAP_OPT_FILTER_LONG];
106   uint8_t short_opts[COAP_OPT_FILTER_SHORT];
107 }
108  * @endcode
109  *
110  * The first element contains a bit vector that indicates which fields
111  * in the remaining array are used. The first COAP_OPT_FILTER_LONG
112  * bits correspond to the long option types that are stored in the
113  * elements from index 1 to COAP_OPT_FILTER_LONG. The next
114  * COAP_OPT_FILTER_SHORT bits correspond to the short option types
115  * that are stored in the elements from index COAP_OPT_FILTER_LONG + 1
116  * to COAP_OPT_FILTER_LONG + COAP_OPT_FILTER_SHORT. The latter
117  * elements are treated as bytes.
118  */
119 typedef uint16_t coap_opt_filter_t[COAP_OPT_FILTER_SIZE];
120 
121 /** Pre-defined filter that includes all options. */
122 #define COAP_OPT_ALL NULL
123 
124 /**
125  * Clears filter @p f.
126  *
127  * @param f The filter to clear.
128  */
129 COAP_STATIC_INLINE void
coap_option_filter_clear(coap_opt_filter_t f)130 coap_option_filter_clear(coap_opt_filter_t f) {
131   memset(f, 0, sizeof(coap_opt_filter_t));
132 }
133 
134 /**
135  * Sets the corresponding entry for @p type in @p filter. This
136  * function returns @c 1 if bit was set or @c 0 on error (i.e. when
137  * the given type does not fit in the filter).
138  *
139  * @param filter The filter object to change.
140  * @param type   The type for which the bit should be set.
141  *
142  * @return       @c 1 if bit was set, @c 0 otherwise.
143  */
144 int coap_option_filter_set(coap_opt_filter_t filter, uint16_t type);
145 
146 /**
147  * Clears the corresponding entry for @p type in @p filter. This
148  * function returns @c 1 if bit was set or @c 0 on error (i.e. when
149  * the given type does not fit in the filter).
150  *
151  * @param filter The filter object to change.
152  * @param type   The type that should be cleared from the filter.
153  *
154  * @return       @c 1 if bit was set, @c 0 otherwise.
155  */
156 int coap_option_filter_unset(coap_opt_filter_t filter, uint16_t type);
157 
158 /**
159  * Checks if @p type is contained in @p filter. This function returns
160  * @c 1 if found, @c 0 if not, or @c -1 on error (i.e. when the given
161  * type does not fit in the filter).
162  *
163  * @param filter The filter object to search.
164  * @param type   The type to search for.
165  *
166  * @return       @c 1 if @p type was found, @c 0 otherwise, or @c -1 on error.
167  */
168 int coap_option_filter_get(coap_opt_filter_t filter, uint16_t type);
169 
170 /**
171  * Sets the corresponding bit for @p type in @p filter. This function returns @c
172  * 1 if bit was set or @c -1 on error (i.e. when the given type does not fit in
173  * the filter).
174  *
175  * @deprecated Use coap_option_filter_set() instead.
176  *
177  * @param filter The filter object to change.
178  * @param type   The type for which the bit should be set.
179  *
180  * @return       @c 1 if bit was set, @c -1 otherwise.
181  */
182 COAP_STATIC_INLINE int
coap_option_setb(coap_opt_filter_t filter,uint16_t type)183 coap_option_setb(coap_opt_filter_t filter, uint16_t type) {
184   return coap_option_filter_set(filter, type) ? 1 : -1;
185 }
186 
187 /**
188  * Clears the corresponding bit for @p type in @p filter. This function returns
189  * @c 1 if bit was cleared or @c -1 on error (i.e. when the given type does not
190  * fit in the filter).
191  *
192  * @deprecated Use coap_option_filter_unset() instead.
193  *
194  * @param filter The filter object to change.
195  * @param type   The type for which the bit should be cleared.
196  *
197  * @return       @c 1 if bit was set, @c -1 otherwise.
198  */
199 COAP_STATIC_INLINE int
coap_option_clrb(coap_opt_filter_t filter,uint16_t type)200 coap_option_clrb(coap_opt_filter_t filter, uint16_t type) {
201   return coap_option_filter_unset(filter, type) ? 1 : -1;
202 }
203 
204 /**
205  * Gets the corresponding bit for @p type in @p filter. This function returns @c
206  * 1 if the bit is set @c 0 if not, or @c -1 on error (i.e. when the given type
207  * does not fit in the filter).
208  *
209  * @deprecated Use coap_option_filter_get() instead.
210  *
211  * @param filter The filter object to read bit from.
212  * @param type   The type for which the bit should be read.
213  *
214  * @return       @c 1 if bit was set, @c 0 if not, @c -1 on error.
215  */
216 COAP_STATIC_INLINE int
coap_option_getb(coap_opt_filter_t filter,uint16_t type)217 coap_option_getb(coap_opt_filter_t filter, uint16_t type) {
218   return coap_option_filter_get(filter, type);
219 }
220 
221 /**
222  * Iterator to run through PDU options. This object must be
223  * initialized with coap_option_iterator_init(). Call
224  * coap_option_next() to walk through the list of options until
225  * coap_option_next() returns @c NULL.
226  *
227  * @code
228  * coap_opt_t *option;
229  * coap_opt_iterator_t opt_iter;
230  * coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL);
231  *
232  * while ((option = coap_option_next(&opt_iter))) {
233  *   ... do something with option ...
234  * }
235  * @endcode
236  */
237 typedef struct {
238   size_t length;                /**< remaining length of PDU */
239   uint16_t type;                /**< decoded option type */
240   unsigned int bad:1;           /**< iterator object is ok if not set */
241   unsigned int filtered:1;      /**< denotes whether or not filter is used */
242   coap_opt_t *next_option;      /**< pointer to the unparsed next option */
243   coap_opt_filter_t filter;     /**< option filter */
244 } coap_opt_iterator_t;
245 
246 /**
247  * Initializes the given option iterator @p oi to point to the beginning of the
248  * @p pdu's option list. This function returns @p oi on success, @c NULL
249  * otherwise (i.e. when no options exist). Note that a length check on the
250  * option list must be performed before coap_option_iterator_init() is called.
251  *
252  * @param pdu    The PDU the options of which should be walked through.
253  * @param oi     An iterator object that will be initilized.
254  * @param filter An optional option type filter.
255  *               With @p type != @c COAP_OPT_ALL, coap_option_next()
256  *               will return only options matching this bitmask.
257  *               Fence-post options @c 14, @c 28, @c 42, ... are always
258  *               skipped.
259  *
260  * @return       The iterator object @p oi on success, @c NULL otherwise.
261  */
262 coap_opt_iterator_t *coap_option_iterator_init(const coap_pdu_t *pdu,
263                                                coap_opt_iterator_t *oi,
264                                                const coap_opt_filter_t filter);
265 
266 /**
267  * Updates the iterator @p oi to point to the next option. This function returns
268  * a pointer to that option or @c NULL if no more options exist. The contents of
269  * @p oi will be updated. In particular, @c oi->n specifies the current option's
270  * ordinal number (counted from @c 1), @c oi->type is the option's type code,
271  * and @c oi->option points to the beginning of the current option itself. When
272  * advanced past the last option, @c oi->option will be @c NULL.
273  *
274  * Note that options are skipped whose corresponding bits in the filter
275  * specified with coap_option_iterator_init() are @c 0. Options with type codes
276  * that do not fit in this filter hence will always be returned.
277  *
278  * @param oi The option iterator to update.
279  *
280  * @return   The next option or @c NULL if no more options exist.
281  */
282 coap_opt_t *coap_option_next(coap_opt_iterator_t *oi);
283 
284 /**
285  * Retrieves the first option of type @p type from @p pdu. @p oi must point to a
286  * coap_opt_iterator_t object that will be initialized by this function to
287  * filter only options with code @p type. This function returns the first option
288  * with this type, or @c NULL if not found.
289  *
290  * @param pdu  The PDU to parse for options.
291  * @param type The option type code to search for.
292  * @param oi   An iterator object to use.
293  *
294  * @return     A pointer to the first option of type @p type, or @c NULL if
295  *             not found.
296  */
297 coap_opt_t *coap_check_option(coap_pdu_t *pdu,
298                               uint16_t type,
299                               coap_opt_iterator_t *oi);
300 
301 /**
302  * Encodes the given delta and length values into @p opt. This function returns
303  * the number of bytes that were required to encode @p delta and @p length or @c
304  * 0 on error. Note that the result indicates by how many bytes @p opt must be
305  * advanced to encode the option value.
306  *
307  * @param opt    The option buffer space where @p delta and @p length are
308  *               written.
309  * @param maxlen The maximum length of @p opt.
310  * @param delta  The actual delta value to encode.
311  * @param length The actual length value to encode.
312  *
313  * @return       The number of bytes used or @c 0 on error.
314  */
315 size_t coap_opt_setheader(coap_opt_t *opt,
316                           size_t maxlen,
317                           uint16_t delta,
318                           size_t length);
319 
320 /**
321  * Compute storage bytes needed for an option with given @p delta and
322  * @p length
323  *
324  * @param delta  The option delta.
325  * @param length The option length.
326  *
327  * @return       The number of bytes required to encode this option.
328  */
329 size_t coap_opt_encode_size(uint16_t delta, size_t length);
330 
331 /**
332  * Encodes option with given @p delta into @p opt. This function returns the
333  * number of bytes written to @p opt or @c 0 on error. This happens especially
334  * when @p opt does not provide sufficient space to store the option value,
335  * delta, and option jumps when required.
336  *
337  * @param opt    The option buffer space where @p val is written.
338  * @param n      Maximum length of @p opt.
339  * @param delta  The option delta.
340  * @param val    The option value to copy into @p opt.
341  * @param length The actual length of @p val.
342  *
343  * @return       The number of bytes that have been written to @p opt or @c 0 on
344  *               error. The return value will always be less than @p n.
345  */
346 size_t coap_opt_encode(coap_opt_t *opt,
347                        size_t n,
348                        uint16_t delta,
349                        const uint8_t *val,
350                        size_t length);
351 
352 /**
353  * Decodes the delta value of the next option. This function returns the number
354  * of bytes read or @c 0 on error. The caller of this function must ensure that
355  * it does not read over the boundaries of @p opt (e.g. by calling
356  * coap_opt_check_delta().
357  *
358  * @param opt The option to examine.
359  *
360  * @return    The number of bytes read or @c 0 on error.
361  */
362 uint16_t coap_opt_delta(const coap_opt_t *opt);
363 
364 /**
365  * Returns the length of the given option. @p opt must point to an option jump
366  * or the beginning of the option. This function returns @c 0 when @p opt is not
367  * an option or the actual length of @p opt (which can be @c 0 as well).
368  *
369  * @note {The rationale for using @c 0 in case of an error is that in most
370  * contexts, the result of this function is used to skip the next
371  * coap_opt_length() bytes.}
372  *
373  * @param opt  The option whose length should be returned.
374  *
375  * @return     The option's length or @c 0 when undefined.
376  */
377 uint16_t coap_opt_length(const coap_opt_t *opt);
378 
379 /**
380  * Returns a pointer to the value of the given option. @p opt must point to an
381  * option jump or the beginning of the option. This function returns @c NULL if
382  * @p opt is not a valid option.
383  *
384  * @param opt The option whose value should be returned.
385  *
386  * @return    A pointer to the option value or @c NULL on error.
387  */
388 const uint8_t *coap_opt_value(const coap_opt_t *opt);
389 
390 /** @} */
391 
392 /**
393  * Representation of chained list of CoAP options to install.
394  *
395  * @code
396  * coap_optlist_t *optlist_chain = NULL;
397  * coap_pdu_t *pdu = coap_new_pdu(session);
398  *
399  * ... other set up code ...
400  * coap_insert_optlist(&optlist_chain, coap_new_optlist(COAP_OPTION_OBSERVE,
401  *                    COAP_OBSERVE_ESTABLISH, NULL));
402  *
403  * coap_add_optlist_pdu(pdu, &optlist_chain);
404  * ... other code ...
405  * coap_delete_optlist(optlist_chain);
406  * @endcode
407  */
408 typedef struct coap_optlist_t {
409   struct coap_optlist_t *next;  /**< next entry in the optlist chain */
410   uint16_t number;              /**< the option number (no delta coding) */
411   size_t length;                /**< the option value length */
412   uint8_t *data;                /**< the option data */
413 } coap_optlist_t;
414 
415 /**
416  * Create a new optlist entry.
417  *
418  * @param number    The option number (COAP_OPTION_*)
419  * @param length    The option length
420  * @param data      The option value data
421  *
422  * @return          A pointer to the new optlist entry, or @c NULL if error
423  */
424 coap_optlist_t *coap_new_optlist(uint16_t number,
425                                  size_t length,
426                                  const uint8_t *data);
427 
428 /**
429  * The current optlist of @p optlist_chain is first sorted (as per RFC7272
430  * ordering requirements) and then added to the @p pdu.
431  *
432  * @param pdu  The pdu to add the options to from the chain list
433  * @param optlist_chain The chained list of optlist to add to the pdu
434  *
435  * @return     @c 1 if succesful or @c 0 if failure;
436  */
437 int coap_add_optlist_pdu(coap_pdu_t *pdu, coap_optlist_t** optlist_chain);
438 
439 /**
440  * Adds @p optlist to the given @p optlist_chain. The optlist_chain variable
441  * be set to NULL before the initial call to coap_insert_optlist().
442  * The optlist_chain will need to be deleted using coap_delete_optlist()
443  * when no longer required.
444  *
445  * @param optlist_chain The chain to add optlist to
446  * @param optlist  The optlist to add to the queue
447  *
448  * @return         @c 1 if successful, @c 0 otherwise.
449  */
450 int coap_insert_optlist(coap_optlist_t **optlist_chain,
451                         coap_optlist_t *optlist);
452 
453 /**
454  * Removes all entries from the @p optlist_chain, freeing off their
455  * memory usage.
456  *
457  * @param optlist_chain The optlist chain to remove all the entries from
458  */
459 void coap_delete_optlist(coap_optlist_t *optlist_chain);
460 
461 #endif /* COAP_OPTION_H_ */
462