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 # include <assert.h>
19 
20 #ifndef COAP_RESOURCE_CHECK_TIME
21 /** The interval in seconds to check if resources have changed. */
22 #define COAP_RESOURCE_CHECK_TIME 2
23 #endif /* COAP_RESOURCE_CHECK_TIME */
24 
25 #ifdef COAP_RESOURCES_NOHASH
26 #  include "utlist.h"
27 #else
28 #  include "uthash.h"
29 #endif
30 
31 #include "hashkey.h"
32 #include "async.h"
33 #include "str.h"
34 #include "pdu.h"
35 #include "net.h"
36 #include "subscribe.h"
37 
38 /**
39  * Definition of message handler function (@sa coap_resource_t).
40  */
41 typedef void (*coap_method_handler_t)
42   (coap_context_t  *,
43    struct coap_resource_t *,
44    const coap_endpoint_t *,
45    coap_address_t *,
46    coap_pdu_t *,
47    str * /* token */,
48    coap_pdu_t * /* response */);
49 
50 #define COAP_ATTR_FLAGS_RELEASE_NAME  0x1
51 #define COAP_ATTR_FLAGS_RELEASE_VALUE 0x2
52 
53 typedef struct coap_attr_t {
54   struct coap_attr_t *next;
55   str name;
56   str value;
57   int flags;
58 } coap_attr_t;
59 
60 #define COAP_RESOURCE_FLAGS_RELEASE_URI 0x1
61 #define COAP_RESOURCE_FLAGS_NOTIFY_NON  0x0
62 #define COAP_RESOURCE_FLAGS_NOTIFY_CON  0x2
63 
64 typedef struct coap_resource_t {
65   unsigned int dirty:1;          /**< set to 1 if resource has changed */
66   unsigned int partiallydirty:1; /**< set to 1 if some subscribers have not yet
67                                   *   been notified of the last change */
68   unsigned int observable:1;     /**< can be observed */
69   unsigned int cacheable:1;      /**< can be cached */
70 
71   /**
72    * Used to store handlers for the four coap methods @c GET, @c POST, @c PUT,
73    * and @c DELETE. coap_dispatch() will pass incoming requests to the handler
74    * that corresponds to its request method or generate a 4.05 response if no
75    * handler is available.
76    */
77   coap_method_handler_t handler[4];
78 
79   coap_key_t key;                /**< the actual key bytes for this resource */
80 
81 #ifdef COAP_RESOURCES_NOHASH
82   struct coap_resource_t *next;
83 #else
84   UT_hash_handle hh;
85 #endif
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 for this resource. This field will point into the static
92    * memory.
93    */
94   str uri;
95   int flags;
96 
97 } coap_resource_t;
98 
99 /**
100  * Creates a new resource object and initializes the link field to the string
101  * of length @p len. This function returns the new coap_resource_t object.
102  *
103  * @param uri    The URI path of the new resource.
104  * @param len    The length of @p uri.
105  * @param flags  Flags for memory management (in particular release of memory).
106  *
107  * @return       A pointer to the new object or @c NULL on error.
108  */
109 coap_resource_t *coap_resource_init(const unsigned char *uri,
110                                     size_t len, int flags);
111 
112 
113 /**
114  * Sets the notification message type of resource @p r to given
115  * @p mode which must be one of @c COAP_RESOURCE_FLAGS_NOTIFY_NON
116  * or @c COAP_RESOURCE_FLAGS_NOTIFY_CON.
117  */
118 static inline void
coap_resource_set_mode(coap_resource_t * r,int mode)119 coap_resource_set_mode(coap_resource_t *r, int mode) {
120   r->flags = (r->flags & !COAP_RESOURCE_FLAGS_NOTIFY_CON) | mode;
121 }
122 
123 /**
124  * Registers the given @p resource for @p context. The resource must have been
125  * created by coap_resource_init(), the storage allocated for the resource will
126  * be released by coap_delete_resource().
127  *
128  * @param context  The context to use.
129  * @param resource The resource to store.
130  */
131 void coap_add_resource(coap_context_t *context, coap_resource_t *resource);
132 
133 /**
134  * Deletes a resource identified by @p key. The storage allocated for that
135  * resource is freed.
136  *
137  * @param context  The context where the resources are stored.
138  * @param key      The unique key for the resource to delete.
139  *
140  * @return         @c 1 if the resource was found (and destroyed),
141  *                 @c 0 otherwise.
142  */
143 int coap_delete_resource(coap_context_t *context, coap_key_t key);
144 
145 /**
146  * Deletes all resources from given @p context and frees their storage.
147  *
148  * @param context The CoAP context with the resources to be deleted.
149  */
150 void coap_delete_all_resources(coap_context_t *context);
151 
152 /**
153  * Registers a new attribute with the given @p resource. As the
154  * attributes str fields will point to @p name and @p val the
155  * caller must ensure that these pointers are valid during the
156  * attribute's lifetime.
157  *
158  * @param resource The resource to register the attribute with.
159  * @param name     The attribute's name.
160  * @param nlen     Length of @p name.
161  * @param val      The attribute's value or @c NULL if none.
162  * @param vlen     Length of @p val if specified.
163  * @param flags    Flags for memory management (in particular release of
164  *                 memory).
165  *
166  * @return         A pointer to the new attribute or @c NULL on error.
167  */
168 coap_attr_t *coap_add_attr(coap_resource_t *resource,
169                            const unsigned char *name,
170                            size_t nlen,
171                            const unsigned char *val,
172                            size_t vlen,
173                            int flags);
174 
175 /**
176  * Returns @p resource's coap_attr_t object with given @p name if found, @c NULL
177  * otherwise.
178  *
179  * @param resource The resource to search for attribute @p name.
180  * @param name     Name of the requested attribute.
181  * @param nlen     Actual length of @p name.
182  * @return         The first attribute with specified @p name or @c NULL if none
183  *                 was found.
184  */
185 coap_attr_t *coap_find_attr(coap_resource_t *resource,
186                             const unsigned char *name,
187                             size_t nlen);
188 
189 /**
190  * Deletes an attribute.
191  *
192  * @param attr Pointer to a previously created attribute.
193  *
194  */
195 void coap_delete_attr(coap_attr_t *attr);
196 
197 /**
198  * Status word to encode the result of conditional print or copy operations such
199  * as coap_print_link(). The lower 28 bits of coap_print_status_t are used to
200  * encode the number of characters that has actually been printed, bits 28 to 31
201  * encode the status.  When COAP_PRINT_STATUS_ERROR is set, an error occurred
202  * during output. In this case, the other bits are undefined.
203  * COAP_PRINT_STATUS_TRUNC indicates that the output is truncated, i.e. the
204  * printing would have exceeded the current buffer.
205  */
206 typedef unsigned int coap_print_status_t;
207 
208 #define COAP_PRINT_STATUS_MASK  0xF0000000u
209 #define COAP_PRINT_OUTPUT_LENGTH(v) ((v) & ~COAP_PRINT_STATUS_MASK)
210 #define COAP_PRINT_STATUS_ERROR 0x80000000u
211 #define COAP_PRINT_STATUS_TRUNC 0x40000000u
212 
213 /**
214  * Writes a description of this resource in link-format to given text buffer. @p
215  * len must be initialized to the maximum length of @p buf and will be set to
216  * the number of characters actually written if successful. This function
217  * returns @c 1 on success or @c 0 on error.
218  *
219  * @param resource The resource to describe.
220  * @param buf      The output buffer to write the description to.
221  * @param len      Must be initialized to the length of @p buf and
222  *                 will be set to the length of the printed link description.
223  * @param offset   The offset within the resource description where to
224  *                 start writing into @p buf. This is useful for dealing
225  *                 with the Block2 option. @p offset is updated during
226  *                 output as it is consumed.
227  *
228  * @return If COAP_PRINT_STATUS_ERROR is set, an error occured. Otherwise,
229  *         the lower 28 bits will indicate the number of characters that
230  *         have actually been output into @p buffer. The flag
231  *         COAP_PRINT_STATUS_TRUNC indicates that the output has been
232  *         truncated.
233  */
234 coap_print_status_t coap_print_link(const coap_resource_t *resource,
235                                     unsigned char *buf,
236                                     size_t *len,
237                                     size_t *offset);
238 
239 /**
240  * Registers the specified @p handler as message handler for the request type @p
241  * method
242  *
243  * @param resource The resource for which the handler shall be registered.
244  * @param method   The CoAP request method to handle.
245  * @param handler  The handler to register with @p resource.
246  */
247 static inline void
coap_register_handler(coap_resource_t * resource,unsigned char method,coap_method_handler_t handler)248 coap_register_handler(coap_resource_t *resource,
249                       unsigned char method,
250                       coap_method_handler_t handler) {
251   assert(resource);
252   assert(method > 0 && (size_t)(method-1) < sizeof(resource->handler)/sizeof(coap_method_handler_t));
253   resource->handler[method-1] = handler;
254 }
255 
256 /**
257  * Returns the resource identified by the unique string @p key. If no resource
258  * was found, this function returns @c NULL.
259  *
260  * @param context  The context to look for this resource.
261  * @param key      The unique key of the resource.
262  *
263  * @return         A pointer to the resource or @c NULL if not found.
264  */
265 coap_resource_t *coap_get_resource_from_key(coap_context_t *context,
266                                             coap_key_t key);
267 
268 /**
269  * Calculates the hash key for the resource requested by the Uri-Options of @p
270  * request. This function calls coap_hash() for every path segment.
271  *
272  * @param request The requesting pdu.
273  * @param key     The resulting hash is stored in @p key.
274  */
275 void coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key);
276 
277 /**
278  * @addtogroup observe
279  */
280 
281 /**
282  * Adds the specified peer as observer for @p resource. The subscription is
283  * identified by the given @p token. This function returns the registered
284  * subscription information if the @p observer has been added, or @c NULL on
285  * error.
286  *
287  * @param resource        The observed resource.
288  * @param local_interface The local network interface where the observer is
289  *                        attached to.
290  * @param observer        The remote peer that wants to received status updates.
291  * @param token           The token that identifies this subscription.
292  * @return                A pointer to the added/updated subscription
293  *                        information or @c NULL on error.
294  */
295 coap_subscription_t *coap_add_observer(coap_resource_t *resource,
296                                        const coap_endpoint_t *local_interface,
297                                        const coap_address_t *observer,
298                                        const str *token);
299 
300 /**
301  * Returns a subscription object for given @p peer.
302  *
303  * @param resource The observed resource.
304  * @param peer     The address to search for.
305  * @param token    The token that identifies this subscription or @c NULL for
306  *                 any token.
307  * @return         A valid subscription if exists or @c NULL otherwise.
308  */
309 coap_subscription_t *coap_find_observer(coap_resource_t *resource,
310                                         const coap_address_t *peer,
311                                         const str *token);
312 
313 /**
314  * Marks an observer as alive.
315  *
316  * @param context  The CoAP context to use.
317  * @param observer The transport address of the observer.
318  * @param token    The corresponding token that has been used for the
319  *                 subscription.
320  */
321 void coap_touch_observer(coap_context_t *context,
322                          const coap_address_t *observer,
323                          const str *token);
324 
325 /**
326  * Removes any subscription for @p observer from @p resource and releases the
327  * allocated storage. The result is @c 1 if an observation relationship with @p
328  * observer and @p token existed, @c 0 otherwise.
329  *
330  * @param resource The observed resource.
331  * @param observer The observer's address.
332  * @param token    The token that identifies this subscription or @c NULL for
333  *                 any token.
334  * @return         @c 1 if the observer has been deleted, @c 0 otherwise.
335  */
336 int coap_delete_observer(coap_resource_t *resource,
337                          const coap_address_t *observer,
338                          const str *token);
339 
340 /**
341  * Checks for all known resources, if they are dirty and notifies subscribed
342  * observers.
343  */
344 void coap_check_notify(coap_context_t *context);
345 
346 #ifdef COAP_RESOURCES_NOHASH
347 
348 #define RESOURCES_ADD(r, obj) \
349   LL_PREPEND((r), (obj))
350 
351 #define RESOURCES_DELETE(r, obj) \
352   LL_DELETE((r), (obj))
353 
354 #define RESOURCES_ITER(r,tmp) \
355   coap_resource_t *tmp;       \
356   LL_FOREACH((r), tmp)
357 
358 #define RESOURCES_FIND(r, k, res) {                         \
359     coap_resource_t *tmp;                                   \
360     (res) = tmp = NULL;                                     \
361     LL_FOREACH((r), tmp) {                                  \
362       if (memcmp((k), tmp->key, sizeof(coap_key_t)) == 0) { \
363         (res) = tmp;                                        \
364         break;                                              \
365       }                                                     \
366     }                                                       \
367   }
368 #else /* COAP_RESOURCES_NOHASH */
369 
370 #define RESOURCES_ADD(r, obj) \
371   HASH_ADD(hh, (r), key, sizeof(coap_key_t), (obj))
372 
373 #define RESOURCES_DELETE(r, obj) \
374   HASH_DELETE(hh, (r), (obj))
375 
376 #define RESOURCES_ITER(r,tmp)  \
377   coap_resource_t *tmp, *rtmp; \
378   HASH_ITER(hh, (r), tmp, rtmp)
379 
380 #define RESOURCES_FIND(r, k, res) {                     \
381     HASH_FIND(hh, (r), (k), sizeof(coap_key_t), (res)); \
382   }
383 
384 #endif /* COAP_RESOURCES_NOHASH */
385 
386 /** @} */
387 
388 coap_print_status_t coap_print_wellknown(coap_context_t *,
389                                          unsigned char *,
390                                          size_t *, size_t,
391                                          coap_opt_t *);
392 
393 void coap_handle_failed_notify(coap_context_t *,
394                                const coap_address_t *,
395                                const str *);
396 
397 #endif /* _COAP_RESOURCE_H_ */
398