'\" t
.\" Title: coap_handler
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot
.\" Date: 10/28/2023
.\" Manual: libcoap Manual
.\" Source: coap_handler 4.3.4
.\" Language: English
.\"
.TH "COAP_HANDLER" "3" "10/28/2023" "coap_handler 4\&.3\&.4" "libcoap Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
coap_handler, coap_register_request_handler, coap_register_response_handler, coap_register_nack_handler, coap_register_ping_handler, coap_register_pong_handler, coap_register_event_handler \- Work with CoAP handlers
.SH "SYNOPSIS"
.sp
\fB#include \fR
.sp
\fBvoid coap_register_request_handler(coap_resource_t *\fR\fB\fIresource\fR\fR\fB, coap_request_t \fR\fB\fImethod\fR\fR\fB, coap_method_handler_t \fR\fB\fIhandler\fR\fR\fB);\fR
.sp
\fBvoid coap_register_response_handler(coap_context_t *\fR\fB\fIcontext\fR\fR\fB, coap_response_handler_t \fR\fB\fIhandler\fR\fR\fB)\fR;
.sp
\fBvoid coap_register_nack_handler(coap_context_t *\fR\fB\fIcontext\fR\fR\fB, coap_nack_handler_t \fR\fB\fIhandler\fR\fR\fB)\fR;
.sp
\fBvoid coap_register_ping_handler(coap_context_t *\fR\fB\fIcontext\fR\fR\fB, coap_ping_handler_t \fR\fB\fIhandler\fR\fR\fB)\fR;
.sp
\fBvoid coap_register_pong_handler(coap_context_t *\fR\fB\fIcontext\fR\fR\fB, coap_pong_handler_t \fR\fB\fIhandler\fR\fR\fB)\fR;
.sp
\fBvoid coap_register_event_handler(coap_context_t *\fR\fB\fIcontext\fR\fR\fB, coap_event_handler_t \fR\fB\fIhandler\fR\fR\fB)\fR;
.sp
For specific (D)TLS library support, link with \fB\-lcoap\-3\-notls\fR, \fB\-lcoap\-3\-gnutls\fR, \fB\-lcoap\-3\-openssl\fR, \fB\-lcoap\-3\-mbedtls\fR or \fB\-lcoap\-3\-tinydtls\fR\&. Otherwise, link with \fB\-lcoap\-3\fR to get the default (D)TLS library support\&.
.SH "DESCRIPTION"
.sp
This documents the different callback handlers that can optionally be invoked on receipt of a packet or when a timeout occurs\&.
.SH "FUNCTIONS"
.sp
\fBFunction: coap_register_request_handler()\fR
.sp
The \fBcoap_register_request_handler\fR() is a server side function that registers a callback handler \fIhandler\fR that is called when there is an incoming request PDU, there is a URI match against the \fIresource\fR and there is a \fImethod\fR (e\&.g\&. PUT, POST etc\&.) match\&. \fImethod\fR can be one of the following\&.
.sp
.if n \{\
.RS 4
.\}
.nf
COAP_REQUEST_GET
COAP_REQUEST_POST
COAP_REQUEST_PUT
COAP_REQUEST_DELETE
COAP_REQUEST_FETCH
COAP_REQUEST_PATCH
COAP_REQUEST_IPATCH
.fi
.if n \{\
.RE
.\}
.sp
The request handler function prototype is defined as:
.sp
.if n \{\
.RS 4
.\}
.nf
typedef void (*coap_method_handler_t)(coap_resource_t *resource,
coap_session_t *session,
const coap_pdu_t *incoming_pdu,
const coap_string_t *query,
coap_pdu_t *response_pdu);
.fi
.if n \{\
.RE
.\}
.sp
In \fIhandler\fR, data from \fIincoming_pdu\fR can be abstracted as described in \fBcoap_pdu_access\fR(3) for analysis and then the \fIhandler\fR updates \fIresponse_pdu\fR as appropriate as described in \fBcoap_pdu_setup\fR(3), including the response code\&. If \fIresponse_pdu\fR\*(Aqs code is not updated, then \fIresponse_pdu\fR will not get sent back to the client\&.
.sp
\fIresponse_pdu\fR is already pre\-populated with the \fIincoming_pdu\fR\*(Aqs token and the PDU type\&. If \fIhandler\fR is called as a result of an unsolicited Observe trigger, then the Observe option (and potentially Block2 option) are also added in\&. The \fIresponse_pdu\fR\*(Aqs response code should always be updated\&.
.sp
This \fIhandler\fR must not call \fBcoap_send\fR(3) to send \fIresponse_pdu\fR\&. \fIresponse_pdu\fR gets sent on return from \fIhandler\fR, assuming the response code has been updated\&. If the response code was not updated, then an empty ACK packet will get sent for CON type requests or nothing for NON type requests\&.
.sp
\fBNOTE:\fR Any data associated with \fIincoming_pdu\fR is no longer be available after exiting this function as \fIincoming_pdu\fR is deleted\&. In particular \fIincoming_pdu\fR\*(Aqs data must not be used if calling \fBcoap_add_data_large_response\fR()\&. However, it is safe to use the data if \fBcoap_add_data\fR() is used to update \fIresponse_pdu\fR where a copy of the data is taken\&.
.sp
\fBNOTE:\fR A request callback handler can be called with a generic resource (i\&.e\&. set up using \fBcoap_resource_unknown_init2\fR(3)), so \fBcoap_resource_get_uri_path\fR(3) can be used to determine the URI in this case\&.
.sp
\fBFunction: coap_register_response_handler()\fR
.sp
The \fBcoap_register_response_handler\fR() is a client side function that registers a request\(cqs response callback \fIhandler\fR for traffic associated with the \fIcontext\fR\&. The application can use this for handling any response packets, including sending a RST packet if this response was unexpected\&. If \fIhandler\fR is NULL, then the handler is de\-registered\&.
.sp
The response handler function prototype is defined as:
.sp
.if n \{\
.RS 4
.\}
.nf
typedef enum coap_response_t {
COAP_RESPONSE_FAIL, /* Response not liked \- send CoAP RST packet */
COAP_RESPONSE_OK /* Response is fine */
} coap_response_t;
typedef coap_response_t (*coap_response_handler_t)(coap_session_t *session,
const coap_pdu_t *sent,
const coap_pdu_t *received,
const coap_mid_t id);
.fi
.if n \{\
.RE
.\}
.sp
In \fIhandler\fR, data from \fIreceived\fR (and optionally \fIsent\fR if set) can be abstracted as described in \fBcoap_pdu_access\fR(3) for analysis\&.
.sp
\fBNOTE:\fR \fIsent\fR will only be non NULL when the request PDU is Confirmable and this is an ACK or RST response to the request\&. In general, matching of Requests and Responses whould be done by generating unique Tokens for each Request and then matching up based on the Token in \fIreceived\fR Response\&.
.sp
\fBNOTE:\fR If the returned value is COAP_RESPONSE_FAIL, then a CoAP RST packet will get sent to the server by libcoap\&. The returned value of COAP_RESPONSE_OK indicates that all is OK\&.
.sp
\fBFunction: coap_register_nack_handler()\fR
.sp
The \fBcoap_register_nack_handler\fR() is a client side function that registers a request\(cqs negative response callback \fIhandler\fR for traffic associated with the \fIcontext\fR\&. If \fIhandler\fR is NULL, then the handler is de\-registered\&.
.sp
The nack handler function prototype is defined as:
.sp
.if n \{\
.RS 4
.\}
.nf
typedef void (*coap_nack_handler_t)(coap_session_t *session,
const coap_pdu_t *sent,
const coap_nack_reason_t reason,
const coap_mid_t mid);
.fi
.if n \{\
.RE
.\}
.sp
NACK \fIreason\fR can be one of the following
.sp
.if n \{\
.RS 4
.\}
.nf
COAP_NACK_TOO_MANY_RETRIES
COAP_NACK_NOT_DELIVERABLE
COAP_NACK_RST
COAP_NACK_TLS_FAILED
COAP_NACK_ICMP_ISSUE
COAP_NACK_BAD_RESPONSE
.fi
.if n \{\
.RE
.\}
.sp
\fIsent\fR can be NULL\&. \fImid\fR can be used for determining which is the transmitting request\&.
.sp
\fBFunction: coap_register_ping_handler()\fR
.sp
The \fBcoap_register_ping_handler\fR() function registers a callback \fIhandler\fR for tracking receipt of CoAP ping traffic associated with the \fIcontext\fR\&. If \fIhandler\fR is NULL, then the handler is de\-registered\&. It can be used both client and server side\&.
.sp
The ping handler function prototype is defined as:
.sp
.if n \{\
.RS 4
.\}
.nf
typedef void (*coap_ping_handler_t)(coap_session_t *session,
const coap_pdu_t *received,
const coap_mid_t mid);
.fi
.if n \{\
.RE
.\}
.sp
\fBFunction: coap_register_pong_handler()\fR
.sp
The \fBcoap_register_pong_handler\fR() function registers a callback \fIhandler\fR for tracking receipt of CoAP ping response traffic associated with the \fIcontext\fR\&. If \fIhandler\fR is NULL, then the handler is de\-registered\&. It can be used both client and server side\&.
.sp
The pong handler function prototype is defined as:
.sp
.if n \{\
.RS 4
.\}
.nf
typedef void (*coap_pong_handler_t)(coap_session_t *session,
const coap_pdu_t *received,
const coap_mid_t mid);
.fi
.if n \{\
.RE
.\}
.sp
\fBFunction: coap_register_event_handler()\fR
.sp
The \fBcoap_register_event_handler\fR() function registers a callback \fIhandler\fR for tracking network events associated with the \fIcontext\fR\&. If \fIhandler\fR is NULL, then the handler is de\-registered\&. It can be used both client and server side\&.
.sp
The event handler function prototype is defined as:
.sp
.if n \{\
.RS 4
.\}
.nf
typedef void (*coap_event_handler_t)(coap_session_t *session,
const coap_event_t event);
.fi
.if n \{\
.RE
.\}
.sp
Events can be one of the following
.sp
.if n \{\
.RS 4
.\}
.nf
/**
* (D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS
*/
COAP_EVENT_DTLS_CLOSED 0x0000
COAP_EVENT_DTLS_CONNECTED 0x01DE
COAP_EVENT_DTLS_RENEGOTIATE 0x01DF
COAP_EVENT_DTLS_ERROR 0x0200
/**
* TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS
*/
COAP_EVENT_TCP_CONNECTED 0x1001
COAP_EVENT_TCP_CLOSED 0x1002
COAP_EVENT_TCP_FAILED 0x1003
/**
* CSM exchange events for reliable protocols only
*/
COAP_EVENT_SESSION_CONNECTED 0x2001
COAP_EVENT_SESSION_CLOSED 0x2002
COAP_EVENT_SESSION_FAILED 0x2003
/**
* (Q\-)BLOCK events
*/
COAP_EVENT_PARTIAL_BLOCK 0x3001
COAP_EVENT_XMIT_BLOCK_FAIL 0x3002
/**
* Server session state management events
*/
COAP_EVENT_SERVER_SESSION_NEW 0x4001
COAP_EVENT_SERVER_SESSION_DEL 0x4002
/**
* Message receive and transmit events
*/
COAP_EVENT_BAD_PACKET 0x5001
COAP_EVENT_MSG_RETRANSMITTED 0x5002
/**
* OSCORE events
*/
COAP_EVENT_OSCORE_DECRYPTION_FAILURE 0x6001
COAP_EVENT_OSCORE_NOT_ENABLED 0x6002
COAP_EVENT_OSCORE_NO_PROTECTED_PAYLOAD 0x6003
COAP_EVENT_OSCORE_NO_SECURITY 0x6004
COAP_EVENT_OSCORE_INTERNAL_ERROR 0x6005
COAP_EVENT_OSCORE_DECODE_ERROR 0x6006
/**
* WebSocket events
*/
COAP_EVENT_WS_PACKET_SIZE 0x7001
COAP_EVENT_WS_CONNECTED 0x7002
COAP_EVENT_WS_CLOSE 0x7003
/**
* Keepalive events
*/
COAP_EVENT_KEEPALIVE_FAILURE 0x8001
.fi
.if n \{\
.RE
.\}
.SH "EXAMPLES"
.sp
\fBGET Resource Callback Handler\fR
.sp
.if n \{\
.RS 4
.\}
.nf
#include
#include
static void
hnd_get_time(coap_resource_t *resource, coap_session_t *session,
coap_pdu_t *request, coap_string_t *query, coap_pdu_t *response) {
unsigned char buf[40];
size_t len;
time_t now;
/* \&.\&.\&. Additional analysis code for resource, request pdu etc\&. \&.\&.\&. */
/* After analysis, generate a suitable response */
now = time(NULL);
if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) {
/* Output secs since Jan 1 1970 */
len = snprintf((char *)buf, sizeof(buf), "%lu", now);
}
else {
/* Output human\-readable time */
struct tm *tmp;
tmp = gmtime(&now);
if (!tmp) {
/* If \*(Aqnow\*(Aq is not valid */
coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
return;
}
len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp);
}
coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
/*
* Invoke coap_add_data_large_response() to do all the hard work\&.
*
* Define the format \- COAP_MEDIATYPE_TEXT_PLAIN \- to add in
* Define how long this response is valid for (secs) \- 1 \- to add in\&.
*
* Observe Option added internally if needed within the function
* Block2 Option added internally if output too large
* ETag Option added internally
*/
coap_add_data_large_response(resource, session, request, response,
query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0,
len,
buf, NULL, 0);
}
.fi
.if n \{\
.RE
.\}
.sp
\fBPacket Response Handler\fR
.sp
.if n \{\
.RS 4
.\}
.nf
#include
static int check_token(coap_pdu_t *received) {
/* Remove (void) definition if variable is used */
(void)received;
/* Code to validate the token is what we expect */
return 1;
}
static coap_response_t
response_handler(coap_context_t *ctx, coap_session_t *session,
coap_pdu_t *sent, coap_pdu_t *received, const coap_mid_t mid) {
/* Remove (void) definition if variable is used */
(void)ctx;
(void)session;
(void)mid;
coap_pdu_type_t rcv_type = coap_pdu_get_type(received);
coap_pdu_code_t rcv_code = coap_pdu_get_code(received);
/* check if this is a response to our original request */
if (!check_token(received)) {
/* drop if this was just some message, or send RST in case of notification */
if (!sent && (rcv_type == COAP_MESSAGE_CON ||
rcv_type == COAP_MESSAGE_NON)) {
/* Cause a CoAP RST to be sent */
return COAP_RESPONSE_FAIL;
}
return COAP_RESPONSE_OK;
}
if (rcv_type == COAP_MESSAGE_RST) {
coap_log_info("got RST\en");
return COAP_RESPONSE_OK;
}
/* Output the received data, if any */
if (COAP_RESPONSE_CLASS(rcv_code) == 2) {
/* Additional code to deal with the response */
}
return COAP_RESPONSE_OK;
}
.fi
.if n \{\
.RE
.\}
.SH "SEE ALSO"
.sp
\fBcoap_block\fR(3), \fBcoap_observe\fR(3), \fBcoap_pdu_access\fR(3), \fBcoap_pdu_setup\fR(3) and \fBcoap_resource\fR(3)
.SH "FURTHER INFORMATION"
.sp
See
.sp
"RFC7252: The Constrained Application Protocol (CoAP)"
.sp
for further information\&.
.SH "BUGS"
.sp
Please report bugs on the mailing list for libcoap: libcoap\-developers@lists\&.sourceforge\&.net or raise an issue on GitHub at https://github\&.com/obgm/libcoap/issues
.SH "AUTHORS"
.sp
The libcoap project