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