From 5995bcf5f672bc96f49ce7bde53ee864b5fe1e14 Mon Sep 17 00:00:00 2001 From: Trumeet Date: Fri, 22 Jul 2022 20:00:17 -0700 Subject: feat(libacron): ac_receive(): support setting a timeout API:ADD Signed-off-by: Trumeet --- client/libacron/acronc/main.c | 2 +- client/libacron/include/net.h | 3 ++- client/libacron/net.c | 24 +++++++++++++++++++++++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/client/libacron/acronc/main.c b/client/libacron/acronc/main.c index ff19f39..cbc359e 100644 --- a/client/libacron/acronc/main.c +++ b/client/libacron/acronc/main.c @@ -173,7 +173,7 @@ int main(int argc, char **argv) { ac_free(); return r; } - while (!(r = ac_receive(connection, &obj))) { + while (!(r = ac_receive(connection, &obj, 10))) { if (!obj) { continue; } diff --git a/client/libacron/include/net.h b/client/libacron/include/net.h index 398450d..5cf8f67 100644 --- a/client/libacron/include/net.h +++ b/client/libacron/include/net.h @@ -41,8 +41,9 @@ LIBAC_EXPORT int ac_disconnect(void *connection); * Blocks the current thread until a new response or event arrives. * @param connection A non-NULL and connected connection passed as-is from ac_connect. * @param response Output response of either an event or a response. May be NULL even if it succeeds. + * @param timeout Read timeout in seconds. Set to 0 to wait infinitely. * @return AC_E_OK or an error code. When failed, *response is NULL. */ -LIBAC_EXPORT int ac_receive(void *connection, ac_obj_t **response); +LIBAC_EXPORT int ac_receive(void *connection, ac_obj_t **response, long timeout); #endif /* LIBAC_NET_H */ diff --git a/client/libacron/net.c b/client/libacron/net.c index 7ac3bda..bbfb465 100644 --- a/client/libacron/net.c +++ b/client/libacron/net.c @@ -21,6 +21,7 @@ #include #ifdef WIN32 +#include /* For DWORD */ #include #include #define errno_sock WSAGetLastError() @@ -29,6 +30,7 @@ #include #include #include +#include #endif static void conn_free(struct ac_connection *conn) { @@ -289,7 +291,7 @@ int ac_disconnect(void *connection) { return AC_E_OK; } -int ac_receive(void *connection, ac_obj_t **response) { +int ac_receive(void *connection, ac_obj_t **response, long timeout) { AC_CHECK_INIT; struct ac_connection *conn = connection; struct wic_inst *inst = &conn->inst; @@ -298,11 +300,31 @@ int ac_receive(void *connection, ac_obj_t **response) { int bytes; size_t retval, pos; +#ifdef WIN32 + DWORD to = timeout * 1000; + if (setsockopt(conn->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&to, sizeof to)) { +#else + struct timeval tv; + tv.tv_sec = timeout; + tv.tv_usec = 0; + if (setsockopt(conn->fd, SOL_SOCKET, SO_RCVTIMEO, (const char *) &tv, sizeof tv)) { +#endif + const int e = errno_sock; + LOGEV("Failed to call setsockopt(3): %s (%d).", + strerror2(e), + e); + return AC_E_INTERNAL; + } + if ((bytes = (int) recv(conn->fd, buffer, sizeof(buffer), 0)) <= 0) { LOGDV("recv(%d) = %d", conn->fd, bytes); if (bytes < 0) { const int e = errno_sock; +#ifdef WIN32 + if (e == WSAETIMEDOUT) { +#else if (e == EAGAIN) { +#endif /* Timeout */ *response = NULL; return AC_E_OK; -- cgit v1.2.3