1COAP_HANDLER(3)                 libcoap Manual                 COAP_HANDLER(3)
2
3
4

NAME

6       coap_handler, coap_register_request_handler,
7       coap_register_response_handler, coap_register_nack_handler,
8       coap_register_ping_handler, coap_register_pong_handler,
9       coap_register_event_handler - Work with CoAP handlers
10

SYNOPSIS

12       #include <coap3/coap.h>
13
14       void coap_register_request_handler(coap_resource_t *resource,
15       coap_request_t method, coap_method_handler_t handler);
16
17       void coap_register_response_handler(coap_context_t *context,
18       coap_response_handler_t handler);
19
20       void coap_register_nack_handler(coap_context_t *context,
21       coap_nack_handler_t handler);
22
23       void coap_register_ping_handler(coap_context_t *context,
24       coap_ping_handler_t handler);
25
26       void coap_register_pong_handler(coap_context_t *context,
27       coap_pong_handler_t handler);
28
29       void coap_register_event_handler(coap_context_t *context,
30       coap_event_handler_t handler);
31
32       For specific (D)TLS library support, link with -lcoap-3-notls,
33       -lcoap-3-gnutls, -lcoap-3-openssl, -lcoap-3-mbedtls or
34       -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 to get the default
35       (D)TLS library support.
36

DESCRIPTION

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

FUNCTIONS

42       Function: coap_register_request_handler()
43
44       The coap_register_request_handler() is a server side function that
45       registers a callback handler handler that is called when there is an
46       incoming request PDU, there is a URI match against the resource and
47       there is a method (e.g. PUT, POST etc.) match. method can be one of the
48       following.
49
50           COAP_REQUEST_GET
51           COAP_REQUEST_POST
52           COAP_REQUEST_PUT
53           COAP_REQUEST_DELETE
54           COAP_REQUEST_FETCH
55           COAP_REQUEST_PATCH
56           COAP_REQUEST_IPATCH
57
58       The request handler function prototype is defined as:
59
60           typedef void (*coap_method_handler_t)(coap_resource_t *resource,
61                                                 coap_session_t *session,
62                                                 const coap_pdu_t *incoming_pdu,
63                                                 const coap_string_t *query,
64                                                 coap_pdu_t *response_pdu);
65
66       In handler, data from incoming_pdu can be abstracted as described in
67       coap_pdu_access(3) for analysis and then the handler updates
68       response_pdu as appropriate as described in coap_pdu_setup(3),
69       including the response code. If response_pdu's code is not updated,
70       then response_pdu will not get sent back to the client.
71
72       response_pdu is already pre-populated with the incoming_pdu's token and
73       the PDU type. If handler is called as a result of an unsolicited
74       Observe trigger, then the Observe option (and potentially Block2
75       option) are also added in. The response_pdu's response code should
76       always be updated.
77
78       This handler must not call coap_send(3) to send response_pdu.
79       response_pdu gets sent on return from handler, assuming the response
80       code has been updated. If the response code was not updated, then an
81       empty ACK packet will get sent for CON type requests or nothing for NON
82       type requests.
83
84       NOTE: Any data associated with incoming_pdu is no longer be available
85       after exiting this function as incoming_pdu is deleted. In particular
86       incoming_pdu's data must not be used if calling
87       coap_add_data_large_response(). However, it is safe to use the data if
88       coap_add_data() is used to update response_pdu where a copy of the data
89       is taken.
90
91       NOTE: A request callback handler can be called with a generic resource
92       (i.e. set up using coap_resource_unknown_init2(3)), so
93       coap_resource_get_uri_path(3) can be used to determine the URI in this
94       case.
95
96       Function: coap_register_response_handler()
97
98       The coap_register_response_handler() is a client side function that
99       registers a request’s response callback handler for traffic associated
100       with the context. The application can use this for handling any
101       response packets, including sending a RST packet if this response was
102       unexpected. If handler is NULL, then the handler is de-registered.
103
104       The response handler function prototype is defined as:
105
106           typedef enum coap_response_t {
107             COAP_RESPONSE_FAIL, /* Response not liked - send CoAP RST packet */
108             COAP_RESPONSE_OK    /* Response is fine */
109           } coap_response_t;
110
111           typedef coap_response_t (*coap_response_handler_t)(coap_session_t *session,
112                                                              const coap_pdu_t *sent,
113                                                              const coap_pdu_t *received,
114                                                              const coap_mid_t id);
115
116       In handler, data from received (and optionally sent if set) can be
117       abstracted as described in coap_pdu_access(3) for analysis.
118
119       NOTE: sent will only be non NULL when the request PDU is Confirmable
120       and this is an ACK or RST response to the request. In general, matching
121       of Requests and Responses whould be done by generating unique Tokens
122       for each Request and then matching up based on the Token in received
123       Response.
124
125       NOTE: If the returned value is COAP_RESPONSE_FAIL, then a CoAP RST
126       packet will get sent to the server by libcoap. The returned value of
127       COAP_RESPONSE_OK indicates that all is OK.
128
129       Function: coap_register_nack_handler()
130
131       The coap_register_nack_handler() is a client side function that
132       registers a request’s negative response callback handler for traffic
133       associated with the context. If handler is NULL, then the handler is
134       de-registered.
135
136       The nack handler function prototype is defined as:
137
138           typedef void (*coap_nack_handler_t)(coap_session_t *session,
139                                               const coap_pdu_t *sent,
140                                               const coap_nack_reason_t reason,
141                                               const coap_mid_t mid);
142
143       NACK reason can be one of the following
144
145           COAP_NACK_TOO_MANY_RETRIES
146           COAP_NACK_NOT_DELIVERABLE
147           COAP_NACK_RST
148           COAP_NACK_TLS_FAILED
149           COAP_NACK_ICMP_ISSUE
150           COAP_NACK_BAD_RESPONSE
151
152       sent can be NULL. mid can be used for determining which is the
153       transmitting request.
154
155       Function: coap_register_ping_handler()
156
157       The coap_register_ping_handler() function registers a callback handler
158       for tracking receipt of CoAP ping traffic associated with the context.
159       If handler is NULL, then the handler is de-registered. It can be used
160       both client and server side.
161
162       The ping handler function prototype is defined as:
163
164           typedef void (*coap_ping_handler_t)(coap_session_t *session,
165                                               const coap_pdu_t *received,
166                                               const coap_mid_t mid);
167
168       Function: coap_register_pong_handler()
169
170       The coap_register_pong_handler() function registers a callback handler
171       for tracking receipt of CoAP ping response traffic associated with the
172       context. If handler is NULL, then the handler is de-registered. It can
173       be used both client and server side.
174
175       The pong handler function prototype is defined as:
176
177           typedef void (*coap_pong_handler_t)(coap_session_t *session,
178                                               const coap_pdu_t *received,
179                                               const coap_mid_t mid);
180
181       Function: coap_register_event_handler()
182
183       The coap_register_event_handler() function registers a callback handler
184       for tracking network events associated with the context. If handler is
185       NULL, then the handler is de-registered. It can be used both client and
186       server side.
187
188       The event handler function prototype is defined as:
189
190           typedef void (*coap_event_handler_t)(coap_session_t *session,
191                                                const coap_event_t event);
192
193       Events can be one of the following
194
195           /**
196            * (D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS
197            */
198           COAP_EVENT_DTLS_CLOSED        0x0000
199           COAP_EVENT_DTLS_CONNECTED     0x01DE
200           COAP_EVENT_DTLS_RENEGOTIATE   0x01DF
201           COAP_EVENT_DTLS_ERROR         0x0200
202           /**
203            * TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS
204            */
205           COAP_EVENT_TCP_CONNECTED      0x1001
206           COAP_EVENT_TCP_CLOSED         0x1002
207           COAP_EVENT_TCP_FAILED         0x1003
208           /**
209            * CSM exchange events for reliable protocols only
210            */
211           COAP_EVENT_SESSION_CONNECTED  0x2001
212           COAP_EVENT_SESSION_CLOSED     0x2002
213           COAP_EVENT_SESSION_FAILED     0x2003
214           /**
215            * (Q-)BLOCK events
216            */
217           COAP_EVENT_PARTIAL_BLOCK      0x3001
218           COAP_EVENT_XMIT_BLOCK_FAIL    0x3002
219           /**
220            * Server session state management events
221            */
222           COAP_EVENT_SERVER_SESSION_NEW 0x4001
223           COAP_EVENT_SERVER_SESSION_DEL 0x4002
224           /**
225            * Message receive and transmit events
226            */
227           COAP_EVENT_BAD_PACKET         0x5001
228           COAP_EVENT_MSG_RETRANSMITTED  0x5002
229           /**
230            * OSCORE events
231            */
232           COAP_EVENT_OSCORE_DECRYPTION_FAILURE   0x6001
233           COAP_EVENT_OSCORE_NOT_ENABLED          0x6002
234           COAP_EVENT_OSCORE_NO_PROTECTED_PAYLOAD 0x6003
235           COAP_EVENT_OSCORE_NO_SECURITY          0x6004
236           COAP_EVENT_OSCORE_INTERNAL_ERROR       0x6005
237           COAP_EVENT_OSCORE_DECODE_ERROR         0x6006
238           /**
239            * WebSocket events
240            */
241           COAP_EVENT_WS_PACKET_SIZE     0x7001
242           COAP_EVENT_WS_CONNECTED       0x7002
243           COAP_EVENT_WS_CLOSE           0x7003
244           /**
245            * Keepalive events
246            */
247           COAP_EVENT_KEEPALIVE_FAILURE  0x8001
248

EXAMPLES

250       GET Resource Callback Handler
251
252           #include <coap3/coap.h>
253
254           #include <stdio.h>
255
256           static void
257           hnd_get_time(coap_resource_t *resource, coap_session_t *session,
258           coap_pdu_t *request, coap_string_t *query, coap_pdu_t *response) {
259
260             unsigned char buf[40];
261             size_t len;
262             time_t now;
263
264             /* ... Additional analysis code for resource, request pdu etc.  ... */
265
266             /* After analysis, generate a suitable response */
267
268             now = time(NULL);
269
270             if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) {
271               /* Output secs since Jan 1 1970 */
272               len = snprintf((char *)buf, sizeof(buf), "%lu", now);
273             }
274             else {
275               /* Output human-readable time */
276               struct tm *tmp;
277               tmp = gmtime(&now);
278               if (!tmp) {
279                 /* If 'now' is not valid */
280                 coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
281                 return;
282               }
283               len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp);
284             }
285             coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
286             /*
287              * Invoke coap_add_data_large_response() to do all the hard work.
288              *
289              * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in
290              * Define how long this response is valid for (secs) - 1 - to add in.
291              *
292              * Observe Option added internally if needed within the function
293              * Block2 Option added internally if output too large
294              * ETag Option added internally
295              */
296             coap_add_data_large_response(resource, session, request, response,
297                                          query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0,
298                                          len,
299                                          buf, NULL, 0);
300
301           }
302
303       Packet Response Handler
304
305           #include <coap3/coap.h>
306
307           static int check_token(coap_pdu_t *received) {
308             /* Remove (void) definition if variable is used */
309             (void)received;
310
311             /* Code to validate the token is what we expect */
312
313             return 1;
314           }
315
316           static coap_response_t
317           response_handler(coap_context_t *ctx, coap_session_t *session,
318           coap_pdu_t *sent, coap_pdu_t *received, const coap_mid_t mid) {
319             /* Remove (void) definition if variable is used */
320             (void)ctx;
321             (void)session;
322             (void)mid;
323             coap_pdu_type_t rcv_type = coap_pdu_get_type(received);
324             coap_pdu_code_t rcv_code = coap_pdu_get_code(received);
325
326             /* check if this is a response to our original request */
327             if (!check_token(received)) {
328               /* drop if this was just some message, or send RST in case of notification */
329               if (!sent && (rcv_type == COAP_MESSAGE_CON ||
330                             rcv_type == COAP_MESSAGE_NON)) {
331                 /* Cause a CoAP RST to be sent */
332                 return COAP_RESPONSE_FAIL;
333               }
334               return COAP_RESPONSE_OK;
335             }
336
337             if (rcv_type == COAP_MESSAGE_RST) {
338               coap_log_info("got RST\n");
339               return COAP_RESPONSE_OK;
340             }
341
342             /* Output the received data, if any */
343             if (COAP_RESPONSE_CLASS(rcv_code) == 2) {
344               /* Additional code to deal with the response */
345
346             }
347             return COAP_RESPONSE_OK;
348
349           }
350

SEE ALSO

352       coap_block(3), coap_observe(3), coap_pdu_access(3), coap_pdu_setup(3)
353       and coap_resource(3)
354

FURTHER INFORMATION

356       See
357
358       "RFC7252: The Constrained Application Protocol (CoAP)"
359
360       for further information.
361

BUGS

363       Please report bugs on the mailing list for libcoap:
364       libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
365       https://github.com/obgm/libcoap/issues
366

AUTHORS

368       The libcoap project <libcoap-developers@lists.sourceforge.net>
369
370
371
372coap_handler 4.3.4                10/09/2023                   COAP_HANDLER(3)
Impressum