aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-06-04 11:52:39 +0200
committerHarald Welte <laforge@gnumonks.org>2018-06-04 22:02:45 +0200
commit0e9d3693b384711821deddf988ec6325f8c646fe (patch)
tree850ebb8447fee27737986e86f183794c06ba06ce
parent3e5ab696b6e4eb638e4b5b06e120baff320f0a40 (diff)
simple_ctrl: Add timeout to blocking I/O
-rw-r--r--Makefile2
-rw-r--r--osmo-ctrl-client.c2
-rw-r--r--simple_ctrl.c75
-rw-r--r--simple_ctrl.h3
4 files changed, 72 insertions, 10 deletions
diff --git a/Makefile b/Makefile
index aad62b5..176597b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
LDFLAGS:=-losmocore -losmogsm -ltalloc
-CFLAGS:=-Wall
+CFLAGS:=-Wall -g
osmo-ctrl-client: osmo-ctrl-client.o simple_ctrl.o
$(CC) $(LDFLAGS) -o $@ $^
diff --git a/osmo-ctrl-client.c b/osmo-ctrl-client.c
index 463bffe..e9ea45a 100644
--- a/osmo-ctrl-client.c
+++ b/osmo-ctrl-client.c
@@ -53,7 +53,7 @@ int main(int argc, char **argv)
osmo_init_logging2(NULL, &log_info);
- sch = simple_ctrl_open(NULL, host, port);
+ sch = simple_ctrl_open(NULL, host, port, 1000);
if (!sch)
exit(1);
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 @@ struct simple_ctrl_handle *simple_ctrl_open(void *ctx, const char *host, uint16_
return NULL;
}
sch->fd = rc;
+ sch->tout_msec = tout_msec;
return sch;
}
@@ -73,8 +127,11 @@ static struct msgb *simple_ipa_receive(struct simple_ctrl_handle *sch)
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 @@ static int simple_ctrl_send(struct simple_ctrl_handle *sch, struct msgb *msg)
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 @@ char *simple_ctrl_get(struct simple_ctrl_handle *sch, const char *var)
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) {
diff --git a/simple_ctrl.h b/simple_ctrl.h
index e45479f..e1577a4 100644
--- a/simple_ctrl.h
+++ b/simple_ctrl.h
@@ -4,7 +4,8 @@
struct simple_ctrl_handle;
-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);
void simple_ctrl_close(struct simple_ctrl_handle *sch);
char *simple_ctrl_get(struct simple_ctrl_handle *sch, const char *var);