Code

client: Make I/O handling more flexible.
[sysdb.git] / src / client / sock.c
index d4596cd7a858cda76e1144492c5e2cf71c11291b..336d0620539531e0428525ad3607a52b1315405e 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <arpa/inet.h>
 
+#include <assert.h>
 #include <errno.h>
 #include <limits.h>
 
@@ -58,12 +59,27 @@ struct sdb_client {
        char *address;
        int   fd;
        bool  eof;
+
+       ssize_t (*read)(sdb_client_t *, sdb_strbuf_t *, size_t);
+       ssize_t (*write)(sdb_client_t *, const void *, size_t);
 };
 
 /*
  * private helper functions
  */
 
+static ssize_t
+client_read(sdb_client_t *client, sdb_strbuf_t *buf, size_t n)
+{
+       return sdb_strbuf_read(buf, client->fd, n);
+} /* client_read */
+
+static ssize_t
+client_write(sdb_client_t *client, const void *buf, size_t n)
+{
+       return sdb_write(client->fd, n, buf);
+} /* client_write */
+
 static int
 connect_unixsock(sdb_client_t *client, const char *address)
 {
@@ -112,6 +128,9 @@ sdb_client_create(const char *address)
        client->fd = -1;
        client->eof = 1;
 
+       client->read = client_read;
+       client->write = client_write;
+
        client->address = strdup(address);
        if (! client->address) {
                sdb_client_destroy(client);
@@ -256,7 +275,7 @@ sdb_client_send(sdb_client_t *client,
        if (sdb_proto_marshal(buf, sizeof(buf), cmd, msg_len, msg) < 0)
                return -1;
 
-       return sdb_write(client->fd, sizeof(buf), buf);
+       return client->write(client, buf, sizeof(buf));
 } /* sdb_client_send */
 
 ssize_t
@@ -286,7 +305,7 @@ sdb_client_recv(sdb_client_t *client,
                        return -1;
 
                errno = 0;
-               status = sdb_strbuf_read(buf, client->fd, req);
+               status = client->read(client, buf, req);
                if (status < 0) {
                        if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
                                continue;
@@ -303,9 +322,15 @@ sdb_client_recv(sdb_client_t *client,
                        continue;
 
                if (rstatus == UINT32_MAX) {
+                       const char *str = sdb_strbuf_string(buf) + data_offset;
+                       size_t len = sdb_strbuf_len(buf) - data_offset;
+                       ssize_t n;
+
                        /* retrieve status and data len */
-                       rstatus = sdb_proto_get_int(buf, data_offset);
-                       rlen = sdb_proto_get_int(buf, data_offset + sizeof(rstatus));
+                       assert(len >= 2 * sizeof(uint32_t));
+                       n = sdb_proto_unmarshal_int32(str, len, &rstatus);
+                       str += n; len -= (size_t)n;
+                       sdb_proto_unmarshal_int32(str, len, &rlen);
 
                        if (! rlen)
                                break;