• 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_unknown_init2,
17coap_resource_proxy_uri_init,
18coap_resource_proxy_uri_init2,
19coap_add_resource,
20coap_delete_resource,
21coap_resource_set_mode,
22coap_resource_set_userdata,
23coap_resource_get_userdata,
24coap_resource_release_userdata_handler,
25coap_resource_get_uri_path
26- Work with CoAP resources
27
28SYNOPSIS
29--------
30*#include <coap@LIBCOAP_API_VERSION@/coap.h>*
31
32*coap_resource_t *coap_resource_init(coap_str_const_t *_uri_path_,
33int _flags_);*
34
35*coap_resource_t *coap_resource_unknown_init(coap_method_handler_t
36_put_handler_);*
37
38*coap_resource_t *coap_resource_unknown_init2(coap_method_handler_t
39_put_handler_, int _flags_);*
40
41*coap_resource_t *coap_resource_proxy_uri_init(coap_method_handler_t
42_proxy_handler_, size_t _host_name_count_, const char *_host_name_list_[]);*
43
44*coap_resource_t *coap_resource_proxy_uri_init2(coap_method_handler_t
45_proxy_handler_, size_t _host_name_count_, const char *_host_name_list_[],
46int _flags_);*
47
48*void coap_add_resource(coap_context_t *_context_,
49coap_resource_t *_resource_);*
50
51*int coap_delete_resource(coap_context_t *_context_,
52coap_resource_t *_resource_);*
53
54*void coap_resource_set_mode(coap_resource_t *_resource_, int _mode_);*
55
56*void coap_resource_set_userdata(coap_resource_t *_resource_, void *_data_);*
57
58*void *coap_resource_get_userdata(coap_resource_t *_resource_);*
59
60*void coap_resource_release_userdata_handler(coap_context_t *_context_,
61coap_resource_release_userdata_handler_t _callback_);*
62
63*coap_str_const_t *coap_resource_get_uri_path(coap_resource_t *_resource_);*
64
65For specific (D)TLS library support, link with
66*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*,
67*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls*
68or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*.   Otherwise, link with
69*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support.
70
71DESCRIPTION
72-----------
73CoAP Resources on a CoAP Server need to be created, updated and deleted as
74appropriate. The URI in
75the request packet defines the resource to work with, with possibly the Query
76or data in the request referring to a sub-resource.
77
78When resources are configured on the CoAP server, the URI to match against
79in the request packet is specified.
80
81Callback Handlers are then added to the resource to handle the different
82request methods. See *coap_register_request_handler*(3) for further information.
83
84Adding Attributes allows textual information to be added to the resource
85which can then be reported back to any client doing a "GET .well-known/core"
86request. See *coap_add_attr*(3) for further information.
87
88If an incoming packet request matches a resource's URI and Method, then
89the appropriate callback resource handler is invoked to process the packet
90which should then update a suitable response packet for returning back to the
91requester.
92
93There is support for handling incoming packets where the URI is unknown (no
94specific resource has been created).
95This could, for example, happen when a PUT request is trying to create a new
96resource. It is the responsibility of the unknown resource callback handler
97to either create a new resource for the URI or just manage things separately.
98
99CoAP Observe (https://rfc-editor.org/rfc/rfc7641[RFC7641]) is not supported
100for unknown resources, so a new
101resource with GET handler must be created by the unknown resource callback
102handle matching the URI which then can be Observable.
103
104There is support for handling incoming proxy based requests using the Proxy-Uri
105or Proxy-Scheme options.
106
107FUNCTIONS
108---------
109
110*Function: coap_resource_init()*
111
112The *coap_resource_init*() function returns a newly created _resource_ of
113type _coap_resource_t_ * .  _uri_path_ specifies the uri string path to match
114against.  Normally there is no need for the leading '/' - e.g. just
115"full/path/for/resource".
116_flags_ can be zero or more of the following definitions or'ed together.
117
118[horizontal]
119*COAP_RESOURCE_FLAGS_NOTIFY_NON*::
120Set the notification message type to non-confirmable for any trigggered
121"observe" responses with type set to confirmable every 5 packets as required by
122"https://rfc-editor.org/rfc/rfc7641#section-4.5[RFC7641 4.5. Transmission]".
123See *coap_observe*(3). +
124*NOTE:* This flag is ignored if COAP_RESOURCE_FLAGS_NOTIFY_CON is set.
125
126*COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS*::
127Set the notification message type to always non-confirmable for any trigggered
128"observe" responses. This should only be used if a upper layer protocol
129requires it. See *coap_observe*(3). +
130*NOTE:* This flag is ignored if COAP_RESOURCE_FLAGS_NOTIFY_CON is set.
131
132*COAP_RESOURCE_FLAGS_NOTIFY_CON*::
133Set the notification message type to confirmable for any trigggered
134"observe" responses. See *coap_observe*(3). +
135*NOTE:* COAP_RESOURCE_FLAGS_NOTIFY_NON is assumed if
136COAP_RESOURCE_FLAGS_NOTIFY_CON is not set.
137
138*COAP_RESOURCE_FLAGS_RELEASE_URI*::
139Free off the coap_str_const_t for _uri_path_ when the _resource_ is deleted.
140
141*COAP_RESOURCE_FLAGS_FORCE_SINGLE_BODY*::
142Force all large traffic to this resource to be presented as a single body
143to the request handler.
144
145*COAP_RESOURCE_FLAGS_OSCORE_ONLY*::
146Define this resource as an OSCORE enabled access only.
147
148*NOTE:* The following flags are only tested against if
149*coap_mcast_per_resource*() has been called.  If *coap_mcast_per_resource*()
150has not been called, then all resources have multicast support, libcoap adds
151in random delays to the responses, and 4.xx / 5.xx responses are dropped.
152
153*NOTE:* The pseudo resource for ".well-known/core" always has multicast
154support enabled and is not configurable.
155
156[horizontal]
157*COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT*::
158This resource has support for multicast requests.
159
160*COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_DELAYS*::
161Disable libcoap library from adding in delays to multicast requests before
162sending the response back to the client.  It is then the responsibility of
163the app to delay the responses for multicast requests. See
164"https://rfc-editor.org/rfc/rfc7252#section-8.2[RFC7252 8.2. Request/Response
165Layer]".
166 However, the pseudo resource for ".well-known/core" always has multicast
167support enabled.
168
169*COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_05*::
170Enable libcoap library suppression of 205 multicast responses that are empty
171(overridden by https://rfc-editor.org/rfc/rfc7967[RFC7967] No-Response option)
172for multicast requests.
173
174*COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_XX*::
175Enable libcoap library suppressing 2.xx multicast responses (overridden by
176https://rfc-editor.org/rfc/rfc7967[RFC7967] No-Response option) for multicast
177requests.
178
179*COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_SUPPRESS_4_XX*::
180Disable libcoap library suppressing 4.xx multicast responses (overridden by
181https://rfc-editor.org/rfc/rfc7967[RFC7967] No-Response option) for multicast
182requests.
183
184*COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_SUPPRESS_5_XX*::
185Disable libcoap library suppressing 5.xx multicast responses (overridden by
186https://rfc-editor.org/rfc/rfc7967[RFC7967] No-Response option) for multicast
187requests.
188
189*NOTE:* _uri_path_, if not 7 bit readable ASCII, binary bytes must be hex
190encoded according to the rules defined in
191"https://rfc-editor.org/rfc/rfc3986#section-2.1[RFC3986 2.1. Percent-Encoding]".
192
193*Function: coap_resource_unknown_init()*
194
195The *coap_resource_unknown_init*() function returns a newly created _resource_
196of type _coap_resource_t_ *. _put_handler_ is automatically added to the
197_resource_ to handle PUT requests to resources that are unknown. Additional
198handlers can be added to this resource if required.
199
200*Function: coap_resource_unknown_init2()*
201
202The *coap_resource_unknown_init2*() function returns a newly created _resource_
203of type _coap_resource_t_ *. _put_handler_ is automatically added to the
204_resource_ to handle PUT requests to resources that are unknown. Additional
205handlers can be added to this resource if required. _flags_ can be zero or
206more of the COAP_RESOURCE_FLAGS MCAST definitions.
207
208*Function: coap_resource_proxy_uri_init()*
209
210The *coap_resource_proxy_uri_init*() function returns a newly created
211_resource_ of type _coap_resource_t_ *. _proxy_handler_ is automatically added
212to the _resource_ to handle PUT/POST/GET etc. requests that use the Proxy-Uri
213option.  There is no need to add explicit request type handlers. One or more
214names by which the proxy is known by (IP address, DNS name etc.) must be
215supplied in the array defined by _host_name_list_[] which has a count of
216_host_name_count_.  This is used to check whether the current endpoint is
217the proxy target address, or the request has to be passed on to an upstream
218server.
219
220*Function: coap_resource_proxy_uri_init2()*
221
222The *coap_resource_proxy_uri_init2*() function returns a newly created
223_resource_ of type _coap_resource_t_ *. _proxy_handler_ is automatically added
224to the _resource_ to handle PUT/POST/GET etc. requests that use the Proxy-Uri
225option.  There is no need to add explicit request type handlers. One or more
226names by which the proxy is known by (IP address, DNS name etc.) must be
227supplied in the array defined by _host_name_list_[] which has a count of
228_host_name_count_.  This is used to check whether the current endpoint is
229the proxy target address, or the request has to be passed on to an upstream
230server. _flags_ can be zero or more COAP_RESOURCE_FLAGS MCAST definitions.
231
232*Function: coap_add_resource()*
233
234The *coap_add_resource*() function registers the given _resource_ with the
235_context_. The _resource_ must have been created by *coap_resource_init*(),
236*coap_resource_unknown_init*(), *coap_resource_unknown_init2*(),
237*coap_resource_proxy_uri_init*() or *coap_resource_proxy_uri_init2*(). The
238storage allocated for the _resource_ will be released by
239*coap_delete_resource*().
240
241As the _uri_path_ of the resource has to be unique across all of the resources
242associated with a _context_, *coap_add_resource*() will delete any previous
243_resource_ with the same _uri_path_ before adding in the new _resource_.
244
245*Function: coap_delete_resource()*
246
247The *coap_delete_resource*() function deletes the resource identified by
248_resource_. The _context_ parameter is ignored. The storage allocated for that
249_resource_ is freed, along with any attributes associated with the _resource_.
250
251*Function: coap_resource_set_mode()*
252
253The *coap_resource_set_mode*() changes the unsolicited notification message
254type of _resource_ to the given _mode_ which must be one of
255COAP_RESOURCE_FLAGS_NOTIFY_NON, COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS or
256COAP_RESOURCE_FLAGS_NOTIFY_CON.
257
258*Function: coap_resource_set_userdata()*
259
260The *coap_resource_set_userdata*() function allows a pointer to user _data_
261to be associated with a _resource_ that can accessed in any callback that
262includes _resource_ as a parameter.
263
264*NOTE:* _data_ must point to a static, or allocated, block of memory.
265
266*Function: coap_resource_get_userdata()*
267
268The *coap_resource_get_userdata*() function obtains the user data pointer
269from the _resource_ that had previously been set up by
270*coap_resource_set_userdata*().
271
272*Function: coap_resource_release_userdata_handler()*
273
274The *coap_resource_release_userdata_handler*() function defines the _context_
275wide _callback_ handler to call to release the allocated user data that has
276been added to the resource using *coap_resource_set_userdata*() when the
277resource is deleted. _callback_ can be NULL (which is the default) if nothing
278needs to be freed off.
279
280*Function: coap_resource_get_uri_path()*
281
282The *coap_resource_get_uri_path*() function is used to obtain the UriPath of
283the _resource_ definion.
284
285RETURN VALUES
286-------------
287*coap_resource_init*(), *coap_resource_unknown_init*(),
288*coap_resource_unknown_init2*(), *coap_resource_proxy_uri_init*() and
289*coap_resource_proxy_uri_init2*() return a newly created resource
290or NULL if there is a malloc failure.
291
292*coap_delete_resource*() returns 0 on failure (_resource_ not
293found), 1 on success.
294
295*coap_resource_get_userdata*() returns the value previously set
296by the *coap_resource_set_userdata*() function or NULL.
297
298*coap_resource_get_uri_path*() returns the uri_path or NULL if
299there was a failure.
300
301EXAMPLES
302--------
303*Fixed Resources Set Up*
304
305[source, c]
306----
307#include <coap@LIBCOAP_API_VERSION@/coap.h>
308
309#define INDEX "This is an example server using libcoap\n"
310
311static void
312hnd_get_index(coap_resource_t *resource, coap_session_t *session,
313const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
314  unsigned char buf[3];
315  /* Remove (void) definition if variable is used */
316  (void)resource;
317  (void)session;
318  (void)request;
319  (void)query;
320
321  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
322
323  coap_add_option(response,
324                  COAP_OPTION_CONTENT_TYPE,
325                  coap_encode_var_safe(buf, sizeof(buf),
326                                       COAP_MEDIATYPE_TEXT_PLAIN),
327                  buf);
328
329  coap_add_option(response,
330                  COAP_OPTION_MAXAGE,
331                  coap_encode_var_safe(buf, sizeof(buf), 0x2ffff), buf);
332
333  coap_add_data(response, strlen(INDEX), (const uint8_t *)INDEX);
334
335  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
336}
337
338static void
339hnd_delete_time(coap_resource_t *resource, coap_session_t *session,
340const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
341  /* Remove (void) definition if variable is used */
342  (void)resource;
343  (void)session;
344  (void)request;
345  (void)query;
346
347  /* .. code .. */
348
349  coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED);
350}
351
352static void
353hnd_get_time(coap_resource_t *resource, coap_session_t *session,
354const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
355  /* Remove (void) definition if variable is used */
356  (void)resource;
357  (void)session;
358  (void)request;
359  (void)query;
360  (void)response;
361
362  /* .. code .. */
363
364  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
365}
366
367static void
368hnd_put_time(coap_resource_t *resource, coap_session_t *session,
369const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
370  /* Remove (void) definition if variable is used */
371  (void)resource;
372  (void)session;
373  (void)request;
374  (void)query;
375  (void)response;
376
377  /* .. code .. */
378
379  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED);
380}
381
382static void
383init_resources(coap_context_t *ctx) {
384
385  coap_resource_t *r;
386
387  /* Create a resource to return general information */
388  r = coap_resource_init(NULL, 0);
389  coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_index);
390
391  /* Document resource for '.well-known/core' request */
392  coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
393  coap_add_attr(r, coap_make_str_const("title"),
394                coap_make_str_const("\"General Info\""), 0);
395
396  coap_add_resource(ctx, r);
397
398  /* Create a resource to return return or update time */
399  r = coap_resource_init(coap_make_str_const("time"),
400                         COAP_RESOURCE_FLAGS_NOTIFY_CON);
401  coap_resource_set_get_observable(r, 1);
402  coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_time);
403  coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_time);
404  coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_time);
405
406  /* Document resource for 'time' request */
407  coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
408  coap_add_attr(r, coap_make_str_const("title"),
409                coap_make_str_const("\"Internal Clock\""), 0);
410  coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"secs\""),
411                0);
412  coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""),
413                0);
414
415  coap_add_resource(ctx, r);
416
417}
418----
419
420*Dynamic Resources Set Up*
421
422[source, c]
423----
424#include <coap@LIBCOAP_API_VERSION@/coap.h>
425
426/* Regular DELETE handler - used by resources created by the
427 * Unknown Resource PUT handler */
428
429static void
430hnd_delete(coap_resource_t *resource, coap_session_t *session,
431const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
432  /* Remove (void) definition if variable is used */
433  (void)session;
434  (void)request;
435  (void)query;
436  (void)response;
437
438  /* .. code .. */
439
440  /* Dynamic resource no longer required - delete it */
441  coap_delete_resource(NULL, resource);
442
443  coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED);
444}
445
446/* Regular GET handler - used by resources created by the
447 * Unknown Resource PUT handler */
448
449static void
450hnd_get(coap_resource_t *resource, coap_session_t *session,
451const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
452
453  coap_str_const_t *get_uri_path;
454
455  /* Remove (void) definition if variable is used */
456  (void)resource;
457  (void)session;
458  (void)request;
459  (void)query;
460
461  /*
462   * Get the specific resource being requested to determine what the response is
463   * The uri_path string is a const pointer
464   */
465
466  get_uri_path = coap_resource_get_uri_path(resource);
467
468  /* .. code .. */
469
470  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
471}
472
473/* Regular PUT handler - used by resources created by the
474 * Unknown Resource PUT handler */
475
476static void
477hnd_put(coap_resource_t *resource, coap_session_t *session,
478const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
479  /* Remove (void) definition if variable is used */
480  (void)resource;
481  (void)session;
482  (void)query;
483
484  coap_string_t *put_uri_path;
485  size_t length;
486  const uint8_t *data;
487  size_t offset;
488  size_t total;
489  int new_resource = 0;
490
491  /* get the uri_path */
492  put_uri_path = coap_get_uri_path(request);
493  if (!put_uri_path) {
494    coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
495    return;
496  }
497  coap_get_data_large(request, &length, &data, &offset, &total);
498
499  /* .. code .. */
500
501  /* Need to do this as coap_get_uri_path() created it */
502  coap_delete_string(put_uri_path);
503
504  if (length + offset < total)
505    coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTINUE);
506  else if (new_resource)
507    coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED);
508  else
509    coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED);
510}
511
512static int
513check_url_fn(coap_string_t *uri_path, uint8_t code) {
514  /* Remove (void) definition if variable is used */
515  (void)uri_path;
516  (void)code;
517
518  /* Code to determine whether the uri is valid or not */
519
520  return 1;
521}
522
523/* Unknown Resource PUT handler */
524
525static void
526hnd_put_unknown(coap_resource_t *resource, coap_session_t *session,
527const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
528  /* Remove (void) definition if variable is used */
529  (void)resource;
530  coap_pdu_code_t req_code = coap_pdu_get_code(request);
531
532  coap_resource_t *r;
533  coap_string_t *uri_path;
534
535  /* get the uri_path - which will get used by coap_resource_init() */
536  uri_path = coap_get_uri_path(request);
537  if (!uri_path) {
538    coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
539    return;
540  }
541
542  /* Check if new URI Path is valid */
543  if (!check_url_fn (uri_path, req_code)) {
544    coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
545    coap_delete_string(uri_path);
546    return;
547  }
548
549  /*
550   * Create a resource to handle the new URI
551   * uri_path will get deleted when the resource is removed
552   */
553  r = coap_resource_init((coap_str_const_t*)uri_path,
554        COAP_RESOURCE_FLAGS_RELEASE_URI | COAP_RESOURCE_FLAGS_NOTIFY_NON);
555  coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put);
556  coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete);
557  /* We possibly want to Observe the GETs */
558  coap_resource_set_get_observable(r, 1);
559  coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get);
560  coap_add_resource(coap_session_get_context(session), r);
561
562  /* Do the PUT for this first call */
563  hnd_put(r, session, request, query, response);
564
565  return;
566
567}
568
569/* Initialize single Unknown Resource PUT handler */
570
571static void
572init_resources(coap_context_t *ctx) {
573
574  coap_resource_t *r;
575
576  /* Create a resource to handle PUTs to unknown URIs */
577  r = coap_resource_unknown_init2(hnd_put_unknown, 0);
578  /*
579   * Additional handlers can be added - for example
580   *  coap_register_request_handler(r, COAP_REQUEST_POST, hnd_post_unknown);
581   *  coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_unknown);
582   *  coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_unknown);
583   */
584  coap_add_resource(ctx, r);
585
586}
587----
588
589SEE ALSO
590--------
591*coap_attribute*(3), *coap_context*(3), *coap_handler*(3) and *coap_observe*(3)
592
593FURTHER INFORMATION
594-------------------
595See
596
597"https://rfc-editor.org/rfc/rfc7252[RFC7252: The Constrained Application Protocol (CoAP)]"
598
599"https://rfc-editor.org/rfc/rfc3986[RFC3986: Uniform Resource Identifier (URI): Generic Syntax]"
600
601for further information.
602
603BUGS
604----
605Please report bugs on the mailing list for libcoap:
606libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
607https://github.com/obgm/libcoap/issues
608
609AUTHORS
610-------
611The libcoap project <libcoap-developers@lists.sourceforge.net>
612