1// -*- mode:doc; -*- 2// vim: set syntax=asciidoc tw=0 3 4coap_handler(3) 5================= 6:doctype: manpage 7:man source: coap_handler 8:man version: @PACKAGE_VERSION@ 9:man manual: libcoap Manual 10 11NAME 12---- 13coap_handler, 14coap_register_request_handler, 15coap_register_response_handler, 16coap_register_nack_handler, 17coap_register_ping_handler, 18coap_register_pong_handler, 19coap_register_event_handler 20- Work with CoAP handlers 21 22SYNOPSIS 23-------- 24*#include <coap@LIBCOAP_API_VERSION@/coap.h>* 25 26*void coap_register_request_handler(coap_resource_t *_resource_, 27coap_request_t _method_, coap_method_handler_t _handler_);* 28 29*void coap_register_response_handler(coap_context_t *_context_, 30coap_response_handler_t _handler_)*; 31 32*void coap_register_nack_handler(coap_context_t *_context_, 33coap_nack_handler_t _handler_)*; 34 35*void coap_register_ping_handler(coap_context_t *_context_, 36coap_ping_handler_t _handler_)*; 37 38*void coap_register_pong_handler(coap_context_t *_context_, 39coap_pong_handler_t _handler_)*; 40 41*void coap_register_event_handler(coap_context_t *_context_, 42coap_event_handler_t _handler_)*; 43 44For specific (D)TLS library support, link with 45*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, 46*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* 47or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with 48*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. 49 50DESCRIPTION 51----------- 52 53This documents the different callback handlers that can optionally be invoked 54on receipt of a packet or when a timeout occurs. 55 56FUNCTIONS 57--------- 58 59*Function: coap_register_request_handler()* 60 61The *coap_register_request_handler*() is a server side function that registers 62a callback handler _handler_ that is called when there is an incoming request 63PDU, there is a URI match against the _resource_ and there is a _method_ 64(e.g. PUT, POST etc.) match. _method_ can be one of the following. 65---- 66COAP_REQUEST_GET 67COAP_REQUEST_POST 68COAP_REQUEST_PUT 69COAP_REQUEST_DELETE 70COAP_REQUEST_FETCH 71COAP_REQUEST_PATCH 72COAP_REQUEST_IPATCH 73---- 74 75The request handler function prototype is defined as: 76[source, c] 77---- 78typedef void (*coap_method_handler_t)(coap_resource_t *resource, 79 coap_session_t *session, 80 const coap_pdu_t *incoming_pdu, 81 const coap_string_t *query, 82 coap_pdu_t *response_pdu); 83---- 84 85In _handler_, data from _incoming_pdu_ can be abstracted as described in 86*coap_pdu_access*(3) for analysis and then the _handler_ updates 87_response_pdu_ as appropriate as described in *coap_pdu_setup*(3), 88including the response code. If _response_pdu_'s code is not updated, then 89_response_pdu_ will not get sent back to the client. 90 91_response_pdu_ is already 92pre-populated with the _incoming_pdu_'s token and the PDU type. If 93_handler_ is called as a result of an unsolicited Observe trigger, then the 94Observe option (and potentially Block2 option) are also added in. The 95_response_pdu_'s response code should always be updated. 96 97This _handler_ must not call *coap_send*(3) to send _response_pdu_. 98_response_pdu_ gets sent on return from _handler_, assuming the response 99code has been updated. If the response code was not updated, then an empty 100ACK packet will get sent for CON type requests or nothing for NON type 101requests. 102 103*NOTE:* Any data associated with _incoming_pdu_ is no longer be available after 104exiting this function as _incoming_pdu_ is deleted. In particular 105_incoming_pdu_'s data must not be used if calling 106*coap_add_data_large_response*(). However, it is safe to use the data if 107*coap_add_data*() is used to update _response_pdu_ where a copy of the data is 108taken. 109 110*NOTE:* A request callback handler can be called with a generic resource (i.e. 111set up using *coap_resource_unknown_init2*(3)), so 112*coap_resource_get_uri_path*(3) can be used to determine the URI in this case. 113 114*Function: coap_register_response_handler()* 115 116The *coap_register_response_handler*() is a client side function that registers 117a request's response callback _handler_ for traffic associated with the 118_context_. The application can use this for handling any response packets, 119including sending a RST packet if this response was unexpected. If _handler_ 120is NULL, then the handler is de-registered. 121 122The response handler function prototype is defined as: 123[source, c] 124---- 125typedef enum coap_response_t { 126 COAP_RESPONSE_FAIL, /* Response not liked - send CoAP RST packet */ 127 COAP_RESPONSE_OK /* Response is fine */ 128} coap_response_t; 129 130typedef coap_response_t (*coap_response_handler_t)(coap_session_t *session, 131 const coap_pdu_t *sent, 132 const coap_pdu_t *received, 133 const coap_mid_t id); 134---- 135 136In _handler_, data from _received_ (and optionally _sent_ if set) can be 137abstracted as described in *coap_pdu_access*(3) for analysis. 138 139*NOTE:* _sent_ will only be non NULL when the request PDU is Confirmable and 140this is an ACK or RST response to the request. In general, matching of 141Requests and Responses whould be done by generating unique Tokens for each 142Request and then matching up based on the Token in _received_ Response. 143 144*NOTE:* If the returned value is COAP_RESPONSE_FAIL, then a CoAP RST packet 145will get sent to the server by libcoap. The returned value of COAP_RESPONSE_OK 146indicates that all is OK. 147 148*Function: coap_register_nack_handler()* 149 150The *coap_register_nack_handler*() is a client side function that registers a 151request's negative response callback _handler_ for traffic associated with the 152_context_. If _handler_ is NULL, then the handler is de-registered. 153 154The nack handler function prototype is defined as: 155[source, c] 156---- 157typedef void (*coap_nack_handler_t)(coap_session_t *session, 158 const coap_pdu_t *sent, 159 const coap_nack_reason_t reason, 160 const coap_mid_t mid); 161---- 162NACK _reason_ can be one of the following 163---- 164COAP_NACK_TOO_MANY_RETRIES 165COAP_NACK_NOT_DELIVERABLE 166COAP_NACK_RST 167COAP_NACK_TLS_FAILED 168COAP_NACK_ICMP_ISSUE 169COAP_NACK_BAD_RESPONSE 170---- 171 172_sent_ can be NULL. _mid_ can be used for determining which is the transmitting 173request. 174 175*Function: coap_register_ping_handler()* 176 177The *coap_register_ping_handler*() function registers a callback _handler_ for 178tracking receipt of CoAP ping traffic associated with the _context_. If 179_handler_ is NULL, then the handler is de-registered. It can be used both 180client and server side. 181 182The ping handler function prototype is defined as: 183[source, c] 184---- 185typedef void (*coap_ping_handler_t)(coap_session_t *session, 186 const coap_pdu_t *received, 187 const coap_mid_t mid); 188---- 189 190*Function: coap_register_pong_handler()* 191 192The *coap_register_pong_handler*() function registers a callback _handler_ for 193tracking receipt of CoAP ping response traffic associated with the _context_. 194If _handler_ is NULL, then the handler is de-registered. It can be used both 195client and server side. 196 197The pong handler function prototype is defined as: 198[source, c] 199---- 200typedef void (*coap_pong_handler_t)(coap_session_t *session, 201 const coap_pdu_t *received, 202 const coap_mid_t mid); 203---- 204 205*Function: coap_register_event_handler()* 206 207The *coap_register_event_handler*() function registers a callback _handler_ 208for tracking network events associated with the _context_. If _handler_ is 209NULL, then the handler is de-registered. It can be used both client and server 210side. 211 212The event handler function prototype is defined as: 213[source, c] 214---- 215typedef void (*coap_event_handler_t)(coap_session_t *session, 216 const coap_event_t event); 217---- 218Events can be one of the following 219---- 220/** 221 * (D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS 222 */ 223COAP_EVENT_DTLS_CLOSED 0x0000 224COAP_EVENT_DTLS_CONNECTED 0x01DE 225COAP_EVENT_DTLS_RENEGOTIATE 0x01DF 226COAP_EVENT_DTLS_ERROR 0x0200 227/** 228 * TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS 229 */ 230COAP_EVENT_TCP_CONNECTED 0x1001 231COAP_EVENT_TCP_CLOSED 0x1002 232COAP_EVENT_TCP_FAILED 0x1003 233/** 234 * CSM exchange events for reliable protocols only 235 */ 236COAP_EVENT_SESSION_CONNECTED 0x2001 237COAP_EVENT_SESSION_CLOSED 0x2002 238COAP_EVENT_SESSION_FAILED 0x2003 239/** 240 * (Q-)BLOCK events 241 */ 242COAP_EVENT_PARTIAL_BLOCK 0x3001 243COAP_EVENT_XMIT_BLOCK_FAIL 0x3002 244/** 245 * Server session state management events 246 */ 247COAP_EVENT_SERVER_SESSION_NEW 0x4001 248COAP_EVENT_SERVER_SESSION_DEL 0x4002 249/** 250 * Message receive and transmit events 251 */ 252COAP_EVENT_BAD_PACKET 0x5001 253COAP_EVENT_MSG_RETRANSMITTED 0x5002 254/** 255 * OSCORE events 256 */ 257COAP_EVENT_OSCORE_DECRYPTION_FAILURE 0x6001 258COAP_EVENT_OSCORE_NOT_ENABLED 0x6002 259COAP_EVENT_OSCORE_NO_PROTECTED_PAYLOAD 0x6003 260COAP_EVENT_OSCORE_NO_SECURITY 0x6004 261COAP_EVENT_OSCORE_INTERNAL_ERROR 0x6005 262COAP_EVENT_OSCORE_DECODE_ERROR 0x6006 263/** 264 * WebSocket events 265 */ 266COAP_EVENT_WS_PACKET_SIZE 0x7001 267COAP_EVENT_WS_CONNECTED 0x7002 268COAP_EVENT_WS_CLOSE 0x7003 269/** 270 * Keepalive events 271 */ 272COAP_EVENT_KEEPALIVE_FAILURE 0x8001 273---- 274 275EXAMPLES 276-------- 277*GET Resource Callback Handler* 278 279[source, c] 280---- 281#include <coap@LIBCOAP_API_VERSION@/coap.h> 282 283#include <stdio.h> 284 285static void 286hnd_get_time(coap_resource_t *resource, coap_session_t *session, 287coap_pdu_t *request, coap_string_t *query, coap_pdu_t *response) { 288 289 unsigned char buf[40]; 290 size_t len; 291 time_t now; 292 293 /* ... Additional analysis code for resource, request pdu etc. ... */ 294 295 /* After analysis, generate a suitable response */ 296 297 now = time(NULL); 298 299 if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) { 300 /* Output secs since Jan 1 1970 */ 301 len = snprintf((char *)buf, sizeof(buf), "%lu", now); 302 } 303 else { 304 /* Output human-readable time */ 305 struct tm *tmp; 306 tmp = gmtime(&now); 307 if (!tmp) { 308 /* If 'now' is not valid */ 309 coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); 310 return; 311 } 312 len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp); 313 } 314 coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 315 /* 316 * Invoke coap_add_data_large_response() to do all the hard work. 317 * 318 * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in 319 * Define how long this response is valid for (secs) - 1 - to add in. 320 * 321 * Observe Option added internally if needed within the function 322 * Block2 Option added internally if output too large 323 * ETag Option added internally 324 */ 325 coap_add_data_large_response(resource, session, request, response, 326 query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0, 327 len, 328 buf, NULL, 0); 329 330} 331---- 332*Packet Response Handler* 333 334[source, c] 335---- 336#include <coap@LIBCOAP_API_VERSION@/coap.h> 337 338static int check_token(coap_pdu_t *received) { 339 /* Remove (void) definition if variable is used */ 340 (void)received; 341 342 /* Code to validate the token is what we expect */ 343 344 return 1; 345} 346 347static coap_response_t 348response_handler(coap_context_t *ctx, coap_session_t *session, 349coap_pdu_t *sent, coap_pdu_t *received, const coap_mid_t mid) { 350 /* Remove (void) definition if variable is used */ 351 (void)ctx; 352 (void)session; 353 (void)mid; 354 coap_pdu_type_t rcv_type = coap_pdu_get_type(received); 355 coap_pdu_code_t rcv_code = coap_pdu_get_code(received); 356 357 /* check if this is a response to our original request */ 358 if (!check_token(received)) { 359 /* drop if this was just some message, or send RST in case of notification */ 360 if (!sent && (rcv_type == COAP_MESSAGE_CON || 361 rcv_type == COAP_MESSAGE_NON)) { 362 /* Cause a CoAP RST to be sent */ 363 return COAP_RESPONSE_FAIL; 364 } 365 return COAP_RESPONSE_OK; 366 } 367 368 if (rcv_type == COAP_MESSAGE_RST) { 369 coap_log_info("got RST\n"); 370 return COAP_RESPONSE_OK; 371 } 372 373 /* Output the received data, if any */ 374 if (COAP_RESPONSE_CLASS(rcv_code) == 2) { 375 /* Additional code to deal with the response */ 376 377 } 378 return COAP_RESPONSE_OK; 379 380} 381---- 382 383SEE ALSO 384-------- 385*coap_block*(3), *coap_observe*(3), *coap_pdu_access*(3), *coap_pdu_setup*(3) 386and *coap_resource*(3) 387 388FURTHER INFORMATION 389------------------- 390See 391 392"https://rfc-editor.org/rfc/rfc7252[RFC7252: The Constrained Application Protocol (CoAP)]" 393 394for further information. 395 396BUGS 397---- 398Please report bugs on the mailing list for libcoap: 399libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at 400https://github.com/obgm/libcoap/issues 401 402AUTHORS 403------- 404The libcoap project <libcoap-developers@lists.sourceforge.net> 405