Provided by: libcoap3t64_4.3.4-1.1build4_amd64 bug

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_pending, coap_can_exit - Work with CoAP I/O to do the packet send and receives

SYNOPSIS

       #include <coap3/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_io_pending(coap_context_t *context);

       int coap_can_exit(coap_context_t *context);

       For specific (D)TLS library support, link with -lcoap-3-notls, -lcoap-3-gnutls,
       -lcoap-3-openssl, -lcoap-3-mbedtls or -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 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 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.

FUNCTIONS

       Function: coap_io_process()

       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.

           #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.

       Function: coap_io_prepare_epoll()

       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.

       Function: coap_io_do_epoll()

       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.

       Function: coap_io_prepare_io()

       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.

       Function: coap_io_do_io()

       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.

       Function: coap_io_process_with_fds()

       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.

       Function: coap_context_get_coap_fd()

       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.

       Function: coap_io_pending()

       The coap_io_pending() function checks to see if there are any outstanding i/o requests /
       responses associated with context as well as if Observe has been set up (client only) and
       large transfers are in process.

       Function: coap_can_exit()

       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() return 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() return the number of milli-seconds that
       need to be waited before the function should next be called.

       coap_io_pending() returns 1 if there is outstanding i/o else returns 0.

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

EXAMPLES

       Method One - use coap_io_process()

           #include <coap3/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;

             /* Initialize libcoap library */
             coap_startup();

             /* 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);
             coap_cleanup();

             /* Do any other cleanup */

             exit(0);

           }

       Method One - coap_io_process_with_fds

           #include <coap3/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;

             /* Initialize libcoap library */
             coap_startup();

             /* 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);
             coap_cleanup();

             /* Do any other cleanup */

             exit(0);

           }

       Method Two - select() based on monitorable file descriptor

           #include <coap3/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;

             /* Initialize libcoap library */
             coap_startup();

             /* 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_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);
             coap_cleanup();

             /* Do any other cleanup */

             exit(0);

           }

       Method Two - epoll_wait() based on monitorable file descriptor

           #include <coap3/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;

             /* Initialize libcoap library */
             coap_startup();

             /* 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_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_debug("epoll_ctl: %s (%d)\n", coap_socket_strerror(), errno);
             }
             coap_free_context(ctx);
             coap_cleanup();

             /* Do any other cleanup */

             exit(0);

           }

SEE ALSO

       coap_block(3), coap_context(3) and coap_init(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>