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_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_handler(coap_resource_t *_resource_, coap_request_t
27_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
53The *coap_register_handler*() function registers a callback handler _handler_
54that is called when there is a URI match against the _resource_ and there is
55a _method_ (e.g. PUT, POST etc.) match. _method_ can be one of the following.
56----
57COAP_REQUEST_GET
58COAP_REQUEST_POST
59COAP_REQUEST_PUT
60COAP_REQUEST_DELETE
61COAP_REQUEST_FETCH
62COAP_REQUEST_PATCH
63COAP_REQUEST_IPATCH
64----
65
66The method handler function prototype is defined as:
67[source, c]
68----
69typedef void (*coap_method_handler_t)(coap_resource_t *resource,
70                                      coap_session_t *session,
71                                      const coap_pdu_t *incoming_pdu,
72                                      const coap_string_t *query,
73                                      coap_pdu_t *response_pdu);
74----
75
76*NOTE:* _incoming_pdu_ will be NULL for the GET Handler if this is an
77internally generated Observe Response.  *coap_resource_get_uri_path*()
78can be used to determine the URI in this case.
79
80*NOTE:* Any data associated with _incoming_pdu_ is no longer be available after
81exiting this function as _incoming_pdu_ is deleted, unless *coap_add_data*()
82was used to update _response_pdu_ where a copy of the data is taken.  In
83particular _incoming_pdu_'s data must not be used if calling
84*coap_add_data_large_response*().
85
86The *coap_register_response_handler*() function defines a request's response
87_handler_ for traffic associated with the _context_.  The application can use
88this for handling any response packets, including sending a RST packet if this
89response was unexpected.  If _handler_ is NULL, then the handler is
90de-registered.
91
92The response handler function prototype is defined as:
93[source, c]
94----
95typedef enum coap_response_t {
96  COAP_RESPONSE_FAIL, /* Response not liked - send CoAP RST packet */
97  COAP_RESPONSE_OK    /* Response is fine */
98} coap_response_t;
99
100typedef coap_response_t (*coap_response_handler_t)(coap_session_t *session,
101                                                   const coap_pdu_t *sent,
102                                                   const coap_pdu_t *received,
103                                                   const coap_mid_t id);
104----
105
106*NOTE:* _sent_ will only be non NULL when the request PDU is Confirmable and
107this is an ACK or RST response to the request.  In general, matching of
108Requests and Responses whould be done by generating unique Tokens for each Request
109and then matching up based on the Token in _received_ Response.
110
111*NOTE:* If the returned value is COAP_RESPONSE_FAIL, then a CoAP RST packet will get
112sent to the server by libcoap.  The returned value of COAP_RESPONSE_OK indicates
113that all is OK.
114
115The *coap_register_nack_handler*() function defines a request's negative
116response _handler_ for traffic associated with the _context_.
117If _handler_ is NULL, then the handler is de-registered.
118
119The nack handler function prototype is defined as:
120[source, c]
121----
122typedef void (*coap_nack_handler_t)(coap_session_t *session,
123                                    const coap_pdu_t *sent,
124                                    const coap_nack_reason_t reason,
125                                    const coap_mid_t mid);
126----
127NACKs can be one of the following
128----
129COAP_NACK_TOO_MANY_RETRIES
130COAP_NACK_NOT_DELIVERABLE
131COAP_NACK_RST
132COAP_NACK_TLS_FAILED
133COAP_NACK_ICMP_ISSUE
134----
135
136The *coap_register_ping_handler*() function defines a _handler_ for tracking
137receipt of CoAP ping traffic associated with the _context_. If _handler_ is
138NULL, then the handler is de-registered.
139
140The ping handler function prototype is defined as:
141[source, c]
142----
143typedef void (*coap_ping_handler_t)(coap_session_t *session,
144                                    const coap_pdu_t *received,
145                                    const coap_mid_t mid);
146----
147
148The *coap_register_pong_handler*() function defines a _handler_ for tracking
149receipt of CoAP ping response traffic associated with the _context_.
150If _handler_ is NULL, then the handler is de-registered.
151
152The pong handler function prototype is defined as:
153[source, c]
154----
155typedef void (*coap_pong_handler_t)(coap_session_t *session,
156                                    const coap_pdu_t *received,
157                                    const coap_mid_t mid);
158----
159
160The *coap_register_event_handler*() function defines a _handler_ for tracking
161(D)TLS events associated with the _context_. If _handler_ is NULL, then
162the handler is de-registered.
163
164The event handler function prototype is defined as:
165[source, c]
166----
167typedef void (*coap_event_handler_t)(coap_session_t *session,
168                                     const coap_event_t event);
169----
170Events can be one of the following
171----
172/**
173 * (D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS
174 */
175COAP_EVENT_DTLS_CLOSED        0x0000
176COAP_EVENT_DTLS_CONNECTED     0x01DE
177COAP_EVENT_DTLS_RENEGOTIATE   0x01DF
178COAP_EVENT_DTLS_ERROR         0x0200
179/**
180 * TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS
181 */
182COAP_EVENT_TCP_CONNECTED      0x1001
183COAP_EVENT_TCP_CLOSED         0x1002
184COAP_EVENT_TCP_FAILED         0x1003
185/**
186 * CSM exchange events for reliable protocols only
187 */
188COAP_EVENT_SESSION_CONNECTED  0x2001
189COAP_EVENT_SESSION_CLOSED     0x2002
190COAP_EVENT_SESSION_FAILED     0x2003
191----
192
193EXAMPLES
194--------
195*GET Resource Callback Handler*
196
197[source, c]
198----
199#include <coap@LIBCOAP_API_VERSION@/coap.h>
200
201#include <stdio.h>
202
203static void
204hnd_get_time(coap_resource_t *resource, coap_session_t *session,
205coap_pdu_t *request, coap_string_t *query, coap_pdu_t *response) {
206
207  unsigned char buf[40];
208  size_t len;
209  time_t now;
210
211  /* ... Additional analysis code for resource, request pdu etc.  ... */
212
213  /* After analysis, generate a suitable response */
214
215  now = time(NULL);
216
217  if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) {
218    /* Output secs since Jan 1 1970 */
219    len = snprintf((char *)buf, sizeof(buf), "%lu", now);
220  }
221  else {
222    /* Output human-readable time */
223    struct tm *tmp;
224    tmp = gmtime(&now);
225    if (!tmp) {
226      /* If 'now' is not valid */
227      coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
228      return;
229    }
230    len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp);
231  }
232  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
233  /*
234   * Invoke coap_add_data_large_response() to do all the hard work.
235   *
236   * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in
237   * Define how long this response is valid for (secs) - 1 - to add in.
238   *
239   * OBSERVE Option added internally if needed within the function
240   * BLOCK2 Option added internally if output too large
241   * ETAG Option added internally
242   */
243  coap_add_data_large_response(resource, session, request, response,
244                               query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0,
245                               len,
246                               buf, NULL, 0);
247
248}
249----
250*Packet Response Handler*
251
252[source, c]
253----
254#include <coap@LIBCOAP_API_VERSION@/coap.h>
255
256static int check_token(coap_pdu_t *received) {
257  /* Remove (void) definition if variable is used */
258  (void)received;
259
260  /* Code to validate the token is what we expect */
261
262  return 1;
263}
264
265static coap_response_t
266response_handler(coap_context_t *ctx, coap_session_t *session,
267coap_pdu_t *sent, coap_pdu_t *received, const coap_mid_t mid) {
268  /* Remove (void) definition if variable is used */
269  (void)ctx;
270  (void)session;
271  (void)mid;
272  coap_pdu_type_t rcv_type = coap_pdu_get_type(received);
273  coap_pdu_code_t rcv_code = coap_pdu_get_code(received);
274
275  /* check if this is a response to our original request */
276  if (!check_token(received)) {
277    /* drop if this was just some message, or send RST in case of notification */
278    if (!sent && (rcv_type == COAP_MESSAGE_CON ||
279                  rcv_type == COAP_MESSAGE_NON)) {
280      /* Cause a CoAP RST to be sent */
281      return COAP_RESPONSE_FAIL;
282    }
283    return COAP_RESPONSE_OK;
284  }
285
286  if (rcv_type == COAP_MESSAGE_RST) {
287    coap_log(LOG_INFO, "got RST\n");
288    return COAP_RESPONSE_OK;
289  }
290
291  /* Output the received data, if any */
292  if (COAP_RESPONSE_CLASS(rcv_code) == 2) {
293    /* Additional code to deal with the response */
294
295  }
296  return COAP_RESPONSE_OK;
297
298}
299----
300
301SEE ALSO
302--------
303*coap_block*(3), *coap_observe*(3) and *coap_resource*(3)
304
305FURTHER INFORMATION
306-------------------
307See "RFC7252: The Constrained Application Protocol (CoAP)" for further
308information.
309
310BUGS
311----
312Please report bugs on the mailing list for libcoap:
313libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
314https://github.com/obgm/libcoap/issues
315
316AUTHORS
317-------
318The libcoap project <libcoap-developers@lists.sourceforge.net>
319