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