• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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