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

NAME

6       coap_io, coap_io_process, coap_io_process_with_fds,
7       coap_context_get_coap_fd, coap_io_prepare_io, coap_io_do_io,
8       coap_io_prepare_epoll, coap_io_do_epoll - Work with CoAP I/O to do the
9       packet send and receives
10

SYNOPSIS

12       #include <coap3/coap.h>
13
14       int coap_io_process(coap_context_t *context, uint32_t timeout_ms);
15
16       int coap_io_process_with_fds(coap_context_t *context, uint32_t
17       timeout_ms, int nfds, fd_set *readfds, fd_set *writefds, fd_set
18       *exceptfds);
19
20       int coap_context_get_coap_fd(const coap_context_t *context);
21
22       unsigned int coap_io_prepare_io(coap_context_t *context, coap_socket_t
23       *sockets[], unsigned int max_sockets, unsigned int *num_sockets,
24       coap_tick_t now);
25
26       void coap_io_do_io(coap_context_t *context, coap_tick_t now);
27
28       unsigned int coap_io_prepare_epoll(coap_context_t *context, coap_tick_t
29       now);
30
31       void coap_io_do_epoll(coap_context_t *context, struct epoll_event
32       *events, size_t nevents);
33
34       For specific (D)TLS library support, link with -lcoap-3-notls,
35       -lcoap-3-gnutls, -lcoap-3-openssl, -lcoap-3-mbedtls or
36       -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 to get the default
37       (D)TLS library support.
38

DESCRIPTION

40       After setting up all the contexts, resources, endpoints sessions etc.,
41       the underlying CoAP and (D)TLS need to send (and possible re-send)
42       created packets as well as receive packets for processing.
43
44       The coap_io_process() function will process any outstanding packets to
45       send for the specified context, process any available input packets and
46       then wait for processing any new input packets, or for when to
47       re-transmit a packet, for up to timeout_ms milli-seconds before
48       returning. There are 2 special case timeout_ms values.
49
50           #define COAP_IO_WAIT    0
51           #define COAP_IO_NO_WAIT ((uint32_t)-1)
52
53       If timeout_ms is set to COAP_IO_WAIT, then coap_io_process() will block
54       until the next internal action (e.g. packet retransmit) if any, or
55       block until the next packet is received whichever is the sooner and do
56       the necessary processing. If timeout_ms is set to COAP_IO_NO_WAIT, then
57       coap_io_process() will return immediately after processing without
58       waiting for any new input packets to arrive.
59
60       There are two methods of how to call coap_io_process().
61
62        1. Have coap_io_process() called from within a while() loop. Under
63           idle conditions (no input traffic) coap_io_process() will then get
64           called every timeout_ms, but more frequently if there is input /
65           retransmission traffic.
66
67        2. Wait on the file descriptor returned by coap_context_get_coap_fd()
68           using select() or an event returned by epoll_wait(). If read is
69           available on the file descriptor, call coap_io_process() with
70           timeout_ms set to COAP_IO_NO_WAIT.
71
72           NOTE: This second method is only available for environments that
73           support epoll (mostly Linux) with libcoap compiled to use epoll
74           (the default) as libcoap will then be using epoll internally to
75           process all the file descriptors of the different sessions.
76
77       See EXAMPLES below.
78
79       The coap_io_process() function is the primary function applications
80       should use. There are internal functions that coap_io_process() calls
81       which are available to use if absolutely necessary. These internal
82       functions and how to use them is different depending on whether libcoap
83       has been compiled to use epoll (Linux systems only) or not.
84
85       For epoll libcoap, coap_io_process() in simple terms calls
86       coap_io_prepare_epoll(), does an epoll_wait() and then calls
87       coap_io_do_epoll() if needed to make sure that all event based i/o has
88       been completed.
89
90       For non-epoll libcoap, coap_io_process() in simple terms calls
91       coap_io_prepare_io() to set up sockets[], sets up all of the select()
92       parameters based on the COAP_SOCKET_WANT* values in the sockets[], does
93       a select(), updates the sockets[] with COAP_SOCKET_CAN_* as appropriate
94       and then calls coap_io_do_io() to make sure that all current i/o has
95       been completed.
96
97       The coap_io_prepare_epoll() function for the specified context will
98       iterate through the endpoints and sessions to transmit any triggered
99       observer responses as well as handling any timed out packet
100       re-transmissions. Returned, based on now, is the number of milli-secs
101       needed to delay until the next time that coap_io_prepare_epoll() needs
102       to get called. After this call an epoll_wait() should done.
103
104       The coap_io_do_epoll() function for the specified context will iterate
105       through the nevents of events returned by epoll_wait() and execute the
106       appropriate low level i/o function to send / receive / process the
107       packets. Where appropriate, structure information (endpoints, sessions
108       etc.) is updated with the value of now in the lower level functions.
109
110       The coap_io_prepare_io() function for the specified context will
111       iterate through the endpoints and sessions to add all of sockets
112       waiting for network traffic (COAP_SOCKET_WANT_* is set) found to
113       sockets (limited by max_sockets) and updates num_sockets with the
114       number of sockets found. Furthermore, any triggered observer responses
115       are transmitted as well as handling any timed out packet
116       re-transmissions. Returned, based on now, is the number of milli-secs
117       needed to delay until the next time that coap_io_prepare_io() needs to
118       get called. After this call a select() should done on all the file
119       descriptors (COAP_WANT_READ for readfds etc.), and any that are
120       returned active should set the appropriate COAP_SOCKET_CAN_* in the
121       sockets.
122
123       The coap_io_do_io() function for the specified context will iterate
124       through the endpoints and sessions to find all of sockets that have
125       COAP_SOCKET_CAN_* set and then execute the appropriate low level i/o
126       function to send / receive / process the packets. Where appropriate,
127       structure information (endpoints, sessions etc.) is updated with the
128       value of now in the lower level functions.
129
130       The coap_io_process_with_fds() function is the same as
131       coap_process_io() but supports additional select() style parameters
132       nfds, readfds, writefds and exceptfds. This provides the ability to add
133       in additional non libcoap FDs to test for in the internal select() call
134       which can then tested after the return from coap_io_process_with_fds().
135       readfds, writefds and exceptfds can either point to a defined and
136       pre-filled fd_set structure or NULL if not required. nfds needs to be
137       set to the maximum FD to test for in readfds, writefds or exceptfds if
138       any of them are set plus 1. If none of them are set, then nfds should
139       be set to 0.
140
141           Note
142           The additional parameters for coap_io_process_with_fds() are only
143           used if there is no epoll support in libcoap. If there is epoll
144           support, then coap_context_get_coap_fd() should be used and this
145           returned FD along with other non libcoap FDs can separately be
146           monitored using method 2 above.
147
148       The coap_context_get_coap_fd() function obtains from the specified
149       context a single file descriptor that can be monitored by a select() or
150       as an event returned from a epoll_wait() call. This file descriptor
151       will get updated with information (read, write etc. available) whenever
152       any of the internal to libcoap file descriptors (sockets) change state.
153

RETURN VALUES

155       coap_io_process() and coap_io_process_with_fds() returns the time, in
156       milli-seconds, that was spent in the function. If -1 is returned, there
157       was an unexpected error.
158
159       coap_context_get_coap_fd() returns a non-negative number as the file
160       descriptor to monitor, or -1 if epoll is not configured in libcoap.
161
162       coap_io_prepare_io() and coap_io_prepare_epoll() returns the number of
163       milli-seconds that need to be waited before the function should next be
164       called.
165

EXAMPLES

167       Method One - use coap_io_process()
168
169           #include <coap3/coap.h>
170
171           int main(int argc, char *argv[]){
172
173             coap_context_t *ctx = NULL;
174             unsigned wait_ms;
175             /* Remove (void) definition if variable is used */
176             (void)argc;
177             (void)argv;
178
179             /* Create the libcoap context */
180             ctx = coap_new_context(NULL);
181             if (!ctx) {
182               exit(1);
183             }
184             /* See coap_block(3) */
185             coap_context_set_block_mode(ctx,
186                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
187
188
189             /* Other Set up Code */
190
191             wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;
192
193             while (1) {
194               int result = coap_io_process(ctx, wait_ms);
195               if (result < 0) {
196                 /* There is an internal issue */
197                 break;
198               }
199               /* Do any other housekeeping */
200             }
201             coap_free_context(ctx);
202
203             /* Do any other cleanup */
204
205             exit(0);
206
207           }
208
209       Method One - coap_io_process_with_fds
210
211           #include <coap3/coap.h>
212
213           int main(int argc, char *argv[]){
214
215             coap_context_t *ctx = NULL;
216             unsigned wait_ms;
217             fd_set readfds;
218             int nfds = 0;
219             /* Remove (void) definition if variable is used */
220             (void)argc;
221             (void)argv;
222
223             /* Create the libcoap context */
224             ctx = coap_new_context(NULL);
225             if (!ctx) {
226               exit(1);
227             }
228             /* See coap_block(3) */
229             coap_context_set_block_mode(ctx,
230                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
231
232
233             FD_ZERO(&readfds);
234             /* Set up readfds and nfds to handle other non libcoap FDs */
235
236             /* Other Set up Code */
237
238             wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;
239
240             while (1) {
241               int result = coap_io_process_with_fds(ctx, wait_ms, nfds, &readfds, NULL, NULL);
242               if (result < 0) {
243                 /* There is an internal issue */
244                 break;
245               }
246               /* Check if set non libcoap FDs and process accordingly */
247
248               /* Do any other housekeeping */
249             }
250             coap_free_context(ctx);
251
252             /* Do any other cleanup */
253
254             exit(0);
255
256           }
257
258       Method Two - select() based on monitorable file descriptor
259
260           #include <coap3/coap.h>
261
262           #include <errno.h>
263
264           int main(int argc, char *argv[]){
265
266             coap_context_t *ctx = NULL;
267             int coap_fd;
268             fd_set m_readfds;
269             int nfds;
270             /* Remove (void) definition if variable is used */
271             (void)argc;
272             (void)argv;
273
274             /* Create the libcoap context */
275             ctx = coap_new_context(NULL);
276             if (!ctx) {
277               exit(1);
278             }
279             /* See coap_block(3) */
280             coap_context_set_block_mode(ctx,
281                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
282
283             coap_fd = coap_context_get_coap_fd(ctx);
284             if (coap_fd == -1) {
285               /* epoll is not supported */
286               exit(1);
287             }
288             FD_ZERO(&m_readfds);
289             FD_SET(coap_fd, &m_readfds);
290             nfds = coap_fd + 1;
291
292             /* Other Set up Code */
293
294             while (1) {
295               fd_set readfds = m_readfds;
296               int result;
297               /* Wait until any i/o takes place */
298               result = select (nfds, &readfds, NULL, NULL, NULL);
299               if (result == -1) {
300                 if (errno != EAGAIN) {
301                   coap_log(LOG_DEBUG, "select: %s (%d)\n", coap_socket_strerror(), errno);
302                   break;
303                 }
304               }
305               if (result > 0) {
306                 if (FD_ISSET(coap_fd, &readfds)) {
307                   result = coap_io_process(ctx, COAP_IO_NO_WAIT);
308                   if (result < 0) {
309                     /* There is an internal issue */
310                     break;
311                   }
312                 }
313               }
314               /* Do any other housekeeping */
315             }
316             coap_free_context(ctx);
317
318             /* Do any other cleanup */
319
320             exit(0);
321
322           }
323
324       Method Two - epoll_wait() based on monitorable file descriptor
325
326           #include <coap3/coap.h>
327
328           #include <sys/epoll.h>
329
330           #include <errno.h>
331
332           #define MAX_EVENTS 10
333
334           int main(int argc, char *argv[]){
335
336             coap_context_t *ctx = NULL;
337             int coap_fd;
338             int epoll_fd;
339             struct epoll_event ev;
340             struct epoll_event events[MAX_EVENTS];
341             int nevents;
342             int i;
343             /* Remove (void) definition if variable is used */
344             (void)argc;
345             (void)argv;
346
347             /* Create the libcoap context */
348             ctx = coap_new_context(NULL);
349             if (!ctx) {
350               exit(1);
351             }
352             /* See coap_block(3) */
353             coap_context_set_block_mode(ctx,
354                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
355
356             coap_fd = coap_context_get_coap_fd(ctx);
357             if (coap_fd == -1) {
358               exit(1);
359             }
360             epoll_fd = epoll_create1(0);
361             if (epoll_fd == -1) {
362               exit(2);
363             }
364             ev.events = EPOLLIN;
365             ev.data.fd = coap_fd;
366             if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, coap_fd, &ev) == -1) {
367               exit(3);
368             }
369
370             /* Other Set up Code */
371
372             while (1) {
373               int result;
374               /* Wait until any i/o takes place */
375               nevents = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
376               if (nevents == -1) {
377                 if (errno != EAGAIN) {
378                   coap_log(LOG_DEBUG, "epoll_wait: %s (%d)\n", coap_socket_strerror(), errno);
379                   break;
380                 }
381               }
382               for (i = 0; i < nevents; i++) {
383                 if (events[i].data.fd == coap_fd) {
384                   result = coap_io_process(ctx, COAP_IO_NO_WAIT);
385                   if (result < 0) {
386                     /* There is an internal issue */
387                     break;
388                   }
389                 }
390                 else {
391                   /* Process other events */
392                 }
393               }
394               /* Do any other housekeeping */
395             }
396
397             if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, coap_fd, &ev) == -1) {
398               coap_log(LOG_DEBUG, "epoll_ctl: %s (%d)\n", coap_socket_strerror(), errno);
399             }
400             coap_free_context(ctx);
401
402             /* Do any other cleanup */
403
404             exit(0);
405
406           }
407

SEE ALSO

409       coap_block(3), coap_context(3)
410

FURTHER INFORMATION

412       See "RFC7252: The Constrained Application Protocol (CoAP)" for further
413       information.
414

BUGS

416       Please report bugs on the mailing list for libcoap:
417       libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
418       https://github.com/obgm/libcoap/issues
419

AUTHORS

421       The libcoap project <libcoap-developers@lists.sourceforge.net>
422
423
424
425coap_io 4.3.0                     01/20/2022                        COAP_IO(3)
Impressum