libcoap-sys 0.2.2+libcoap-4.3.1

Raw bindings to the libcoap CoAP library.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
// -*- mode:doc; -*-
// vim: set syntax=asciidoc,tw=0:

coap_io(3)
==========
:doctype: manpage
:man source:   coap_io
:man version:  @PACKAGE_VERSION@
:man manual:   libcoap Manual

NAME
----
coap_io,
coap_io_process,
coap_io_process_with_fds,
coap_context_get_coap_fd,
coap_io_prepare_io,
coap_io_do_io,
coap_io_prepare_epoll,
coap_io_do_epoll,
coap_io_can_exit
- Work with CoAP I/O to do the packet send and receives

SYNOPSIS
--------
*#include <coap@LIBCOAP_API_VERSION@/coap.h>*

*int coap_io_process(coap_context_t *_context_, uint32_t _timeout_ms_)*;

*int coap_io_process_with_fds(coap_context_t *_context_,
uint32_t _timeout_ms_, int _nfds_, fd_set *_readfds_, fd_set *_writefds_,
fd_set *_exceptfds_)*;

*int coap_context_get_coap_fd(const coap_context_t *_context_)*;

*unsigned int coap_io_prepare_io(coap_context_t *_context_,
coap_socket_t *_sockets_[], unsigned int _max_sockets_,
unsigned int *_num_sockets_, coap_tick_t _now_)*;

*void coap_io_do_io(coap_context_t *_context_, coap_tick_t _now_)*;

*unsigned int coap_io_prepare_epoll(coap_context_t *_context_,
coap_tick_t _now_)*;

*void coap_io_do_epoll(coap_context_t *_context_, struct epoll_event *_events_,
size_t _nevents_)*;

*int coap_can_exit(coap_context_t *_context_)*;

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

DESCRIPTION
-----------
After setting up all the contexts, resources, endpoints sessions etc., the
underlying CoAP and (D)TLS need to send (and possible re-send) created packets
as well as receive packets for processing.

The *coap_io_process*() function will process any outstanding packets to send
for the specified _context_, process any available input packets and then wait
for processing any new input packets, or for when to re-transmit a packet, for
up to _timeout_ms_ milli-seconds before returning. There are 2 special case
_timeout_ms_ values.
[source, c]
----
#define COAP_IO_WAIT    0
#define COAP_IO_NO_WAIT ((uint32_t)-1)
----
If _timeout_ms_ is set to COAP_IO_WAIT, then *coap_io_process*() will block
until the next internal action (e.g. packet retransmit) if any, or block until
the next packet is received whichever is the sooner and do the necessary
processing. If _timeout_ms_ is set to COAP_IO_NO_WAIT, then *coap_io_process*()
will return immediately after processing without waiting for any new input
packets to arrive.

*NOTE:* *coap_io_process*() should not be called from within a callback
handler as defined using the coap_register_*_handler() as *coap_io_process*()
will likely recursively call the same handler.

There are two methods of how to call *coap_io_process*().

1. Have *coap_io_process*() called from within a while() loop.  Under idle
conditions (no input traffic) *coap_io_process*() will then get called every
_timeout_ms_, but more frequently if there is input / retransmission traffic.

2. Wait on the file descriptor returned by *coap_context_get_coap_fd*()
using *select*(), *poll*() or an event returned by epoll_wait(). If 'read' is
available on the CoAP file descriptor, call *coap_io_process*() with
_timeout_ms_ set to COAP_IO_NO_WAIT. +
*NOTE*: This second method is only available for environments that support epoll
(mostly Linux) with libcoap compiled to use *epoll* (the default) as libcoap
will then be using *epoll* internally to process all the file descriptors of
the different sessions.

See EXAMPLES below.

The *coap_io_process*() function is the primary function applications should
use. There are internal functions that *coap_io_process*() calls which are
available to use if absolutely necessary.  These internal functions and how to
use them is different depending on whether libcoap has been compiled to use
*epoll* (Linux systems only) or not.

For *epoll* libcoap, *coap_io_process*() in simple terms calls
*coap_io_prepare_epoll*(), does an *epoll_wait*() and then calls
*coap_io_do_epoll*() if needed to make sure that all event based i/o has been
completed.

For *non-epoll* libcoap, *coap_io_process*() in simple terms calls
*coap_io_prepare_io*() to set up sockets[], sets up all of the *select*()
parameters based on the COAP_SOCKET_WANT* values in the sockets[], does a
*select*(), updates the sockets[] with COAP_SOCKET_CAN_* as appropriate and
then calls *coap_io_do_io*() to make sure that all current i/o has been
completed.

The *coap_io_prepare_epoll*() function for the specified _context_ will
iterate through the endpoints and sessions to transmit any triggered observer
responses as well as handling any timed out packet re-transmissions.  Returned,
based on _now_, is the number of milli-secs needed to delay until the next
time that *coap_io_prepare_epoll*() needs to get called.  After this call an
*epoll_wait*() should done.

The *coap_io_do_epoll*() function for the specified _context_ will
iterate through the _nevents_ of _events_ returned by *epoll_wait*() and
execute the appropriate low level i/o function to send / receive / process the
packets. Where appropriate, structure information (endpoints, sessions etc.)
is updated with the value of _now_ in the lower level functions.

The *coap_io_prepare_io*() function for the specified _context_ will iterate
through the endpoints and sessions to add all of sockets waiting for network
traffic (COAP_SOCKET_WANT_* is set) found to _sockets_ (limited by
_max_sockets_) and updates _num_sockets_ with the number of sockets found.
Furthermore, any triggered observer responses are transmitted
as well as handling any timed out packet re-transmissions.  Returned, based on
_now_, is the number of milli-secs needed to delay until the next time that
*coap_io_prepare_io*() needs to get called.  After this call a *select*() should
done on all the file descriptors (COAP_WANT_READ for readfds etc.), and any
that are returned active should set the appropriate COAP_SOCKET_CAN_* in the
_sockets_.

The *coap_io_do_io*() function for the specified _context_ will
iterate through the endpoints and sessions to find all of sockets that have
COAP_SOCKET_CAN_* set and then execute the appropriate low level i/o function
to send / receive / process the packets. Where appropriate, structure
information (endpoints, sessions etc.) is updated with the value of _now_ in
the lower level functions.

The *coap_io_process_with_fds*() function is the same as *coap_process_io*()
but supports additional select() style parameters _nfds_, _readfds_,
_writefds_ and _exceptfds_. This provides the ability to add in additional
non libcoap FDs to test for in the internal select() call which can then
tested after the return from coap_io_process_with_fds(). _readfds_,
_writefds_ and _exceptfds_ can either point to a defined and pre-filled fd_set
structure or NULL if not required. _nfds_ needs to be set to the maximum FD to
test for in _readfds_, _writefds_ or _exceptfds_ if any of them are set plus 1.
If none of them are set, then _nfds_ should be set to 0.

NOTE: The additional parameters for *coap_io_process_with_fds*() are only used
if there is no epoll support in libcoap. If there is epoll support, then
*coap_context_get_coap_fd*() should be used and this returned FD along with
other non libcoap FDs can separately be monitored using method 2 above.

The *coap_context_get_coap_fd*() function obtains from the specified
_context_ a single file descriptor that can be monitored by a *select*() or
as an event returned from a *epoll_wait*() call.  This file descriptor will get
updated with information (read, write etc. available) whenever any of the
internal to libcoap file descriptors (sockets) change state.

The *coap_can_exit*() function checks to see if there are any outstanding
PDUs to transmit associated with _context_ and returns 1 if there is nothing
outstanding else 0. This function does not check that all requests transmitted
have been responded to.

RETURN VALUES
-------------
*coap_io_process*() and *coap_io_process_with_fds*() returns the time, in
milli-seconds, that was spent in the function. If -1 is returned, there was
an unexpected error.

*coap_context_get_coap_fd*() returns a non-negative number as the file
descriptor to monitor, or -1 if epoll is not configured in libcoap.

*coap_io_prepare_io*() and *coap_io_prepare_epoll*() returns the number of
milli-seconds that need to be waited before the function should next be called.

*coap_can_exit*() returns 1 if there is nothing outstanding to transmit else
returns 0.

EXAMPLES
--------
*Method One - use coap_io_process()*

[source, c]
----
#include <coap@LIBCOAP_API_VERSION@/coap.h>

int main(int argc, char *argv[]){

  coap_context_t *ctx = NULL;
  unsigned wait_ms;
  /* Remove (void) definition if variable is used */
  (void)argc;
  (void)argv;

  /* Create the libcoap context */
  ctx = coap_new_context(NULL);
  if (!ctx) {
    exit(1);
  }
  /* See coap_block(3) */
  coap_context_set_block_mode(ctx,
                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);


  /* Other Set up Code */

  wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;

  while (1) {
    int result = coap_io_process(ctx, wait_ms);
    if (result < 0) {
      /* There is an internal issue */
      break;
    }
    /* Do any other housekeeping */
  }
  coap_free_context(ctx);

  /* Do any other cleanup */

  exit(0);

}
----

*Method One - coap_io_process_with_fds*

[source, c]
----
#include <coap@LIBCOAP_API_VERSION@/coap.h>

int main(int argc, char *argv[]){

  coap_context_t *ctx = NULL;
  unsigned wait_ms;
  fd_set readfds;
  int nfds = 0;
  /* Remove (void) definition if variable is used */
  (void)argc;
  (void)argv;

  /* Create the libcoap context */
  ctx = coap_new_context(NULL);
  if (!ctx) {
    exit(1);
  }
  /* See coap_block(3) */
  coap_context_set_block_mode(ctx,
                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);


  FD_ZERO(&readfds);
  /* Set up readfds and nfds to handle other non libcoap FDs */

  /* Other Set up Code */

  wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;

  while (1) {
    int result = coap_io_process_with_fds(ctx, wait_ms, nfds, &readfds, NULL, NULL);
    if (result < 0) {
      /* There is an internal issue */
      break;
    }
    /* Check if set non libcoap FDs and process accordingly */

    /* Do any other housekeeping */
  }
  coap_free_context(ctx);

  /* Do any other cleanup */

  exit(0);

}
----

*Method Two - select() based on monitorable file descriptor*

[source, c]
----
#include <coap@LIBCOAP_API_VERSION@/coap.h>

#include <errno.h>

int main(int argc, char *argv[]){

  coap_context_t *ctx = NULL;
  int coap_fd;
  fd_set m_readfds;
  int nfds;
  /* Remove (void) definition if variable is used */
  (void)argc;
  (void)argv;

  /* Create the libcoap context */
  ctx = coap_new_context(NULL);
  if (!ctx) {
    exit(1);
  }
  /* See coap_block(3) */
  coap_context_set_block_mode(ctx,
                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);

  coap_fd = coap_context_get_coap_fd(ctx);
  if (coap_fd == -1) {
    /* epoll is not supported */
    exit(1);
  }
  FD_ZERO(&m_readfds);
  FD_SET(coap_fd, &m_readfds);
  nfds = coap_fd + 1;

  /* Other Set up Code */

  while (1) {
    fd_set readfds = m_readfds;
    int result;
    /* Wait until any i/o takes place */
    result = select (nfds, &readfds, NULL, NULL, NULL);
    if (result == -1) {
      if (errno != EAGAIN) {
        coap_log(LOG_DEBUG, "select: %s (%d)\n", coap_socket_strerror(), errno);
        break;
      }
    }
    if (result > 0) {
      if (FD_ISSET(coap_fd, &readfds)) {
        result = coap_io_process(ctx, COAP_IO_NO_WAIT);
        if (result < 0) {
          /* There is an internal issue */
          break;
        }
      }
    }
    /* Do any other housekeeping */
  }
  coap_free_context(ctx);

  /* Do any other cleanup */

  exit(0);

}
----

*Method Two - epoll_wait() based on monitorable file descriptor*

[source, c]
----
#include <coap@LIBCOAP_API_VERSION@/coap.h>

#include <sys/epoll.h>

#include <errno.h>

#define MAX_EVENTS 10

int main(int argc, char *argv[]){

  coap_context_t *ctx = NULL;
  int coap_fd;
  int epoll_fd;
  struct epoll_event ev;
  struct epoll_event events[MAX_EVENTS];
  int nevents;
  int i;
  /* Remove (void) definition if variable is used */
  (void)argc;
  (void)argv;

  /* Create the libcoap context */
  ctx = coap_new_context(NULL);
  if (!ctx) {
    exit(1);
  }
  /* See coap_block(3) */
  coap_context_set_block_mode(ctx,
                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);

  coap_fd = coap_context_get_coap_fd(ctx);
  if (coap_fd == -1) {
    exit(1);
  }
  epoll_fd = epoll_create1(0);
  if (epoll_fd == -1) {
    exit(2);
  }
  ev.events = EPOLLIN;
  ev.data.fd = coap_fd;
  if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, coap_fd, &ev) == -1) {
    exit(3);
  }

  /* Other Set up Code */

  while (1) {
    int result;
    /* Wait until any i/o takes place */
    nevents = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
    if (nevents == -1) {
      if (errno != EAGAIN) {
        coap_log(LOG_DEBUG, "epoll_wait: %s (%d)\n", coap_socket_strerror(), errno);
        break;
      }
    }
    for (i = 0; i < nevents; i++) {
      if (events[i].data.fd == coap_fd) {
        result = coap_io_process(ctx, COAP_IO_NO_WAIT);
        if (result < 0) {
          /* There is an internal issue */
          break;
        }
      }
      else {
        /* Process other events */
      }
    }
    /* Do any other housekeeping */
  }

  if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, coap_fd, &ev) == -1) {
    coap_log(LOG_DEBUG, "epoll_ctl: %s (%d)\n", coap_socket_strerror(), errno);
  }
  coap_free_context(ctx);

  /* Do any other cleanup */

  exit(0);

}
----

SEE ALSO
--------
*coap_block*(3) and *coap_context*(3)

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>