• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * resource.h -- generic resource handling
3  *
4  * Copyright (C) 2010,2011,2014,2015 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 resource.h
12  * @brief Generic resource handling
13  */
14 
15 #ifndef COAP_RESOURCE_H_
16 #define COAP_RESOURCE_H_
17 
18 #ifndef COAP_RESOURCE_CHECK_TIME
19 /** The interval in seconds to check if resources have changed. */
20 #define COAP_RESOURCE_CHECK_TIME 2
21 #endif /* COAP_RESOURCE_CHECK_TIME */
22 
23 #include "uthash.h"
24 #include "async.h"
25 #include "block.h"
26 #include "str.h"
27 #include "pdu.h"
28 #include "net.h"
29 #include "subscribe.h"
30 
31 /**
32  * Definition of message handler function (@sa coap_resource_t).
33  */
34 typedef void (*coap_method_handler_t)
35   (coap_context_t  *,
36    struct coap_resource_t *,
37    coap_session_t *,
38    coap_pdu_t *,
39    coap_binary_t * /* token */,
40    coap_string_t * /* query string */,
41    coap_pdu_t * /* response */);
42 
43 #define COAP_ATTR_FLAGS_RELEASE_NAME  0x1
44 #define COAP_ATTR_FLAGS_RELEASE_VALUE 0x2
45 
46 typedef struct coap_attr_t {
47   struct coap_attr_t *next;
48   coap_str_const_t *name;
49   coap_str_const_t *value;
50   int flags;
51 } coap_attr_t;
52 
53 /** The URI passed to coap_resource_init() is free'd by coap_delete_resource(). */
54 #define COAP_RESOURCE_FLAGS_RELEASE_URI 0x1
55 
56 /**
57  * Notifications will be sent non-confirmable by default. RFC 7641 Section 4.5
58  * https://tools.ietf.org/html/rfc7641#section-4.5
59  */
60 #define COAP_RESOURCE_FLAGS_NOTIFY_NON  0x0
61 
62 /**
63  * Notifications will be sent confirmable by default. RFC 7641 Section 4.5
64  * https://tools.ietf.org/html/rfc7641#section-4.5
65  */
66 #define COAP_RESOURCE_FLAGS_NOTIFY_CON  0x2
67 
68 typedef struct coap_resource_t {
69   unsigned int dirty:1;          /**< set to 1 if resource has changed */
70   unsigned int partiallydirty:1; /**< set to 1 if some subscribers have not yet
71                                   *   been notified of the last change */
72   unsigned int observable:1;     /**< can be observed */
73   unsigned int cacheable:1;      /**< can be cached */
74   unsigned int is_unknown:1;     /**< resource created for unknown handler */
75 
76   /**
77    * Used to store handlers for the seven coap methods @c GET, @c POST, @c PUT,
78    * @c DELETE, @c FETCH, @c PATCH and @c IPATCH.
79    * coap_dispatch() will pass incoming requests to the handler
80    * that corresponds to its request method or generate a 4.05 response if no
81    * handler is available.
82    */
83   coap_method_handler_t handler[7];
84 
85   UT_hash_handle hh;
86 
87   coap_attr_t *link_attr; /**< attributes to be included with the link format */
88   coap_subscription_t *subscribers;  /**< list of observers for this resource */
89 
90   /**
91    * Request URI Path for this resource. This field will point into static
92    * or allocated memory which must remain there for the duration of the
93    * resource.
94    */
95   coap_str_const_t *uri_path;  /**< the key used for hash lookup for this resource */
96   int flags;
97 
98   /**
99   * The next value for the Observe option. This field must be increased each
100   * time the resource changes. Only the lower 24 bits are sent.
101   */
102   unsigned int observe;
103 
104   /**
105    * This pointer is under user control. It can be used to store context for
106    * the coap handler.
107    */
108   void *user_data;
109 
110 } coap_resource_t;
111 
112 /**
113  * Creates a new resource object and initializes the link field to the string
114  * @p uri_path. This function returns the new coap_resource_t object.
115  *
116  * If the string is going to be freed off by coap_delete_resource() when
117  * COAP_RESOURCE_FLAGS_RELEASE_URI is set in @p flags, then either the 's'
118  * variable of coap_str_const_t has to point to constant text, or point to data
119  * within the allocated coap_str_const_t parameter.
120  *
121  * @param uri_path The string URI path of the new resource.
122  * @param flags    Flags for memory management (in particular release of
123  *                 memory). Possible values:@n
124  *
125  *                 COAP_RESOURCE_FLAGS_RELEASE_URI
126  *                  If this flag is set, the URI passed to
127  *                  coap_resource_init() is free'd by
128  *                  coap_delete_resource()@n
129  *
130  *                 COAP_RESOURCE_FLAGS_NOTIFY_CON
131  *                  If this flag is set, coap-observe notifications
132  *                  will be sent confirmable by default.@n
133  *
134  *                 COAP_RESOURCE_FLAGS_NOTIFY_NON (default)
135  *                  If this flag is set, coap-observe notifications
136  *                  will be sent non-confirmable by default.@n
137  *
138  *                  If flags is set to 0 then the
139  *                  COAP_RESOURCE_FLAGS_NOTIFY_NON is considered.
140  *
141  * @return         A pointer to the new object or @c NULL on error.
142  */
143 coap_resource_t *coap_resource_init(coap_str_const_t *uri_path,
144                                     int flags);
145 
146 
147 /**
148  * Creates a new resource object for the unknown resource handler with support
149  * for PUT.
150  *
151  * In the same way that additional handlers can be added to the resource
152  * created by coap_resource_init() by using coap_register_handler(), POST,
153  * GET, DELETE etc. handlers can be added to this resource. It is the
154  * responsibility of the application to manage the unknown resources by either
155  * creating new resources with coap_resource_init() (which should have a
156  * DELETE handler specified for the resource removal) or by maintaining an
157  * active resource list.
158  *
159  * Note: There can only be one unknown resource handler per context - attaching
160  *       a new one overrides the previous definition.
161  *
162  * Note: It is not possible to observe the unknown resource with a GET request
163  *       - a separate resource needs to be reated by the PUT (or POST) handler,
164  *       and make that resource observable.
165  *
166  * This function returns the new coap_resource_t object.
167  *
168  * @param put_handler The PUT handler to register with @p resource for
169  *                    unknown Uri-Path.
170  *
171  * @return       A pointer to the new object or @c NULL on error.
172  */
173 coap_resource_t *coap_resource_unknown_init(coap_method_handler_t put_handler);
174 
175 /**
176  * Sets the notification message type of resource @p resource to given
177  * @p mode
178 
179  * @param resource The resource to update.
180  * @param mode     Must be one of @c COAP_RESOURCE_FLAGS_NOTIFY_NON
181  *                 or @c COAP_RESOURCE_FLAGS_NOTIFY_CON.
182  */
183 COAP_STATIC_INLINE void
coap_resource_set_mode(coap_resource_t * resource,int mode)184 coap_resource_set_mode(coap_resource_t *resource, int mode) {
185   resource->flags = (resource->flags &
186     ~(COAP_RESOURCE_FLAGS_NOTIFY_CON|COAP_RESOURCE_FLAGS_NOTIFY_NON)) |
187     (mode & (COAP_RESOURCE_FLAGS_NOTIFY_CON|COAP_RESOURCE_FLAGS_NOTIFY_NON));
188 }
189 
190 /**
191  * Sets the user_data. The user_data is exclusively used by the library-user
192  * and can be used as context in the handler functions.
193  *
194  * @param r       Resource to attach the data to
195  * @param data    Data to attach to the user_data field. This pointer is only used for
196  *                storage, the data remains under user control
197  */
198 COAP_STATIC_INLINE void
coap_resource_set_userdata(coap_resource_t * r,void * data)199 coap_resource_set_userdata(coap_resource_t *r, void *data) {
200   r->user_data = data;
201 }
202 
203 /**
204  * Gets the user_data. The user_data is exclusively used by the library-user
205  * and can be used as context in the handler functions.
206  *
207  * @param r        Resource to retrieve the user_darta from
208  *
209  * @return        The user_data pointer
210  */
211 COAP_STATIC_INLINE void *
coap_resource_get_userdata(coap_resource_t * r)212 coap_resource_get_userdata(coap_resource_t *r) {
213   return r->user_data;
214 }
215 
216 /**
217  * Registers the given @p resource for @p context. The resource must have been
218  * created by coap_resource_init() or coap_resource_unknown_init(), the
219  * storage allocated for the resource will be released by coap_delete_resource().
220  *
221  * @param context  The context to use.
222  * @param resource The resource to store.
223  */
224 void coap_add_resource(coap_context_t *context, coap_resource_t *resource);
225 
226 /**
227  * Deletes a resource identified by @p resource. The storage allocated for that
228  * resource is freed, and removed from the context.
229  *
230  * @param context  The context where the resources are stored.
231  * @param resource The resource to delete.
232  *
233  * @return         @c 1 if the resource was found (and destroyed),
234  *                 @c 0 otherwise.
235  */
236 int coap_delete_resource(coap_context_t *context, coap_resource_t *resource);
237 
238 /**
239  * Deletes all resources from given @p context and frees their storage.
240  *
241  * @param context The CoAP context with the resources to be deleted.
242  */
243 void coap_delete_all_resources(coap_context_t *context);
244 
245 /**
246  * Registers a new attribute with the given @p resource. As the
247  * attribute's coap_str_const_ fields will point to @p name and @p value the
248  * caller must ensure that these pointers are valid during the
249  * attribute's lifetime.
250 
251  * If the @p name and/or @p value string is going to be freed off at attribute
252  * removal time by the setting of COAP_ATTR_FLAGS_RELEASE_NAME or
253  * COAP_ATTR_FLAGS_RELEASE_VALUE in @p flags, then either the 's'
254  * variable of coap_str_const_t has to point to constant text, or point to data
255  * within the allocated coap_str_const_t parameter.
256  *
257  * @param resource The resource to register the attribute with.
258  * @param name     The attribute's name as a string.
259  * @param value    The attribute's value as a string or @c NULL if none.
260  * @param flags    Flags for memory management (in particular release of
261  *                 memory). Possible values:@n
262  *
263  *                 COAP_ATTR_FLAGS_RELEASE_NAME
264  *                  If this flag is set, the name passed to
265  *                  coap_add_attr_release() is free'd
266  *                  when the attribute is deleted@n
267  *
268  *                 COAP_ATTR_FLAGS_RELEASE_VALUE
269  *                  If this flag is set, the value passed to
270  *                  coap_add_attr_release() is free'd
271  *                  when the attribute is deleted@n
272  *
273  * @return         A pointer to the new attribute or @c NULL on error.
274  */
275 coap_attr_t *coap_add_attr(coap_resource_t *resource,
276                            coap_str_const_t *name,
277                            coap_str_const_t *value,
278                            int flags);
279 
280 /**
281  * Returns @p resource's coap_attr_t object with given @p name if found, @c NULL
282  * otherwise.
283  *
284  * @param resource The resource to search for attribute @p name.
285  * @param name     Name of the requested attribute as a string.
286  * @return         The first attribute with specified @p name or @c NULL if none
287  *                 was found.
288  */
289 coap_attr_t *coap_find_attr(coap_resource_t *resource,
290                             coap_str_const_t *name);
291 
292 /**
293  * Deletes an attribute.
294  * Note: This is for internal use only, as it is not deleted from its chain.
295  *
296  * @param attr Pointer to a previously created attribute.
297  *
298  */
299 void coap_delete_attr(coap_attr_t *attr);
300 
301 /**
302  * Status word to encode the result of conditional print or copy operations such
303  * as coap_print_link(). The lower 28 bits of coap_print_status_t are used to
304  * encode the number of characters that has actually been printed, bits 28 to 31
305  * encode the status.  When COAP_PRINT_STATUS_ERROR is set, an error occurred
306  * during output. In this case, the other bits are undefined.
307  * COAP_PRINT_STATUS_TRUNC indicates that the output is truncated, i.e. the
308  * printing would have exceeded the current buffer.
309  */
310 typedef unsigned int coap_print_status_t;
311 
312 #define COAP_PRINT_STATUS_MASK  0xF0000000u
313 #define COAP_PRINT_OUTPUT_LENGTH(v) ((v) & ~COAP_PRINT_STATUS_MASK)
314 #define COAP_PRINT_STATUS_ERROR 0x80000000u
315 #define COAP_PRINT_STATUS_TRUNC 0x40000000u
316 
317 /**
318  * Writes a description of this resource in link-format to given text buffer. @p
319  * len must be initialized to the maximum length of @p buf and will be set to
320  * the number of characters actually written if successful. This function
321  * returns @c 1 on success or @c 0 on error.
322  *
323  * @param resource The resource to describe.
324  * @param buf      The output buffer to write the description to.
325  * @param len      Must be initialized to the length of @p buf and
326  *                 will be set to the length of the printed link description.
327  * @param offset   The offset within the resource description where to
328  *                 start writing into @p buf. This is useful for dealing
329  *                 with the Block2 option. @p offset is updated during
330  *                 output as it is consumed.
331  *
332  * @return If COAP_PRINT_STATUS_ERROR is set, an error occured. Otherwise,
333  *         the lower 28 bits will indicate the number of characters that
334  *         have actually been output into @p buffer. The flag
335  *         COAP_PRINT_STATUS_TRUNC indicates that the output has been
336  *         truncated.
337  */
338 coap_print_status_t coap_print_link(const coap_resource_t *resource,
339                                     unsigned char *buf,
340                                     size_t *len,
341                                     size_t *offset);
342 
343 /**
344  * Registers the specified @p handler as message handler for the request type @p
345  * method
346  *
347  * @param resource The resource for which the handler shall be registered.
348  * @param method   The CoAP request method to handle.
349  * @param handler  The handler to register with @p resource.
350  */
351 void coap_register_handler(coap_resource_t *resource,
352                            unsigned char method,
353                            coap_method_handler_t handler);
354 
355 /**
356  * Returns the resource identified by the unique string @p uri_path. If no
357  * resource was found, this function returns @c NULL.
358  *
359  * @param context  The context to look for this resource.
360  * @param uri_path  The unique string uri of the resource.
361  *
362  * @return         A pointer to the resource or @c NULL if not found.
363  */
364 coap_resource_t *coap_get_resource_from_uri_path(coap_context_t *context,
365                                                 coap_str_const_t *uri_path);
366 
367 /**
368  * @addtogroup observe
369  */
370 
371 /**
372  * Adds the specified peer as observer for @p resource. The subscription is
373  * identified by the given @p token. This function returns the registered
374  * subscription information if the @p observer has been added, or @c NULL on
375  * error.
376  *
377  * @param resource        The observed resource.
378  * @param session         The observer's session
379  * @param token           The token that identifies this subscription.
380  * @param query           The query string, if any. subscription will
381                           take ownership of the string.
382  * @param has_block2      If Option Block2 defined.
383  * @param block2          Contents of Block2 if Block 2 defined.
384  * @return                A pointer to the added/updated subscription
385  *                        information or @c NULL on error.
386  */
387 coap_subscription_t *coap_add_observer(coap_resource_t *resource,
388                                        coap_session_t *session,
389                                        const coap_binary_t *token,
390                                        coap_string_t *query,
391                                        int has_block2,
392                                        coap_block_t block2);
393 
394 /**
395  * Returns a subscription object for given @p peer.
396  *
397  * @param resource The observed resource.
398  * @param session  The observer's session
399  * @param token    The token that identifies this subscription or @c NULL for
400  *                 any token.
401  * @return         A valid subscription if exists or @c NULL otherwise.
402  */
403 coap_subscription_t *coap_find_observer(coap_resource_t *resource,
404                                         coap_session_t *session,
405                                         const coap_binary_t *token);
406 
407 /**
408  * Marks an observer as alive.
409  *
410  * @param context  The CoAP context to use.
411  * @param session  The observer's session
412  * @param token    The corresponding token that has been used for the
413  *                 subscription.
414  */
415 void coap_touch_observer(coap_context_t *context,
416                          coap_session_t *session,
417                          const coap_binary_t *token);
418 
419 /**
420  * Removes any subscription for @p observer from @p resource and releases the
421  * allocated storage. The result is @c 1 if an observation relationship with @p
422  * observer and @p token existed, @c 0 otherwise.
423  *
424  * @param resource The observed resource.
425  * @param session  The observer's session.
426  * @param token    The token that identifies this subscription or @c NULL for
427  *                 any token.
428  * @return         @c 1 if the observer has been deleted, @c 0 otherwise.
429  */
430 int coap_delete_observer(coap_resource_t *resource,
431                          coap_session_t *session,
432                          const coap_binary_t *token);
433 
434 /**
435  * Removes any subscription for @p session and releases the allocated storage.
436  *
437  * @param context  The CoAP context to use.
438  * @param session  The observer's session.
439  */
440 void coap_delete_observers(coap_context_t *context, coap_session_t *session);
441 
442 /**
443  * Checks for all known resources, if they are dirty and notifies subscribed
444  * observers.
445  */
446 void coap_check_notify(coap_context_t *context);
447 
448 #ifdef WITH_LWIP
449 /**
450  * This API is called when the caller is not in the same thread
451  * with tcpip thread.
452  * Checks for all known resources, if they are dirty and notifies subscribed
453  * observers.
454  */
455 void coap_check_notify_lwip(coap_context_t *context);
456 #endif
457 
458 #define RESOURCES_ADD(r, obj) \
459   HASH_ADD(hh, (r), uri_path->s[0], (obj)->uri_path->length, (obj))
460 
461 #define RESOURCES_DELETE(r, obj) \
462   HASH_DELETE(hh, (r), (obj))
463 
464 #define RESOURCES_ITER(r,tmp)  \
465   coap_resource_t *tmp, *rtmp; \
466   HASH_ITER(hh, (r), tmp, rtmp)
467 
468 #define RESOURCES_FIND(r, k, res) {                     \
469     HASH_FIND(hh, (r), (k)->s, (k)->length, (res)); \
470   }
471 
472 /** @} */
473 
474 coap_print_status_t coap_print_wellknown(coap_context_t *,
475                                          unsigned char *,
476                                          size_t *, size_t,
477                                          coap_opt_t *);
478 
479 void
480 coap_handle_failed_notify(coap_context_t *,
481                           coap_session_t *,
482                           const coap_binary_t *);
483 
484 /**
485  * Set whether a @p resource is observable.  If the resource is observable
486  * and the client has set the COAP_OPTION_OBSERVE in a request packet, then
487  * whenever the state of the resource changes (a call to
488  * coap_resource_trigger_observe()), an Observer response will get sent.
489  *
490  * @param resource The CoAP resource to use.
491  * @param mode     @c 1 if Observable is to be set, @c 0 otherwise.
492  *
493  */
494 COAP_STATIC_INLINE void
coap_resource_set_get_observable(coap_resource_t * resource,int mode)495 coap_resource_set_get_observable(coap_resource_t *resource, int mode) {
496   resource->observable = mode ? 1 : 0;
497 }
498 
499 /**
500  * Initiate the sending of an Observe packet for all observers of @p resource,
501  * optionally matching @p query if not NULL
502  *
503  * @param resource The CoAP resource to use.
504  * @param query    The Query to match against or NULL
505  *
506  * @return         @c 1 if the Observe has been triggered, @c 0 otherwise.
507  */
508 int
509 coap_resource_notify_observers(coap_resource_t *resource,
510                                const coap_string_t *query);
511 
512 /**
513  * Get the UriPath from a @p resource.
514  *
515  * @param resource The CoAP resource to check.
516  *
517  * @return         The UriPath if it exists or @c NULL otherwise.
518  */
519 COAP_STATIC_INLINE coap_str_const_t*
coap_resource_get_uri_path(coap_resource_t * resource)520 coap_resource_get_uri_path(coap_resource_t *resource) {
521   if (resource)
522     return resource->uri_path;
523   return NULL;
524 }
525 
526 /**
527  * @deprecated use coap_resource_notify_observers() instead.
528  */
529 COAP_DEPRECATED int
530 coap_resource_set_dirty(coap_resource_t *r,
531                         const coap_string_t *query);
532 
533 #endif /* COAP_RESOURCE_H_ */
534