aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrumeet <yuuta@yuuta.moe>2022-07-22 20:00:17 -0700
committerTrumeet <yuuta@yuuta.moe>2022-07-22 20:00:17 -0700
commit5995bcf5f672bc96f49ce7bde53ee864b5fe1e14 (patch)
tree210ab887b58ec2bc68730931da1848d292a25b48
parent78d23828d7024a827135eb824e77e7bbf63bc065 (diff)
downloadacron-5995bcf5f672bc96f49ce7bde53ee864b5fe1e14.tar
acron-5995bcf5f672bc96f49ce7bde53ee864b5fe1e14.tar.gz
acron-5995bcf5f672bc96f49ce7bde53ee864b5fe1e14.tar.bz2
acron-5995bcf5f672bc96f49ce7bde53ee864b5fe1e14.zip
feat(libacron): ac_receive(): support setting a timeout
API:ADD Signed-off-by: Trumeet <yuuta@yuuta.moe>
-rw-r--r--client/libacron/acronc/main.c2
-rw-r--r--client/libacron/include/net.h3
-rw-r--r--client/libacron/net.c24
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 <math.h>
#ifdef WIN32
+#include <windows.h> /* For DWORD */
#include <winsock2.h>
#include <ws2tcpip.h>
#define errno_sock WSAGetLastError()
@@ -29,6 +30,7 @@
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
+#include <sys/time.h>
#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;