• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// -*- mode:doc; -*-
2// vim: set syntax=asciidoc,tw=0:
3
4coap_resource(3)
5=================
6:doctype: manpage
7:man source:   coap_resource
8:man version:  @PACKAGE_VERSION@
9:man manual:   libcoap Manual
10
11NAME
12----
13coap_resource,
14coap_resource_init,
15coap_resource_unknown_init,
16coap_resource_proxy_uri_init,
17coap_add_resource,
18coap_delete_resource,
19coap_resource_set_mode,
20coap_resource_set_userdata,
21coap_resource_get_userdata,
22coap_resource_release_userdata_handler,
23coap_resource_get_uri_path
24- Work with CoAP resources
25
26SYNOPSIS
27--------
28*#include <coap@LIBCOAP_API_VERSION@/coap.h>*
29
30*coap_resource_t *coap_resource_init(coap_str_const_t *_uri_path_,
31int _flags_);*
32
33*coap_resource_t *coap_resource_unknown_init(coap_method_handler_t
34_put_handler_);*
35
36*coap_resource_t *coap_resource_proxy_uri_init(coap_method_handler_t
37_proxy_handler_, size_t _host_name_count_, const char *_host_name_list_[]);*
38
39*void coap_add_resource(coap_context_t *_context_,
40coap_resource_t *_resource_);*
41
42*int coap_delete_resource(coap_context_t *_context_,
43coap_resource_t *_resource_);*
44
45*void coap_resource_set_mode(coap_resource_t *_resource_, int _mode_);*
46
47*void coap_resource_set_userdata(coap_resource_t *_resource_, void *_data_);*
48
49*void *coap_resource_get_userdata(coap_resource_t *_resource_);*
50
51*void coap_resource_release_userdata_handler(coap_context_t *_context_,
52coap_resource_release_userdata_handler_t _callback_);*
53
54*coap_str_const_t *coap_resource_get_uri_path(coap_resource_t *_resource_);*
55
56For specific (D)TLS library support, link with
57*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*,
58*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls*
59or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*.   Otherwise, link with
60*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support.
61
62DESCRIPTION
63-----------
64CoAP Resources on a CoAP Server need to be created and updated etc. The URI in
65the request packet defines the resource to work with, with possibly the Query
66referring to a sub-resource.
67
68When resources are configured on the CoAP server, the URI to match against
69in the request packet is specified.
70
71Callback Handlers are then added to the resource to handle the different
72request methods.
73
74Adding Attributes allows textual information to be added to the resource
75which can then be reported back to any client doing a "GET .well-known/core"
76request.
77
78If an incoming packet request matches a resource's URI and Method, then
79the appropriate callback resource handler is invoked to process the packet
80which then should update a suitable response packet for sending back to the
81requester.
82
83There is support for handling incoming packets where the URI is unknown.
84This could, for example, happen when a PUT request is trying to create a new
85resource. It is the responsibility of the unknown resource callback handler
86to either create a new resource for the URI or just manage things separately.
87
88CoAP Observe (RFC 7641) is not supported for unknown resources, so a new
89resource with GET handler must be created by the unknown resource callback
90handle matching the URI which then can be Observable.
91
92The *coap_resource_init*() function returns a newly created _resource_ of
93type _coap_resource_t_ * .  _uri_path_ specifies the uri string path to match
94against.  _flags_ is used to define whether the
95_resource_ is of type Confirmable Message or Non-Confirmable Message for
96any "observe" responses.  See *coap_observe*(3).
97_flags_ can be one of the following definitions or'ed together.
98
99[horizontal]
100*COAP_RESOURCE_FLAGS_NOTIFY_NON*::
101Set the notification message type to non-confirmable for any trigggered
102"observe" responses with type set to confirmable every 5 packets as required by
103RFC7641 section-4.5.
104
105*COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS*::
106Set the notification message type to always non-confirmable for any trigggered
107"observe" responses. This should only be used if a upper layer protocol
108requires it.
109
110*COAP_RESOURCE_FLAGS_NOTIFY_CON*::
111Set the notification message type to confirmable for any trigggered
112"observe" responses.
113
114*COAP_RESOURCE_FLAGS_RELEASE_URI*::
115Free off the coap_str_const_t for _uri_path_ when the _resource_ is deleted.
116
117*NOTE:* _uri_path_, if not 7 bit readable ASCII, binary bytes must be hex
118encoded according to the rules defined in RFC3968 Section 2.1.
119
120The *coap_resource_unknown_init*() function returns a newly created _resource_
121of type _coap_resource_t_ *. _put_handler_ is automatically added to the
122_resource_ to handle PUT requests to resources that are unknown. Additional
123handlers can be added to this resource if required.
124
125The *coap_resource_proxy_uri_init*() function returns a newly created
126_resource_ of type _coap_resource_t_ *. _proxy_handler_ is automatically added
127to the _resource_ to handle PUT/POST/GET etc. requests that use the Proxy-Uri:
128option.  There is no need to add explicit request type handlers. One or more
129names by which the proxy is known by (IP address, DNS name etc.) must be
130supplied in the array defined by _host_name_list_[] which has a count of
131_host_name_count_.  This is used to check whether the current endpoint is
132the proxy target address.
133
134The *coap_add_resource*() function registers the given _resource_ with the
135_context_. The _resource_ must have been created by *coap_resource_init*(),
136*coap_resource_unknown_init*() or *coap_resource_proxy_uri_init*(). The storage
137allocated for the _resource_ will be released by *coap_delete_resource*().
138
139As the _uri_path_ of the resource has to be unique across all of the resources
140associated with a _context_, *coap_add_resource*() (or
141*coap_add_resource_release*()) will delete any previous
142_resource_ with the same _uri_path_ before adding in the new _resource_.
143
144The *coap_delete_resource*() function deletes a _resource_ identified by
145_resource_ from _context_. The storage allocated for that _resource_ is freed,
146along with any attrigutes associated with the _resource_.
147
148The *coap_resource_set_mode*() changes the notification message type of
149_resource_ to the given _mode_ which must be one of
150COAP_RESOURCE_FLAGS_NOTIFY_NON, COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS or
151COAP_RESOURCE_FLAGS_NOTIFY_CON.
152
153The *coap_resource_set_userdata*() function allows a pointer to user _data_
154to be associated with a _resource_ that can accessed in any callback that
155includes _resource_ as a parameter.
156
157*NOTE:* _data_ must point to a static, or allocated, block of memory.
158
159The *coap_resource_get_userdata*() function obtains the user data pointer
160from the _resource_ that had previously been set up by
161*coap_resource_set_userdata*().
162
163The *coap_resource_release_userdata_handler*() function defines the _context_
164wide _callback_ handler to call to release the allocated user data that has
165been added to the resource using *coap_resource_set_userdata*() when the
166resource is deleted. _callback_ can be NULL (which is the default) if nothing
167needs to be freed off.
168
169The *coap_resource_get_uri_path*() function is used to obtain the UriPath of
170the _resource_ definion.
171
172RETURN VALUES
173-------------
174The *coap_resource_init*(), *coap_resource_unknown_init*() and
175*coap_resource_proxy_uri_init*() functions return a newly created resource
176or NULL if there is a malloc failure.
177
178The *coap_delete_resource*() function return 0 on failure (_resource_ not
179found), 1 on success.
180
181The *coap_resource_get_userdata*() function returns the value previously set
182by the *coap_resource_set_userdata*() function or NULL.
183
184The *coap_resource_get_uri_path*() function returns the uri_path or NULL if
185there was a failure.
186
187EXAMPLES
188--------
189*Fixed Resources Set Up*
190
191[source, c]
192----
193#include <coap@LIBCOAP_API_VERSION@/coap.h>
194
195#define INDEX "This is an example server using libcoap\n"
196
197static void
198hnd_get_index(coap_resource_t *resource, coap_session_t *session,
199const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
200  unsigned char buf[3];
201  /* Remove (void) definition if variable is used */
202  (void)resource;
203  (void)session;
204  (void)request;
205  (void)query;
206
207  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
208
209  coap_add_option(response,
210                  COAP_OPTION_CONTENT_TYPE,
211                  coap_encode_var_safe(buf, sizeof(buf),
212                                       COAP_MEDIATYPE_TEXT_PLAIN),
213                  buf);
214
215  coap_add_option(response,
216                  COAP_OPTION_MAXAGE,
217                  coap_encode_var_safe(buf, sizeof(buf), 0x2ffff), buf);
218
219  coap_add_data(response, strlen(INDEX), (const uint8_t *)INDEX);
220
221  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
222}
223
224static void
225hnd_delete_time(coap_resource_t *resource, coap_session_t *session,
226const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
227  /* Remove (void) definition if variable is used */
228  (void)resource;
229  (void)session;
230  (void)request;
231  (void)query;
232
233  /* .. code .. */
234
235  coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED);
236}
237
238static void
239hnd_get_time(coap_resource_t *resource, coap_session_t *session,
240const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
241  /* Remove (void) definition if variable is used */
242  (void)resource;
243  (void)session;
244  (void)request;
245  (void)query;
246  (void)response;
247
248  /* .. code .. */
249
250  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
251}
252
253static void
254hnd_put_time(coap_resource_t *resource, coap_session_t *session,
255const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
256  /* Remove (void) definition if variable is used */
257  (void)resource;
258  (void)session;
259  (void)request;
260  (void)query;
261  (void)response;
262
263  /* .. code .. */
264
265  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED);
266}
267
268static void
269init_resources(coap_context_t *ctx) {
270
271  coap_resource_t *r;
272
273  /* Create a resource to return general information */
274  r = coap_resource_init(NULL, 0);
275  coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index);
276
277  /* Document resource for '.well-known/core' request */
278  coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
279  coap_add_attr(r, coap_make_str_const("title"),
280                coap_make_str_const("\"General Info\""), 0);
281
282  coap_add_resource(ctx, r);
283
284  /* Create a resource to return return or update time */
285  r = coap_resource_init(coap_make_str_const("time"),
286                         COAP_RESOURCE_FLAGS_NOTIFY_CON);
287  coap_resource_set_get_observable(r, 1);
288  coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time);
289  coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time);
290  coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time);
291
292  /* Document resource for 'time' request */
293  coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
294  coap_add_attr(r, coap_make_str_const("title"),
295                coap_make_str_const("\"Internal Clock\""), 0);
296  coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"secs\""),
297                0);
298  coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""),
299                0);
300
301  coap_add_resource(ctx, r);
302
303}
304----
305
306*Dynamic Resources Set Up*
307
308[source, c]
309----
310#include <coap@LIBCOAP_API_VERSION@/coap.h>
311
312/* Regular DELETE handler - used by resources created by the
313 * Unknown Resource PUT handler */
314
315static void
316hnd_delete(coap_resource_t *resource, coap_session_t *session,
317const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
318  /* Remove (void) definition if variable is used */
319  (void)session;
320  (void)request;
321  (void)query;
322  (void)response;
323
324  /* .. code .. */
325
326  /* Dynamic resource no longer required - delete it */
327  coap_delete_resource(coap_session_get_context(session), resource);
328
329  coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED);
330}
331
332/* Regular GET handler - used by resources created by the
333 * Unknown Resource PUT handler */
334
335static void
336hnd_get(coap_resource_t *resource, coap_session_t *session,
337const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
338
339  coap_str_const_t *get_uri_path;
340  /* Remove (void) definition if variable is used */
341  (void)resource;
342  (void)session;
343  (void)request;
344  (void)query;
345  (void)response;
346
347  /*
348   * request will be NULL if an Observe triggered request, so the uri_path,
349   * if needed, must be abstracted from the resource.
350   * The uri_path string is a const pointer
351   */
352
353  get_uri_path = coap_resource_get_uri_path(resource);
354
355  /* .. code .. */
356
357  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
358}
359
360/* Regular PUT handler - used by resources created by the
361 * Unknown Resource PUT handler */
362
363static void
364hnd_put(coap_resource_t *resource, coap_session_t *session,
365const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
366  /* Remove (void) definition if variable is used */
367  (void)resource;
368  (void)session;
369  (void)query;
370
371  coap_string_t *put_uri_path;
372  size_t length;
373  const uint8_t *data;
374  size_t offset;
375  size_t total;
376  int new_resource = 0;
377
378  /* get the uri_path */
379  put_uri_path = coap_get_uri_path(request);
380  if (!put_uri_path) {
381    coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
382    return;
383  }
384  coap_get_data_large(request, &length, &data, &offset, &total);
385
386  /* .. code .. */
387
388  /* Need to do this as coap_get_uri_path() created it */
389  coap_delete_string(put_uri_path);
390
391  if (length + offset < total)
392    coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTINUE);
393  else if (new_resource)
394    coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED);
395  else
396    coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED);
397}
398
399static int
400check_url_fn(coap_string_t *uri_path, uint8_t code) {
401  /* Remove (void) definition if variable is used */
402  (void)uri_path;
403  (void)code;
404
405  /* Code to determine whether the uri is valid or not */
406
407  return 1;
408}
409
410/* Unknown Resource PUT handler */
411
412static void
413hnd_unknown_put(coap_resource_t *resource, coap_session_t *session,
414const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
415  /* Remove (void) definition if variable is used */
416  (void)resource;
417  coap_pdu_code_t req_code = coap_pdu_get_code(request);
418
419  coap_resource_t *r;
420  coap_string_t *uri_path;
421
422  /* get the uri_path - which will get used by coap_resource_init() */
423  uri_path = coap_get_uri_path(request);
424  if (!uri_path) {
425    coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
426    return;
427  }
428
429  /* Check if new URI Path is valid */
430  if (!check_url_fn (uri_path, req_code)) {
431    coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
432    coap_delete_string(uri_path);
433    return;
434  }
435
436  /*
437   * Create a resource to handle the new URI
438   * uri_path will get deleted when the resource is removed
439   */
440  r = coap_resource_init((coap_str_const_t*)uri_path,
441        COAP_RESOURCE_FLAGS_RELEASE_URI | COAP_RESOURCE_FLAGS_NOTIFY_NON);
442  coap_register_handler(r, COAP_REQUEST_PUT, hnd_put);
443  coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete);
444  /* We possibly want to Observe the GETs */
445  coap_resource_set_get_observable(r, 1);
446  coap_register_handler(r, COAP_REQUEST_GET, hnd_get);
447  coap_add_resource(coap_session_get_context(session), r);
448
449  /* Do the PUT for this first call */
450  hnd_put(r, session, request, query, response);
451
452  return;
453
454}
455
456/* Initialize single Unknown Resource PUT handler */
457
458static void
459init_resources(coap_context_t *ctx) {
460
461  coap_resource_t *r;
462
463  /* Create a resource to handle PUTs to unknown URIs */
464  r = coap_resource_unknown_init(hnd_unknown_put);
465  /*
466   * Additional handlers can be added - for example
467   *  coap_register_handler(r, COAP_REQUEST_POST, hnd_post_unknown);
468   *  coap_register_handler(r, COAP_REQUEST_GET, hnd_get_unknown);
469   *  coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_unknown);
470   */
471  coap_add_resource(ctx, r);
472
473}
474----
475
476SEE ALSO
477--------
478*coap_attribute*(3), *coap_context*(3), *coap_observe*(3) and *coap_handler*(3)
479
480FURTHER INFORMATION
481-------------------
482See "RFC7252: The Constrained Application Protocol (CoAP)" for further
483information.
484
485BUGS
486----
487Please report bugs on the mailing list for libcoap:
488libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
489https://github.com/obgm/libcoap/issues
490
491AUTHORS
492-------
493The libcoap project <libcoap-developers@lists.sourceforge.net>
494