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_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, -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_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), 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			  11/03/2025			    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.0>

home | help