simple_ctrl: Add timeout to blocking I/O
diff --git a/simple_ctrl.c b/simple_ctrl.c
index 6b1c8a8..1d3b250 100644
--- a/simple_ctrl.c
+++ b/simple_ctrl.c
@@ -36,12 +36,65 @@
#include "simple_ctrl.h"
+/***********************************************************************
+ * blocking I/O with timeout helpers
+ ***********************************************************************/
+
+static ssize_t read_timeout(int fd, void *buf, size_t count, uint32_t tout_msec)
+{
+ struct timeval tout;
+ fd_set readset;
+ int rc;
+
+ FD_ZERO(&readset);
+ FD_SET(fd, &readset);
+ tout.tv_sec = tout_msec/1000;
+ tout.tv_usec = (tout_msec%1000)*1000;
+
+ rc = select(fd+1, &readset, NULL, NULL, &tout);
+ if (rc < 0)
+ return rc;
+
+ if (FD_ISSET(fd, &readset))
+ return read(fd, buf, count);
+
+ return -ETIMEDOUT;
+}
+
+static ssize_t write_timeout(int fd, const void *buf, size_t count, uint32_t tout_msec)
+{
+ struct timeval tout;
+ fd_set writeset;
+ int rc;
+
+ FD_ZERO(&writeset);
+ FD_SET(fd, &writeset);
+ tout.tv_sec = tout_msec/1000;
+ tout.tv_usec = (tout_msec%1000)*1000;
+
+ rc = select(fd+1, NULL, &writeset, NULL, &tout);
+ if (rc < 0)
+ return rc;
+
+ if (FD_ISSET(fd, &writeset))
+ return write(fd, buf, count);
+
+ return -ETIMEDOUT;
+}
+
+
+/***********************************************************************
+ * actual CTRL client API
+ ***********************************************************************/
+
struct simple_ctrl_handle {
int fd;
uint32_t next_id;
+ uint32_t tout_msec;
};
-struct simple_ctrl_handle *simple_ctrl_open(void *ctx, const char *host, uint16_t dport)
+struct simple_ctrl_handle *simple_ctrl_open(void *ctx, const char *host, uint16_t dport,
+ uint32_t tout_msec)
{
struct simple_ctrl_handle *sch;
int rc;
@@ -58,6 +111,7 @@
return NULL;
}
sch->fd = rc;
+ sch->tout_msec = tout_msec;
return sch;
}
@@ -73,8 +127,11 @@
struct msgb *resp;
int rc, len;
- rc = read(sch->fd, (uint8_t *) &hh, sizeof(hh));
- if (rc != sizeof(hh)) {
+ rc = read_timeout(sch->fd, (uint8_t *) &hh, sizeof(hh), sch->tout_msec);
+ if (rc < 0) {
+ fprintf(stderr, "CTRL: Error during read: %d\n", rc);
+ return NULL;
+ } else if (rc < sizeof(hh)) {
fprintf(stderr, "CTRL: ERROR: short read (header)\n");
return NULL;
}
@@ -130,12 +187,14 @@
ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_CTRL);
ipa_prepend_header(msg, IPAC_PROTO_OSMO);
- rc = write(sch->fd, msg->data, msg->len);
-
- if (rc < msg->len) {
+ rc = write_timeout(sch->fd, msg->data, msg->len, sch->tout_msec);
+ if (rc < 0) {
+ fprintf(stderr, "CTRL: Error during write: %d\n", rc);
+ return rc;
+ } else if (rc < msg->len) {
fprintf(stderr, "CTRL: ERROR: short write\n");
msgb_free(msg);
- return rc;
+ return -1;
} else {
msgb_free(msg);
return 0;
@@ -172,6 +231,8 @@
return NULL;
}
resp = simple_ctrl_xceive(sch, msg);
+ if (!resp)
+ return NULL;
rc = sscanf(msgb_l2(resp), "GET_REPLY %u %ms %ms", &rx_id, &rx_var, &rx_val);
if (rc == 3) {