Code

utils/proto: Replaced sdb_proto_send_msg with sdb_proto_marshal.
[sysdb.git] / src / utils / proto.c
index 29783efd5aefb3db7cd09037f6f534fa4363b020..3315e0c7878056393df7a581b558f4a70df8e417 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
+#include <sys/select.h>
+
 /*
  * public API
  */
 
+int
+sdb_proto_select(int fd, int type)
+{
+       fd_set fds;
+       fd_set *readfds = NULL;
+       fd_set *writefds = NULL;
+       fd_set *exceptfds = NULL;
+
+       if (fd < 0) {
+               errno = EBADF;
+               return -1;
+       }
+
+       FD_ZERO(&fds);
+
+       switch (type) {
+               case SDB_PROTO_SELECTIN:
+                       readfds = &fds;
+                       break;
+               case SDB_PROTO_SELECTOUT:
+                       writefds = &fds;
+                       break;
+               case SDB_PROTO_SELECTERR:
+                       exceptfds = &fds;
+                       break;
+               default:
+                       errno = EINVAL;
+                       return -1;
+       }
+
+       FD_SET(fd, &fds);
+
+       while (42) {
+               int n;
+               errno = 0;
+               n = select(fd + 1, readfds, writefds, exceptfds, NULL);
+
+               if ((n < 0) && (errno != EINTR))
+                       return n;
+               if (n > 0)
+                       break;
+       }
+       return 0;
+} /* sdb_proto_select */
+
 ssize_t
 sdb_proto_send(int fd, size_t msg_len, const char *msg)
 {
@@ -56,7 +103,8 @@ sdb_proto_send(int fd, size_t msg_len, const char *msg)
        while (len > 0) {
                ssize_t status;
 
-               /* XXX: use select() */
+               if (sdb_proto_select(fd, SDB_PROTO_SELECTOUT))
+                       return -1;
 
                errno = 0;
                status = write(fd, buf, len);
@@ -77,24 +125,26 @@ sdb_proto_send(int fd, size_t msg_len, const char *msg)
 } /* sdb_proto_send */
 
 ssize_t
-sdb_proto_send_msg(int fd, uint32_t code,
+sdb_proto_marshal(char *buf, size_t buf_len, uint32_t code,
                uint32_t msg_len, const char *msg)
 {
        size_t len = 2 * sizeof(uint32_t) + msg_len;
-       char buffer[len];
-
        uint32_t tmp;
 
+       if (buf_len < 2 * sizeof(uint32_t))
+               return -1;
+       if (buf_len < len) /* crop message */
+               msg_len -= (uint32_t)(len - buf_len);
+
        tmp = htonl(code);
-       memcpy(buffer, &tmp, sizeof(tmp));
+       memcpy(buf, &tmp, sizeof(tmp));
        tmp = htonl(msg_len);
-       memcpy(buffer + sizeof(tmp), &tmp, sizeof(tmp));
+       memcpy(buf + sizeof(tmp), &tmp, sizeof(tmp));
 
        if (msg_len)
-               memcpy(buffer + 2 * sizeof(tmp), msg, msg_len);
-
-       return sdb_proto_send(fd, len, buffer);
-} /* sdb_proto_send_msg */
+               memcpy(buf + 2 * sizeof(tmp), msg, msg_len);
+       return len;
+} /* sdb_proto_marshal */
 
 uint32_t
 sdb_proto_get_int(sdb_strbuf_t *buf, size_t offset)