diff --git a/include/coap3/coap_net.h b/include/coap3/coap_net.h index 3349d860f7..ceb639df07 100644 --- a/include/coap3/coap_net.h +++ b/include/coap3/coap_net.h @@ -845,6 +845,26 @@ COAP_API void coap_io_do_epoll(coap_context_t *ctx, struct epoll_event *events, */ COAP_API coap_fd_t coap_socket_get_fd(coap_socket_t *socket); +/* + * Get the current libcoap usage of file descriptors that are in a read or write pending state. + * + * @param context The current CoAP context. + * @param read_fds Array to populate with file descriptors in the read pending state. + * @param have_read_fds Updated wth the number of fds found in read pending state. + * @param max_read_fds Maximum size of read_fds[] array. + * @param write_fds Array to populate with file descriptors in the write pending state. + * @param have_write_fds Updated wth the number of fds found in write pending state. + * @param max_write_fds Maximum size of write_fds[] array. + * + * @return @c 1 if successful, else @c 0 if error. + */ +COAP_API unsigned int coap_io_get_fds(coap_context_t *context, coap_fd_t read_fds[], + unsigned int *have_read_fds, + unsigned int max_read_fds, + coap_fd_t write_fds[], + unsigned int *have_write_fds, + unsigned int max_write_dfs); + /** * Get the libcoap internal flags for a socket. This can be used to * integrate libcoap in an external event loop instead of using one of its diff --git a/include/coap3/coap_net_internal.h b/include/coap3/coap_net_internal.h index e4573579a0..c1812508c8 100644 --- a/include/coap3/coap_net_internal.h +++ b/include/coap3/coap_net_internal.h @@ -779,6 +779,28 @@ int coap_io_process_with_fds_lkd(coap_context_t *ctx, uint32_t timeout_ms, fd_set *exceptfds); #endif /* ! RIOT_VERSION && ! WITH_CONTIKI */ +/* + * Get the current libcoap usage of file descriptors that are in a read or write pending state. + * + * Note: This function must be called in the locked state. + * + * @param context The current CoAP context. + * @param read_fds Array to populate with file descriptors in the read pending state. + * @param have_read_fds Updated wth the number of fds found in read pending state. + * @param max_read_fds Maximum size of read_fds[] array. + * @param write_fds Array to populate with file descriptors in the write pending state. + * @param have_write_fds Updated wth the number of fds found in write pending state. + * @param max_write_fds Maximum size of write_fds[] array. + * + * @return @c 1 if successful, else @c 0 if error. + */ +unsigned int coap_io_get_fds_lkd(coap_context_t *context, coap_fd_t read_fds[], + unsigned int *have_read_fds, + unsigned int max_read_fds, + coap_fd_t write_fds[], + unsigned int *have_write_fds, + unsigned int max_write_dfs); + /** * Sends a CoAP message to given peer. The memory that is * allocated for the pdu will be released by coap_send_lkd(). diff --git a/libcoap-3.map b/libcoap-3.map index 9c7493a6aa..85c35e53ed 100644 --- a/libcoap-3.map +++ b/libcoap-3.map @@ -123,6 +123,7 @@ global: coap_insert_optlist; coap_io_do_epoll; coap_io_do_io; + coap_io_get_fds; coap_io_pending; coap_io_prepare_epoll; coap_io_prepare_io; diff --git a/libcoap-3.sym b/libcoap-3.sym index 611933f630..79680b9d27 100644 --- a/libcoap-3.sym +++ b/libcoap-3.sym @@ -121,6 +121,7 @@ coap_host_is_unix_domain coap_insert_optlist coap_io_do_epoll coap_io_do_io +coap_io_get_fds coap_io_pending coap_io_prepare_epoll coap_io_prepare_io diff --git a/man/Makefile.am b/man/Makefile.am index b62f25c39d..983c76cc46 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -135,6 +135,7 @@ install-man: install-man3 install-man5 install-man7 @echo ".so man3/coap_deprecated.3" > coap_set_event_handler.3 @echo ".so man3/coap_deprecated.3" > coap_write.3 @echo ".so man3/coap_io.3" > coap_io_pending.3 + @echo ".so man3/coap_io.3" > coap_io_get_fds.3 @echo ".so man3/coap_io.3" > coap_can_exit.3 @echo ".so man3/coap_io.3" > coap_socket_get_fd.3 @echo ".so man3/coap_io.3" > coap_socket_get_flags.3 diff --git a/man/coap_io.txt.in b/man/coap_io.txt.in index 48155e3762..2baf3541f7 100644 --- a/man/coap_io.txt.in +++ b/man/coap_io.txt.in @@ -19,6 +19,7 @@ coap_io_do_io, coap_io_prepare_epoll, coap_io_do_epoll, coap_io_pending, +coap_io_get_fds, coap_can_exit, coap_socket_get_fd, coap_socket_get_flags, @@ -51,6 +52,10 @@ size_t _nevents_)*; *int coap_io_pending(coap_context_t *_context_)*; +*unsigned int coap_io_get_fds(coap_context_t *_context_, coap_fd_t _read_fds_[], +unsigned int *_have_read_fds_, unsigned int _max_read_fds_, coap_fd_t _write_fds_[], +unsigned int *_have_write_fds_, unsigned int _max_write_dfs_)*; + *int coap_can_exit(coap_context_t *_context_)*; *coap_fd_t coap_socket_get_fd(coap_socket_t *socket);* @@ -69,7 +74,7 @@ or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with 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 +underlying CoAP and (D)TLS need to send (and possibly re-send) created packets as well as receive packets for processing. The *coap_io_process*() function is the primary function applications should @@ -204,6 +209,19 @@ 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_io_get_fds()* + +The *coap_io_get_fds*() function is used to get all of the libcoap internally +used file descriptors associated with _context_ in a read or write pending state. + +_read_fds_[] is a defined array to hold all the file descriptors that are in a +read pending state with a size of _max_read_fds_. _have_read_fds_ is returned +with the number of file descriptors in _read_fds_[]. + +_write_fds_[] is a defined array to hold all the file descriptors that are in a +write pending state with a size of _max_write_fds_. _have_write_fds_ is returned +with the number of file descriptors in _write_fds_[]. + *Function: coap_can_exit()* The *coap_can_exit*() function checks to see if there are any outstanding @@ -241,6 +259,8 @@ 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_io_get_fds*() returns 1 if file descriptors returned, else returns 0. + *coap_can_exit*() returns 1 if there is nothing outstanding to transmit else returns 0. diff --git a/src/coap_io.c b/src/coap_io.c index 1b16945d07..f413797109 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -1576,6 +1576,106 @@ coap_io_prepare_io_lkd(coap_context_t *ctx, return (unsigned int)((timeout * 1000 + COAP_TICKS_PER_SECOND - 1) / COAP_TICKS_PER_SECOND); } +/* + * return 0 Insufficient space to hold fds, or fds not supported + * 1 All fds found + */ +COAP_API unsigned int +coap_io_get_fds(coap_context_t *ctx, + coap_fd_t read_fds[], + unsigned int *have_read_fds, + unsigned int max_read_fds, + coap_fd_t write_fds[], + unsigned int *have_write_fds, + unsigned int max_write_fds) { + unsigned int ret; + + coap_lock_lock(ctx, return 0); + ret = coap_io_get_fds_lkd(ctx, read_fds, have_read_fds, max_read_fds, write_fds, + have_write_fds, max_write_fds); + coap_lock_unlock(ctx); + return ret; +} + +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION) +static int +coap_add_fd(coap_fd_t fd, coap_fd_t this_fds[], unsigned int *have_this_fds, + unsigned int max_this_fds) { + if (*have_this_fds < max_this_fds) { + this_fds[(*have_this_fds)++] = fd; + return 1; + } + coap_log_warn("coap_io_get_fds: Insufficient space for new fd (%u >= %u)\n", *have_this_fds, + max_this_fds); + return 0; +} + +/* + * return 0 Insufficient space to hold fds, or fds not supported + * 1 All fds found + */ +unsigned int +coap_io_get_fds_lkd(coap_context_t *ctx, + coap_fd_t read_fds[], + unsigned int *have_read_fds, + unsigned int max_read_fds, + coap_fd_t write_fds[], + unsigned int *have_write_fds, + unsigned int max_write_fds) { + *have_read_fds = 0; + *have_write_fds = 0; + +#ifdef COAP_EPOLL_SUPPORT + if (!coap_add_fd(ctx->epfd, read_fds, have_read_fds, max_read_fds)) + return 0; + if (!coap_add_fd(ctx->epfd, write_fds, have_write_fds, max_write_fds)) + return 0; + return 1; +#else /* ! COAP_EPOLL_SUPPORT */ + unsigned int i; + + for (i = 0; i < ctx->num_sockets; i++) { + if (ctx->sockets[i]->flags & (COAP_SOCKET_WANT_READ|COAP_SOCKET_WANT_ACCEPT)) { + if (!coap_add_fd(ctx->sockets[i]->fd, read_fds, have_read_fds, max_read_fds)) + return 0; + } + if (ctx->sockets[i]->flags & (COAP_SOCKET_WANT_WRITE|COAP_SOCKET_WANT_CONNECT)) { + if (!coap_add_fd(ctx->sockets[i]->fd, write_fds, have_write_fds, max_write_fds)) + return 0; + } + } + return 1; +#endif /* ! COAP_EPOLL_SUPPORT */ +} + +#else /* ! WITH_LWIP && ! WITH_CONTIKI && ! RIOT_VERSION*/ + +/* + * return 0 Insufficient space to hold fds, or fds not supported + * 1 All fds found + */ +unsigned int +coap_io_get_fds_lkd(coap_context_t *ctx, + coap_fd_t read_fds[], + unsigned int *have_read_fds, + unsigned int max_read_fds, + coap_fd_t write_fds[], + unsigned int *have_write_fds, + unsigned int max_write_fds) { + (void)ctx; + (void)read_fds; + (void)max_read_fds; + (void)write_fds; + (void)max_write_fds; + + *have_read_fds = 0; + *have_write_fds = 0; + + coap_log_warn("coap_io_get_fds: Not supported\n"); + return 0; +} +#endif /* WITH_LWIP || WITH_CONTIKI && ! RIOT_VERSION*/ + #if !defined(WITH_LWIP) && !defined(CONTIKI) && !defined(RIOT_VERSION) COAP_API int coap_io_process(coap_context_t *ctx, uint32_t timeout_ms) {