Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
COAP_IO(3)			 libcoap Manual 		      COAP_IO(3)

NAME
     coap_io,	   coap_io_process,	 coap_io_process_with_fds,     coap_con-
     text_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,  -lcoap-3-wolfssl  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_pre-
     pare_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_pre-
     pare_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 un-
     til  the next internal action (e.g. packet retransmit) if any, or block un-
     til the next packet is received whichever is the sooner and do  the  neces-
     sary   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  /  retransmis-
	 sion traffic.

       2. Wait on the file descriptor returned by coap_context_get_coap_fd() us-
	 ing 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  sup-
	 port  epoll  (mostly Linux) with libcoap compiled to use epoll (the de-
	 fault) 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 re-
     sponses as well as handling any  timed  out  packet  re-transmissions.  Re-
     turned, 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  ap-
     propriate	low  level i/o function to send / receive / process the packets.
     Where appropriate, structure information (endpoints, sessions etc.) is  up-
     dated 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  net-
     work  traffic  (COAP_SOCKET_WANT_*  is  set)  found  to sockets (limited by
     max_sockets) and updates num_sockets with the number of sockets found. Fur-
     thermore, any triggered observer responses are transmitted as well as  han-
     dling 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_pre-
     pare_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  func-
     tion  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 trans-
     mitted 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 de-
     scriptor 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), coap_init(3) and coap_supported(3)

FURTHER INFORMATION
     See

     "RFC7252: The Constrained Application Protocol (CoAP)"

     for further information.

BUGS
     Please  raise  an issue on GitHub at https://github.com/obgm/libcoap/issues
     to report any bugs.

     Please raise a Pull Request  at  https://github.com/obgm/libcoap/pulls  for
     any fixes.

AUTHORS
     The libcoap project <libcoap-developers@lists.sourceforge.net>

coap_io 4.3.5			   08/02/2026			      COAP_IO(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=coap_io_pending&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help