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