---
name: "coap_register_event_handler"
section: "3"
platform: "linux"
package: "libcoap3t64"
version: "4.3.4-1.1+deb13u3"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/coap_handler"
---

# coap\_register\_event\_handler(3)

Work with CoAP handlers

Part of [coap\_handler(3)](/coap_handler/3.md).

## 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** 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:

```
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);
```

In *handler*, data from *incoming\_pdu* can be abstracted as described in [**coap\_pdu\_access**(3)](/coap_pdu_access/3.md) for analysis and then the *handler* updates *response\_pdu* as appropriate as described in [**coap\_pdu\_setup**(3)](/coap_pdu_setup/3.md), 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)](/coap_send/3.md) 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)](/coap_resource_unknown_init2/3.md)), so [**coap\_resource\_get\_uri\_path**(3)](/coap_resource_get_uri_path/3.md) 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;
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);
```

In *handler*, data from *received* (and optionally *sent* if set) can be abstracted as described in [**coap\_pdu\_access**(3)](/coap_pdu_access/3.md) 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:** 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:

```
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

```
COAP_NACK_TOO_MANY_RETRIES
COAP_NACK_NOT_DELIVERABLE
COAP_NACK_RST
COAP_NACK_TLS_FAILED
COAP_NACK_ICMP_ISSUE
COAP_NACK_BAD_RESPONSE
```

*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:

```
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:

```
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:

```
typedef void (*coap_event_handler_t)(coap_session_t *session,
                                     const coap_event_t event);
```

Events can be one of the following

```
/**
 * (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
```

## 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_block/3.md), [**coap\_observe**(3)](/coap_observe/3.md), [**coap\_pdu\_access**(3)](/coap_pdu_access/3.md), [**coap\_pdu\_setup**(3)](/coap_pdu_setup/3.md) and [**coap\_resource**(3)](/coap_resource/3.md)

## FURTHER INFORMATION

See

"RFC7252: The Constrained Application Protocol (CoAP)"

for further information.

## BUGS

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

## AUTHORS

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