Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
COAP_HANDLER(3)			libcoap	Manual		       COAP_HANDLER(3)

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

SYNOPSIS
       #include	<coap3/coap.h>

       void coap_register_request_handler(coap_resource_t *resource,
       coap_request_t method, coap_method_handler_t handler);

       void coap_register_response_handler(coap_context_t *context,
       coap_response_handler_t handler);

       void coap_register_nack_handler(coap_context_t *context,
       coap_nack_handler_t handler);

       void coap_register_ping_handler(coap_context_t *context,
       coap_ping_handler_t handler);

       void coap_register_pong_handler(coap_context_t *context,
       coap_pong_handler_t handler);

       void coap_register_event_handler(coap_context_t *context,
       coap_event_handler_t handler);

       For specific (D)TLS library support, link with -lcoap-3-notls,
       -lcoap-3-gnutls,	-lcoap-3-openssl, -lcoap-3-mbedtls, -lcoap-3-wolfssl
       or -lcoap-3-tinydtls. Otherwise,	link with -lcoap-3 to get the default
       (D)TLS library support.

DESCRIPTION
       This documents the different callback handlers that can optionally be
       invoked on receipt of a packet or when a	timeout	occurs.

FUNCTIONS
       Function: coap_register_request_handler()

       The coap_register_request_handler() is a	server side function that
       registers a callback handler handler that is called when	there is an
       incoming	request	PDU, there is a	URI match against the resource and
       there is	a method (e.g. PUT, POST etc.) match. method can be one	of the
       following.

	   COAP_REQUEST_GET
	   COAP_REQUEST_POST
	   COAP_REQUEST_PUT
	   COAP_REQUEST_DELETE
	   COAP_REQUEST_FETCH
	   COAP_REQUEST_PATCH
	   COAP_REQUEST_IPATCH

       The request handler function prototype is defined as:

	   /**
	    * Definition of message handler function
	    *
	    * @param resource The resource being requested.
	    * @param session The CoAP session.
	    * @param request The request PDU.
	    * @param query The query string for	the resource.
	    * @param response The pre-populated	response PDU.
	    */
	   typedef void	(*coap_method_handler_t)(coap_resource_t *resource,
						 coap_session_t	*session,
						 const coap_pdu_t *request,
						 const coap_string_t *query,
						 coap_pdu_t *response);

       In handler, data	from incoming_pdu can be abstracted as described in
       coap_pdu_access(3) for analysis and then	the handler updates
       response_pdu as appropriate as described	in coap_pdu_setup(3),
       including the response code. If response_pdu's code is not updated,
       then response_pdu will not get sent back	to the client.

       response_pdu is already pre-populated with the incoming_pdu's token and
       the PDU type. If	handler	is called as a result of an unsolicited
       Observe trigger,	then the Observe option	(and potentially Block2
       option) are also	added in. The response_pdu's response code should
       always be updated.

       This handler must not call coap_send(3) to send response_pdu.
       response_pdu gets sent on return	from handler, 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.

       NOTE: Any data associated with incoming_pdu is no longer	be available
       after exiting this function as incoming_pdu is deleted. In particular
       incoming_pdu's data must	not be used if calling
       coap_add_data_large_response(). However,	it is safe to use the data if
       coap_add_data() is used to update response_pdu where a copy of the data
       is taken.

       NOTE: A request callback	handler	can be called with a generic resource
       (i.e. set up using coap_resource_unknown_init2(3)), so
       coap_resource_get_uri_path(3) can be used to determine the URI in this
       case.

       Function: coap_register_response_handler()

       The coap_register_response_handler() is a client	side function that
       registers a request's response callback handler for traffic associated
       with the	context. The application can use this for handling any
       response	packets, including sending a RST packet	if this	response was
       unexpected. If handler is NULL, then the	handler	is de-registered.

       The response handler function prototype is defined as:

	   typedef enum	coap_response_t	{
	     COAP_RESPONSE_FAIL, /* Response not liked - send CoAP RST packet */
	     COAP_RESPONSE_OK	 /* Response is	fine */
	   } coap_response_t;

	   /**
	    * Response handler that is used as callback	in coap_context_t.
	    *
	    * @param session CoAP session.
	    * @param sent The PDU that was transmitted.
	    * @param received The PDU that was received.
	    * @param mid CoAP transaction ID.
	    *
	    * @return @c COAP_RESPONSE_OK if successful, else @c COAP_RESPONSE_FAIL which
	    *	      triggers sending a RST packet if the received PDU	is a CON or NON.
	    */
	   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 mid);

       In handler, data	from received (and optionally sent if set) can be
       abstracted as described in coap_pdu_access(3) for analysis.

       NOTE: sent 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 received
       Response.

       NOTE: sent (if not NULL)	may not	contain	all or any of the data used
       for the initial request if block	transfers are being used. For Block1
       requests, the complete data will	be lost	once the data has been
       successfully transmitted	as acknowledged	by the first response. For
       Block2 responses, sent gets re-used to request the next Block2 and so
       data information	is lost.

       NOTE: 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.

       Function: coap_register_nack_handler()

       The coap_register_nack_handler()	is a client side function that
       registers a request's negative response callback	handler	for traffic
       associated with the context. If handler is NULL,	then the handler is
       de-registered.

       The nack	handler	function prototype is defined as:

	   /**
	    * Negative Acknowedge handler that is used as callback in coap_context_t.
	    *
	    * @param session CoAP session.
	    * @param sent The PDU that was transmitted.
	    * @param reason The	reason for the NACK.
	    * @param mid CoAP message ID.
	    */
	   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);

       NACK reason can be one of the following

	   typedef enum	{
	     COAP_NACK_TOO_MANY_RETRIES,
	     COAP_NACK_NOT_DELIVERABLE,
	     COAP_NACK_RST,
	     COAP_NACK_TLS_FAILED,
	     COAP_NACK_ICMP_ISSUE,
	     COAP_NACK_BAD_RESPONSE,
	     COAP_NACK_TLS_LAYER_FAILED,
	     COAP_NACK_WS_LAYER_FAILED,
	     COAP_NACK_WS_FAILED
	   } coap_nack_reason_t;

       sent can	be NULL. mid can be used for determining which is the
       transmitting request.

       Function: coap_register_ping_handler()

       The coap_register_ping_handler()	function registers a callback handler
       for tracking receipt of CoAP ping traffic associated with the context.
       If handler is NULL, then	the handler is de-registered. It can be	used
       both client and server side.

       The ping	handler	function prototype is defined as:

	   /**
	    * Received Ping handler that is used as callback in	coap_context_t.
	    *
	    * @param session CoAP session.
	    * @param received The PDU that was received.
	    * @param mid CoAP message ID.
	    */
	   typedef void	(*coap_ping_handler_t)(coap_session_t *session,
					       const coap_pdu_t	*received,
					       const coap_mid_t	mid);

       Function: coap_register_pong_handler()

       The coap_register_pong_handler()	function registers a callback handler
       for tracking receipt of CoAP ping response traffic associated with the
       context.	If handler is NULL, then the handler is	de-registered. It can
       be used both client and server side.

       The pong	handler	function prototype is defined as:

	   /**
	    * Received Pong handler that is used as callback in	coap_context_t.
	    *
	    * @param session CoAP session.
	    * @param received The PDU that was received.
	    * @param mid CoAP message ID.
	    */
	   typedef void	(*coap_pong_handler_t)(coap_session_t *session,
					       const coap_pdu_t	*received,
					       const coap_mid_t	mid);

       Function: coap_register_event_handler()

       The coap_register_event_handler() function registers a callback handler
       for tracking network events associated with the context.	If handler is
       NULL, then the handler is de-registered.	It can be used both client and
       server side.

       The event handler function prototype is defined as:

	   /**
	    * Type for event handler functions that can	be registered with a CoAP
	    * context using the	function coap_set_event_handler().
	    *
	    * @param session The current CoAP session.
	    * @param event The event type that has occurred.
	    *
	    * @return @c 0 No further action required by libcoap
	    *	      @c 1 Depending from where	called,	libcoap	may take further
	    *		   action (reserved for	future use)
	    */
	   typedef int (*coap_event_handler_t)(coap_session_t *session,
					       const coap_event_t event);

       Events can be one of the	following

	   /**
	    * Scalar type to represent different events, e.g. DTLS events or
	    * retransmission timeouts.
	    */
	   typedef enum	{
	     /*
	      *	(D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS
	      */
	     /** Triggerred when (D)TLS	session	closed */
	     COAP_EVENT_DTLS_CLOSED	  = 0x0000,
	     /** Triggered when	(D)TLS session connected */
	     COAP_EVENT_DTLS_CONNECTED	  = 0x01DE,
	     /** Triggered when	(D)TLS session renegotiated */
	     COAP_EVENT_DTLS_RENEGOTIATE  = 0x01DF,
	     /** Triggered when	(D)TLS error occurs */
	     COAP_EVENT_DTLS_ERROR	  = 0x0200,

	     /*
	      *	TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS
	      */
	     /** Triggered when	TCP layer connects */
	     COAP_EVENT_TCP_CONNECTED	  = 0x1001,
	     /** Triggered when	TCP layer is closed */
	     COAP_EVENT_TCP_CLOSED	  = 0x1002,
	     /** Triggered when	TCP layer fails	for some reason	*/
	     COAP_EVENT_TCP_FAILED	  = 0x1003,

	     /*
	      *	CSM exchange events for	reliable protocols only
	      */
	     /** Triggered when	TCP layer completes exchange of	CSM information	*/
	     COAP_EVENT_SESSION_CONNECTED = 0x2001,
	     /** Triggered when	TCP layer closes following exchange of CSM information */
	     COAP_EVENT_SESSION_CLOSED	  = 0x2002,
	     /** Triggered when	TCP layer fails	 following exchange of CSM information */
	     COAP_EVENT_SESSION_FAILED	  = 0x2003,

	     /*
	      *	(Q-)Block errors
	      */
	     /** Triggered when	not all	of a large body	has been received */
	     COAP_EVENT_PARTIAL_BLOCK	  = 0x3001,
	     /** Triggered when	not all	of a large body	has been transmitted */
	     COAP_EVENT_XMIT_BLOCK_FAIL	  = 0x3002,

	     /*
	      *	Server session events
	      */
	     /**
	      *	Called in the CoAP IO loop if a	new *server-side* session is created due
	      *	to an incoming connection.
	      *
	      *	Note that the session might not	be a fully established connection yet,
	      *	it might also refer to,	e.g., a	DTLS session in	a handshake stage.
	      */
	     COAP_EVENT_SERVER_SESSION_NEW = 0x4001,

	     /**
	      *	Called in the CoAP IO loop if a	server session is deleted (e.g., due to
	      *	inactivity or because the maximum number of idle sessions was exceeded).
	      *
	      *	The session will still contain valid data when the event handler is
	      *	called.
	      */
	     COAP_EVENT_SERVER_SESSION_DEL = 0x4002,

	     /*
	      *	Message	receive	and transmit events
	      */
	     /** Triggered when	badly formatted	packet received	*/
	     COAP_EVENT_BAD_PACKET	   = 0x5001,
	     /** Triggered when	a message is retransmitted */
	     COAP_EVENT_MSG_RETRANSMITTED  = 0x5002,

	     /*
	      *	OSCORE events
	      */
	     /** Triggered when	there is an OSCORE decryption failure */
	     COAP_EVENT_OSCORE_DECRYPTION_FAILURE = 0x6001,
	     /** Triggered when	trying to use OSCORE to	decrypt, but it	is not enabled */
	     COAP_EVENT_OSCORE_NOT_ENABLED,
	     /** Triggered when	there is no OSCORE encrypted payload provided */
	     COAP_EVENT_OSCORE_NO_PROTECTED_PAYLOAD,
	     /** Triggered when	there is no OSCORE security definition found */
	     COAP_EVENT_OSCORE_NO_SECURITY,
	     /** Triggered when	there is an OSCORE internal error i.e malloc failed */
	     COAP_EVENT_OSCORE_INTERNAL_ERROR,
	     /** Triggered when	there is an OSCORE decode of OSCORE option failure */
	     COAP_EVENT_OSCORE_DECODE_ERROR,
	     /*
	      *	WebSocket events
	      */
	     /** Triggered when	there is an oversize WebSockets	packet */
	     COAP_EVENT_WS_PACKET_SIZE = 0x7001,
	     /** Triggered when	the WebSockets layer is	up */
	     COAP_EVENT_WS_CONNECTED,
	     /** Triggered when	the WebSockets layer is	closed */
	     COAP_EVENT_WS_CLOSED,
	     /*
	      *	Keepalive events
	      */
	     /** Triggered when	no response to a keep alive (ping) packet */
	     COAP_EVENT_KEEPALIVE_FAILURE = 0x8001,
	   } coap_event_t;

EXAMPLES
       GET Resource Callback Handler

	   #include <coap3/coap.h>

	   #include <stdio.h>

	   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 'now' 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);

	   }

       Packet Response Handler

	   #include <coap3/coap.h>

	   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\n");
	       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;

	   }

SEE ALSO
       coap_block(3), coap_observe(3), coap_pdu_access(3), coap_pdu_setup(3)
       and coap_resource(3)

FURTHER	INFORMATION
       See

       "RFC7252: The Constrained Application Protocol (CoAP)"

       for further information.

BUGS
       Please raise an issue on	GitHub at
       https://github.com/obgm/libcoap/issues to report	any bugs.

       Please raise a Pull Request at https://github.com/obgm/libcoap/pulls
       for any fixes.

AUTHORS
       The libcoap project <libcoap-developers@lists.sourceforge.net>

coap_handler 4.3.5		  11/03/2025		       COAP_HANDLER(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=coap_handler&sektion=3&manpath=FreeBSD+Ports+15.0>

home | help