Rename coap_run_once() to coap_io_process()

coap_read(), coap_write() and coap_run_once() are confusing in their names
and do not really describe what they do.

For example, coap_read() does both reading and writing, coap_write() may
do some writing, but primarily is used to determine what should be monitored
and for how long to wait in the following select() or epoll_wait() calls.

coap_run_once() implies that the code is only to be run once - again confusing.

By renaming coap_read() to coap_io_do_io(), this better describes what this
function does.

By renaming coap_write() to coap_io_prepare_io() this better describes what this
function does.

By renaming coap_run_once() to coap_io_process(), this better describes what
this function does.

By renaming coap_io_do_events() to coap_io_do_epoll(), this better describes what
this function does and is associated with.

A wrapper function coap_io_prepare_epoll() has been created, using
coap_io_prepare_io() with some preset values to simplify function usage.

include/coap2/net.h:

Update with the new function names, and deprecate the old functions.  Also
document the fact that coap_io_prepare_io(), coap_io_do_io(),
coap_io_prepare_epoll(), and coap_io_do_epoll() are really internal functions.

Create app_io module for Doxygen.

libcoap-2.map:
libcoap-2.sym:

Expose the new functions to applications.

examples/client.c:
examples/coap-rd.c:
examples/coap-server.c:
examples/contiki/coap-observer.c:
examples/contiki/server.c:
examples/etsi_iot_01.c:
man/coap_io.txt.in:
man/coap_observe.txt.in:
src/coap_io.c:
src/coap_io_lwip.c:
src/net.c:
src/pdu.c:

Update using the new function names.

Setting the etimer has been moved out of coap_io_process() into
coap_io_do_epoll(), making the logic easier for applications to use
coap_io_do_epoll() should they need to.  This also gets rid of a
potential timing window where a pending etimer event gets missed.

coap_io_do_epoll() now calls coap_io_prepare_epoll() if the etimer has
triggered removing the need for applications using coap_io_do_epoll() to
set up their own loops if etimer is triggered.
This commit is contained in:
Jon Shallow committed 2020-02-13 19:54:48 +00:00
1 parent fca966385e
commit 9cf4f10b35
15 files changed
+384 -193

No files matched your search

+1 -1
View File
@@ -1740,7 +1740,7 @@ main(int argc, char **argv) {
while (!quit && !(ready && !doing_getting_block && coap_can_exit(ctx)) ) {
result = coap_run_once( ctx, wait_ms == 0 ?
result = coap_io_process( ctx, wait_ms == 0 ?
obs_ms : obs_ms == 0 ?
min(wait_ms, 1000) : min( wait_ms, obs_ms ) );
+1 -1
View File
@@ -859,7 +859,7 @@ main(int argc, char **argv) {
#endif
while ( !quit ) {
result = coap_run_once( ctx, COAP_RESOURCE_CHECK_TIME * 1000 );
result = coap_io_process( ctx, COAP_RESOURCE_CHECK_TIME * 1000 );
if ( result >= 0 ) {
/* coap_check_resource_list( ctx ); */
}
+3 -3
View File
@@ -1453,13 +1453,13 @@ main(int argc, char **argv) {
}
if (result > 0) {
if (FD_ISSET(coap_fd, &readfds)) {
result = coap_run_once(ctx, COAP_RUN_NONBLOCK);
result = coap_io_process(ctx, COAP_RUN_NONBLOCK);
}
}
}
else {
/* epoll is not supported within libcoap */
result = coap_run_once( ctx, wait_ms );
result = coap_io_process(ctx, wait_ms);
}
if ( result < 0 ) {
break;
@@ -1470,7 +1470,7 @@ main(int argc, char **argv) {
/*
* result == 0, or result >= wait_ms
* (wait_ms could have decremented to a small value, below
* the granularity of the timer in coap_run_once() and hence
* the granularity of the timer in coap_io_process() and hence
* result == 0)
*/
time_t t_now = time(NULL);
+1 -1
View File
@@ -176,7 +176,7 @@ PROCESS_THREAD(coap_server_process, ev, data)
while(1) {
PROCESS_YIELD();
if(ev == tcpip_event) {
coap_read(coap_context); /* read received data */
coap_io_do_io(coap_context); /* read received data */
coap_dispatch(coap_context); /* and dispatch PDUs from receivequeue */
}
}
+1 -1
View File
@@ -216,7 +216,7 @@ PROCESS_THREAD(coap_server_process, ev, data)
PROCESS_YIELD();
if(ev == tcpip_event) {
/* There is something to read on the endpoint */
coap_run_once(coap_context, COAP_RUN_BLOCK);
coap_io_process(coap_context, COAP_RUN_BLOCK);
} else if (ev == PROCESS_EVENT_TIMER && etimer_expired(&dirty_timer)) {
coap_resource_notify_observers(time_resource, NULL);
etimer_reset(&dirty_timer);
+1 -1
View File
@@ -667,7 +667,7 @@ main(int argc, char **argv) {
sigaction (SIGPIPE, &sa, NULL);
while ( !quit ) {
result = coap_run_once( ctx, COAP_RESOURCE_CHECK_TIME * 1000 );
result = coap_io_process( ctx, COAP_RESOURCE_CHECK_TIME * 1000 );
if ( result >= 0 ) {
/* coap_check_resource_list( ctx ); */
}
+227 -120
View File
@@ -541,126 +541,6 @@ coap_tid_t coap_send( coap_session_t *session, coap_pdu_t *pdu );
*/
coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node);
/**
* For applications with their own message loop, send all pending retransmits and
* return the list of sockets with events to wait for and the next timeout
* The application should call coap_read, then coap_write again when any condition below is true:
* - data is available on any of the sockets with the COAP_SOCKET_WANT_READ
* - an incoming connection is pending in the listen queue and the COAP_SOCKET_WANT_ACCEPT flag is set
* - at least some data can be written without blocking on any of the sockets with the COAP_SOCKET_WANT_WRITE flag set
* - a connection event occured (success or failure) and the COAP_SOCKET_WANT_CONNECT flag is set
* - the timeout has expired
* Before calling coap_read or coap_write again, the application should position COAP_SOCKET_CAN_READ and COAP_SOCKET_CAN_WRITE flags as applicable.
*
* @param ctx The CoAP context
* @param sockets array of socket descriptors, filled on output
* @param max_sockets size of socket array.
* @param num_sockets pointer to the number of valid entries in the socket arrays on output
* @param now Current time.
*
* @return timeout as maxmimum number of milliseconds that the application should wait for network events or 0 if the application should wait forever.
*/
unsigned int
coap_write(coap_context_t *ctx,
coap_socket_t *sockets[],
unsigned int max_sockets,
unsigned int *num_sockets,
coap_tick_t now
);
/**
* For applications with their own message loop, reads all data from the network.
*
* @param ctx The CoAP context
* @param now Current time
*/
void coap_read(coap_context_t *ctx, coap_tick_t now);
#define COAP_RUN_BLOCK 0
#define COAP_RUN_NONBLOCK 1
/**
* The main message processing loop.
*
* @param ctx The CoAP context
* @param timeout_ms Minimum number of milliseconds to wait for new packets
* before returning. If COAP_RUN_BLOCK, the call will block
* until at least one new packet is received. If
* COAP_RUN_NONBLOCK, the function will return immediately
* following without waiting for any new input not already
* available.
*
* @return Number of milliseconds spent in coap_run_once, or @c -1 if there
* was an error
*/
int coap_run_once( coap_context_t *ctx, unsigned int timeout_ms );
/**
* The main message processing loop with additional fds for internal select.
*
* @param ctx The CoAP context
* @param timeout_ms Minimum number of milliseconds to wait for new packets
* before returning. If COAP_RUN_BLOCK, the call will block
* until at least one new packet is received. If
* COAP_RUN_NONBLOCK, the function will return immediately
* following without waiting for any new input not already
* available.
* @param nfds The maximum FD set in readfds, writefds or exceptfds
* plus one,
* @param readfds Read FDs to additionally check for in internal select()
* or NULL if not required.
* @param writefds Write FDs to additionally check for in internal select()
* or NULL if not required.
* @param exceptfds Except FDs to additionally check for in internal select()
* or NULL if not required.
*
*
* @return Number of milliseconds spent in coap_io_process_with_fds, or @c -1
* if there was an error. If defined, readfds, writefds, exceptfds
* are updated as returned by the internal select() call.
*/
int coap_io_process_with_fds(coap_context_t *ctx, unsigned int timeout_ms,
int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds);
/**
* Any now timed out delayed packet is transmitted, along with any packets
* associated with requested observable response.
*
* In addition, it returns when the next expected I/O is expected to take place
* (e.g. a packet retransmit).
*
* Note: If epoll support is compiled into libcoap, coap_io_prepare_epoll() must
* be used instead of coap_write().
*
* Internal function.
*
* @param ctx The CoAP context
* @param now Current time.
*
* @return timeout Maxmimum number of milliseconds that can be used by a
* epoll_wait() to wait for network events or 0 if wait should be
* forever.
*/
unsigned int
coap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now);
struct epoll_event;
/**
* Process all the epoll events
*
* Internal function
*
* @param ctx The current CoAP context.
* @param events The list of events returned from an epoll_wait() call.
* @param nevents The number of events.
*
*/
void coap_io_do_events(coap_context_t *ctx, struct epoll_event* events,
size_t nevents);
/**
* Parses and interprets a CoAP datagram with context @p ctx. This function
* returns @c 0 if the datagram was handled, or a value less than zero on
@@ -844,4 +724,231 @@ unsigned int coap_calc_timeout(coap_session_t *session, unsigned char r);
int
coap_join_mcast_group(coap_context_t *ctx, const char *groupname);
/**
* @defgroup app_io Application I/O Handling
* API functions for Application Input / Output
* @{
*/
#define COAP_RUN_BLOCK 0
#define COAP_RUN_NONBLOCK 1
/**
* The main I/O processing function. All pending network I/O is completed,
* and then optionally waits for the next input packet.
*
* This internally calls coap_io_prepare_io(), then select() for the appropriate
* sockets, updates COAP_SOCKET_CAN_xxx where appropriate and then calls
* coap_io_do_io() before returning with the time spent in the function.
*
* Alternatively, if libcoap is compiled with epoll support, this internally
* calls coap_io_prepare_epoll(), then epoll_wait() for waiting for any file
* descriptors that have (internally) been set up with epoll_ctl() and
* finally coap_io_do_epoll() before returning with the time spent in the
* function.
*
* @param ctx The CoAP context
* @param timeout_ms Minimum number of milliseconds to wait for new packets
* before returning. If COAP_RUN_BLOCK, the call will block
* until at least one new packet is received. If
* COAP_RUN_NONBLOCK, the function will return immediately
* following without waiting for any new input not already
* available.
*
* @return Number of milliseconds spent in function or @c -1 if there was
* an error
*/
int coap_io_process(coap_context_t *ctx, unsigned int timeout_ms);
/**
* @deprecated Use coap_io_process() instead.
*
* This function just calls coap_io_process().
*
* @param ctx The CoAP context
* @param timeout_ms Minimum number of milliseconds to wait for new packets
* before returning. If COAP_RUN_BLOCK, the call will block
* until at least one new packet is received. If
* COAP_RUN_NONBLOCK, the function will return immediately
* following without waiting for any new input not already
* available.
*
* @return Number of milliseconds spent in function or @c -1 if there was
* an error
*/
COAP_STATIC_INLINE COAP_DEPRECATED int
coap_run_once(coap_context_t *ctx, unsigned int timeout_ms)
{
return coap_io_process(ctx, timeout_ms);
}
/**
* The main message processing loop with additional fds for internal select.
*
* @param ctx The CoAP context
* @param timeout_ms Minimum number of milliseconds to wait for new packets
* before returning. If COAP_RUN_BLOCK, the call will block
* until at least one new packet is received. If
* COAP_RUN_NONBLOCK, the function will return immediately
* after processing any existing input packets.
* @param nfds The maximum FD set in readfds, writefds or exceptfds
* plus one,
* @param readfds Read FDs to additionally check for in internal select()
* or NULL if not required.
* @param writefds Write FDs to additionally check for in internal select()
* or NULL if not required.
* @param exceptfds Except FDs to additionally check for in internal select()
* or NULL if not required.
*
*
* @return Number of milliseconds spent in coap_io_process_with_fds, or @c -1
* if there was an error. If defined, readfds, writefds, exceptfds
* are updated as returned by the internal select() call.
*/
int coap_io_process_with_fds(coap_context_t *ctx, unsigned int timeout_ms,
int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds);
/**
* Iterates through all the coap_socket_t structures embedded in endpoints or
* sessions associated with the @p ctx to determine which are wanting any
* read, write, accept or connect I/O (COAP_SOCKET_WANT_xxx is set). If set,
* the coap_socket_t is added to the @p sockets.
*
* Any now timed out delayed packet is transmitted, along with any packets
* associated with requested observable response.
*
* In addition, it returns when the next expected I/O is expected to take place
* (e.g. a packet retransmit).
*
* Prior to calling coap_io_do_io(), the @p sockets must be tested to see
* if any of the COAP_SOCKET_WANT_xxx have the appropriate information and if
* so, COAP_SOCKET_CAN_xxx is set. This typically will be done after using a
* select() call.
*
* Note: If epoll support is compiled into libcoap, coap_io_prepare_epoll() must
* be used instead of coap_io_prepare_io().
*
* Internal function.
*
* @param ctx The CoAP context
* @param sockets Array of socket descriptors, filled on output
* @param max_sockets Size of socket array.
* @param num_sockets Pointer to the number of valid entries in the socket
* arrays on output.
* @param now Current time.
*
* @return timeout Maxmimum number of milliseconds that can be used by a
* select() to wait for network events or 0 if wait should be
* forever.
*/
unsigned int
coap_io_prepare_io(coap_context_t *ctx,
coap_socket_t *sockets[],
unsigned int max_sockets,
unsigned int *num_sockets,
coap_tick_t now
);
/**
* @deprecated Use coap_io_prepare_io() instead.
*
* This function just calls coap_io_prepare_io().
*
* Internal function.
*
* @param ctx The CoAP context
* @param sockets Array of socket descriptors, filled on output
* @param max_sockets Size of socket array.
* @param num_sockets Pointer to the number of valid entries in the socket
* arrays on output.
* @param now Current time.
*
* @return timeout Maxmimum number of milliseconds that can be used by a
* select() to wait for network events or 0 if wait should be
* forever.
*/
COAP_STATIC_INLINE COAP_DEPRECATED unsigned int
coap_write(coap_context_t *ctx,
coap_socket_t *sockets[],
unsigned int max_sockets,
unsigned int *num_sockets,
coap_tick_t now
) {
return coap_io_prepare_io(ctx, sockets, max_sockets, num_sockets, now);
}
/**
* Processes any outstanding read, write, accept or connect I/O as indicated
* in the coap_socket_t structures (COAP_SOCKET_CAN_xxx set) embedded in
* endpoints or sessions associated with @p ctx.
*
* Note: If epoll support is compiled into libcoap, coap_io_do_epoll() must
* be used instead of coap_io_do_io().
*
* Internal function.
*
* @param ctx The CoAP context
* @param now Current time
*/
void coap_io_do_io(coap_context_t *ctx, coap_tick_t now);
/**
* @deprecated Use coap_io_do_io() instead.
*
* This function just calls coap_io_do_io().
*
* Internal function.
*
* @param ctx The CoAP context
* @param now Current time
*/
COAP_STATIC_INLINE COAP_DEPRECATED void
coap_read(coap_context_t *ctx, coap_tick_t now
) {
coap_io_do_io(ctx, now);
}
/**
* Any now timed out delayed packet is transmitted, along with any packets
* associated with requested observable response.
*
* In addition, it returns when the next expected I/O is expected to take place
* (e.g. a packet retransmit).
*
* Note: If epoll support is compiled into libcoap, coap_io_prepare_epoll() must
* be used instead of coap_io_prepare_io().
*
* Internal function.
*
* @param ctx The CoAP context
* @param now Current time.
*
* @return timeout Maxmimum number of milliseconds that can be used by a
* epoll_wait() to wait for network events or 0 if wait should be
* forever.
*/
unsigned int
coap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now);
struct epoll_event;
/**
* Process all the epoll events
*
* Note: If epoll support is compiled into libcoap, coap_io_do_epoll() must
* be used instead of coap_io_do_io().
*
* Internal function
*
* @param ctx The current CoAP context.
* @param events The list of events returned from an epoll_wait() call.
* @param nevents The number of events.
*
*/
void coap_io_do_epoll(coap_context_t *ctx, struct epoll_event* events,
size_t nevents);
/**@}*/
#endif /* COAP_NET_H_ */
+4 -3
View File
@@ -79,7 +79,11 @@ global:
coap_hash_impl;
coap_insert_node;
coap_insert_optlist;
coap_io_do_epoll;
coap_io_do_io;
coap_io_prepare_epoll;
coap_io_prepare_io;
coap_io_process;
coap_io_process_with_fds;
coap_is_mcast;
coap_join_mcast_group;
@@ -137,7 +141,6 @@ global:
coap_print_addr;
coap_print_link;
coap_print_wellknown;
coap_read;
coap_register_async;
coap_register_event_handler;
coap_register_handler;
@@ -149,7 +152,6 @@ global:
coap_resource_unknown_init;
coap_response_phrase;
coap_retransmit;
coap_run_once;
coap_send;
coap_send_ack;
coap_send_error;
@@ -199,7 +201,6 @@ global:
coap_touch_observer;
coap_wait_ack;
coap_wellknown_response;
coap_write;
coap_write_block_opt;
local:
*;
+4 -3
View File
@@ -77,7 +77,11 @@ coap_handle_failed_notify
coap_hash_impl
coap_insert_node
coap_insert_optlist
coap_io_do_epoll
coap_io_do_io
coap_io_prepare_epoll
coap_io_prepare_io
coap_io_process
coap_io_process_with_fds
coap_is_mcast
coap_join_mcast_group
@@ -135,7 +139,6 @@ coap_pop_next
coap_print_addr
coap_print_link
coap_print_wellknown
coap_read
coap_register_async
coap_register_event_handler
coap_register_handler
@@ -147,7 +150,6 @@ coap_resource_set_dirty
coap_resource_unknown_init
coap_response_phrase
coap_retransmit
coap_run_once
coap_send
coap_send_ack
coap_send_error
@@ -197,5 +199,4 @@ coap_tls_is_supported
coap_touch_observer
coap_wait_ack
coap_wellknown_response
coap_write
coap_write_block_opt
+112 -32
View File
@@ -10,14 +10,15 @@ coap_io(3)
NAME
----
coap_io, coap_run_once, coap_io_process_with_fds, coap_context_get_coap_fd
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
- Work with CoAP I/O to do the packet send and receives
SYNOPSIS
--------
*#include <coap@LIBCOAP_API_VERSION@/coap.h>*
*int coap_run_once(coap_context_t *_context_, unsigned int _timeout_ms_)*;
*int coap_io_process(coap_context_t *_context_, unsigned int _timeout_ms_)*;
*int coap_io_process_with_fds(coap_context_t *_context_,
unsigned int _timeout_ms_, int _nfds_, fd_set *_readfds_, fd_set *_writefds_,
@@ -25,6 +26,18 @@ fd_set *_exceptfds_)*;
*int coap_context_get_coap_fd(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_)*;
*int coap_io_do_epoll(coap_context_t *_context_, struct epoll_event *_events_,
size_t _nevents_)*
Link with *-lcoap-@LIBCOAP_API_VERSION@*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*,
*-lcoap-@LIBCOAP_API_VERSION@-openssl* or
*-lcoap-@LIBCOAP_API_VERSION@-tinydtls* depending on your (D)TLS library
@@ -36,39 +49,92 @@ 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_run_once*() function will process any outstanding packets to send
for the specified _context_ and wait for processing any input packets for up to
_timeout_ms_ milli-seconds before returning. Once any outstanding input packets
have been processed, the function will return. There are 2 special case
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_RUN_BLOCK 0
#define COAP_RUN_NONBLOCK 1
----
If _timeout_ms_ is set to COAP_RUN_BLOCK, then *coap_run_once*() will wait
indefinitely for the first new input packet to come in. If _timeout_ms_ is set
to COAP_RUN_NONBLOCK, then there is no wait if there are no more input packets.
If _timeout_ms_ is set to COAP_RUN_BLOCK, then *coap_io_process*() will wait
indefinitely for the first new input packet to come in, or for when to
re-transmit a packet. If _timeout_ms_ is set to COAP_RUN_NONBLOCK, then there
is no wait if there is no more input or output to process.
There are two methods of how to call *coap_run_once*().
There are two methods of how to call *coap_io_process*().
1. Have *coap_run_once*() called from within a while() loop. Under idle
conditions (no input traffic) *coap_run_once*() will then get called every
_timeout_ms_, but more frequently if there is input traffic.
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() or an event returned by epoll_wait(). If 'read' is available on
the file descriptor, call *coap_run_once*() with _timeout_ms_ set to
COAP_RUN_NONBLOCK. See EXAMPLES below.
using *select*() or an event returned by epoll_wait(). If 'read' is available on
the file descriptor, call *coap_io_process*() with _timeout_ms_ set to
COAP_RUN_NONBLOCK. +
*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.
NOTE: This method is only available for environments that support epoll
(mostly Linux) 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_with_fds*() function is the same as *coap_run_once*()
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
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
@@ -81,24 +147,26 @@ if there is no epoll support in libcoap. If there is epoll support, then
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
_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.
RETURN VALUES
-------------
*coap_run_once*() and *coap_io_process_with_fds*() returns the time, in
*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 supported by the host
environment.
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.
EXAMPLES
--------
*Method One - coap_run_once*
*Method One - use coap_io_process()*
[source, c]
----
@@ -109,6 +177,9 @@ int main(int argc, char *argv[]){
coap_context_t *ctx = NULL;
unsigned wait_ms;
(void)argc;
(void)argv;
/* Create the libcoap context */
ctx = coap_new_context(NULL);
if (!ctx) {
@@ -120,7 +191,7 @@ int main(int argc, char *argv[]){
wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;
while (1) {
int result = coap_run_once(ctx, wait_ms);
int result = coap_io_process(ctx, wait_ms);
if (result < 0) {
/* There is an internal issue */
break;
@@ -149,6 +220,9 @@ int main(int argc, char *argv[]){
fd_set readfds;
int nfds = 0;
(void)argc;
(void)argv;
/* Create the libcoap context */
ctx = coap_new_context(NULL);
if (!ctx) {
@@ -181,7 +255,7 @@ int main(int argc, char *argv[]){
}
----
*Method Two - select*
*Method Two - select() based on monitorable file descriptor*
[source, c]
----
@@ -196,6 +270,9 @@ int main(int argc, char *argv[]){
fd_set m_readfds;
int nfds;
(void)argc;
(void)argv;
/* Create the libcoap context */
ctx = coap_new_context(NULL);
if (!ctx) {
@@ -224,7 +301,7 @@ int main(int argc, char *argv[]){
}
if (result > 0) {
if (FD_ISSET(coap_fd, &readfds)) {
result = coap_run_once(ctx, COAP_RUN_NONBLOCK);
result = coap_io_process(ctx, COAP_RUN_NONBLOCK);
if (result < 0) {
/* There is an internal issue */
break;
@@ -242,7 +319,7 @@ int main(int argc, char *argv[]){
}
----
*Method Two - epoll*
*Method Two - epoll_wait() based on monitorable file descriptor*
[source, c]
----
@@ -264,6 +341,9 @@ int main(int argc, char *argv[]){
int nevents;
int i;
(void)argc;
(void)argv;
/* Create the libcoap context */
ctx = coap_new_context(NULL);
if (!ctx) {
@@ -297,7 +377,7 @@ int main(int argc, char *argv[]){
}
for (i = 0; i < nevents; i++) {
if (events[i].data.fd == coap_fd) {
result = coap_run_once(ctx, COAP_RUN_NONBLOCK);
result = coap_io_process(ctx, COAP_RUN_NONBLOCK);
if (result < 0) {
/* There is an internal issue */
break;
+3 -3
View File
@@ -70,7 +70,7 @@ appropriate GET handler within the server application is called to fill in the
response packet with the appropriate information. This "fake GET request" is
triggered by a call to *coap_resource_notify_observers*().
The call to *coap_run_once*() in the main server application i/o loop will do
The call to *coap_io_process*() in the main server application i/o loop will do
all the necessary processing of sending any outstanding "fake GET requests".
Whenever the server sends a copy of the state of the "observed" resource to
@@ -286,7 +286,7 @@ int main(int argc, char *argv[]){
wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;
while (1) {
int result = coap_run_once( ctx, wait_ms );
int result = coap_io_process( ctx, wait_ms );
if ( result < 0 ) {
break;
} else if ( result && (unsigned)result < wait_ms ) {
@@ -296,7 +296,7 @@ int main(int argc, char *argv[]){
/*
* result == 0, or result >= wait_ms
* (wait_ms could have decremented to a small value, below
* the granularity of the timer in coap_run_once() and hence
* the granularity of the timer in coap_io_process() and hence
* result == 0)
*/
time_t t_now = time(NULL);
+17 -15
View File
@@ -945,6 +945,8 @@ error:
return -1;
}
#if !defined(WITH_CONTIKI)
unsigned int
coap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now) {
#ifndef COAP_EPOLL_SUPPORT
@@ -960,7 +962,7 @@ coap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now) {
unsigned int timeout;
/* Use the common logic */
timeout = coap_write(ctx, sockets, max_sockets, &num_sockets, now);
timeout = coap_io_prepare_io(ctx, sockets, max_sockets, &num_sockets, now);
/* Save when the next expected I/O is to take place */
ctx->next_timeout = timeout ? now + timeout : 0;
if (ctx->eptimerfd != -1) {
@@ -989,10 +991,8 @@ coap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now) {
#endif /* COAP_EPOLL_SUPPORT */
}
#if !defined(WITH_CONTIKI)
unsigned int
coap_write(coap_context_t *ctx,
coap_io_prepare_io(coap_context_t *ctx,
coap_socket_t *sockets[],
unsigned int max_sockets,
unsigned int *num_sockets,
@@ -1174,7 +1174,7 @@ coap_write(coap_context_t *ctx,
}
int
coap_run_once(coap_context_t *ctx, unsigned timeout_ms) {
coap_io_process(coap_context_t *ctx, unsigned timeout_ms) {
return coap_io_process_with_fds(ctx, timeout_ms, 0, NULL, NULL, NULL);
}
@@ -1212,7 +1212,9 @@ coap_io_process_with_fds(coap_context_t *ctx, unsigned int timeout_ms,
coap_ticks(&before);
#ifndef COAP_EPOLL_SUPPORT
timeout = coap_write(ctx, sockets, (unsigned int)(sizeof(sockets) / sizeof(sockets[0])), &num_sockets, before);
timeout = coap_io_prepare_io(ctx, sockets,
(sizeof(sockets) / sizeof(sockets[0])),
&num_sockets, before);
if (timeout == 0 || timeout_ms < timeout)
timeout = timeout_ms;
@@ -1293,7 +1295,7 @@ coap_io_process_with_fds(coap_context_t *ctx, unsigned int timeout_ms,
}
coap_ticks(&now);
coap_read(ctx, now);
coap_io_do_io(ctx, now);
if (ereadfds) {
*ereadfds = readfds;
}
@@ -1334,7 +1336,7 @@ coap_io_process_with_fds(coap_context_t *ctx, unsigned int timeout_ms,
break;
}
coap_io_do_events(ctx, events, nfds);
coap_io_do_epoll(ctx, events, nfds);
/*
* reset to COAP_RUN_NONBLOCK (which causes etimeout to become 0)
@@ -1357,23 +1359,23 @@ coap_io_process_with_fds(coap_context_t *ctx, unsigned int timeout_ms,
}
#else /* WITH_CONTIKI */
int coap_run_once(coap_context_t *ctx, unsigned int timeout_ms) {
int coap_io_process(coap_context_t *ctx, unsigned int timeout_ms) {
coap_tick_t now;
coap_ticks(&now);
/* There is something to read on the endpoint */
ctx->endpoint->sock.flags |= COAP_SOCKET_CAN_READ;
/* read in, and send off any responses */
coap_read(ctx, now); /* read received data */
coap_io_do_io(ctx, now); /* read received data */
return -1;
}
unsigned int
coap_write(coap_context_t *ctx,
coap_socket_t *sockets[],
unsigned int max_sockets,
unsigned int *num_sockets,
coap_tick_t now)
coap_io_prepare(coap_context_t *ctx,
coap_socket_t *sockets[],
unsigned int max_sockets,
unsigned int *num_sockets,
coap_tick_t now)
{
*num_sockets = 0;
return 0;
+2 -2
View File
@@ -48,9 +48,9 @@ struct pbuf *coap_packet_extract_pbuf(coap_packet_t *packet)
*
* The current implementation deals this to coap_dispatch immediately, but
* other mechanisms (as storing the package in a queue and later fetching it
* when coap_read is called) can be envisioned.
* when coap_io_do_io is called) can be envisioned.
*
* It handles everything coap_read does on other implementations.
* It handles everything coap_io_do_io does on other implementations.
*/
static void coap_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
+6 -6
View File
@@ -1125,7 +1125,7 @@ coap_retransmit(coap_context_t *context, coap_queue_t *node) {
#ifdef WITH_LWIP
/* WITH_LWIP, this is handled by coap_recv in a different way */
void
coap_read(coap_context_t *ctx, coap_tick_t now) {
coap_io_do_io(coap_context_t *ctx, coap_tick_t now) {
return;
}
#else /* WITH_LWIP */
@@ -1419,12 +1419,12 @@ coap_accept_endpoint(coap_context_t *ctx, coap_endpoint_t *endpoint,
}
void
coap_read(coap_context_t *ctx, coap_tick_t now) {
coap_io_do_io(coap_context_t *ctx, coap_tick_t now) {
#ifdef COAP_EPOLL_SUPPORT
(void)ctx;
(void)now;
coap_log(LOG_EMERG,
"coap_read() requires libcoap not compiled for using epoll\n");
"coap_io_do_io() requires libcoap not compiled for using epoll\n");
#else /* ! COAP_EPOLL_SUPPORT */
coap_endpoint_t *ep, *tmp;
coap_session_t *s, *rtmp;
@@ -1476,17 +1476,17 @@ coap_read(coap_context_t *ctx, coap_tick_t now) {
}
/*
* While this code in part replicates coap_read(), doing the functions
* While this code in part replicates coap_io_do_io(), doing the functions
* directly saves having to iterate through the endpoints / sessions.
*/
void
coap_io_do_events(coap_context_t *ctx, struct epoll_event *events, size_t nevents) {
coap_io_do_epoll(coap_context_t *ctx, struct epoll_event *events, size_t nevents) {
#ifndef COAP_EPOLL_SUPPORT
(void)ctx;
(void)events;
(void)nevents;
coap_log(LOG_EMERG,
"coap_io_do_events() requires libcoap compiled for using epoll\n");
"coap_io_do_epoll() requires libcoap compiled for using epoll\n");
#else /* COAP_EPOLL_SUPPORT */
coap_tick_t now;
size_t j;
+1 -1
View File
@@ -57,7 +57,7 @@ coap_pdu_from_pbuf( struct pbuf *pbuf )
if (pbuf == NULL) return NULL;
LWIP_ASSERT("Can only deal with contiguous PBUFs", pbuf->tot_len == pbuf->len);
LWIP_ASSERT("coap_read needs to receive an exclusive copy of the incoming pbuf", pbuf->ref == 1);
LWIP_ASSERT("coap_io_do_io needs to receive an exclusive copy of the incoming pbuf", pbuf->ref == 1);
pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t) );
if (!pdu) {