Code

Merged branch 'master' of git://git.tokkee.org/sysdb.
[sysdb.git] / src / utils / proto.c
index d049144ca2716c7a493cab1be92f9fb698bde274..404d2a30ec5d2dabd270ab393bd9e262ec429017 100644 (file)
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "utils/error.h"
 #include "utils/proto.h"
-#include "core/error.h"
 
 #include <arpa/inet.h>
 #include <errno.h>
 
+#include <limits.h>
+
 #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 (ssize_t)n;
+               if (n > 0)
+                       break;
+       }
+       return 0;
+} /* sdb_proto_select */
+
 ssize_t
 sdb_proto_send(int fd, size_t msg_len, const char *msg)
 {
@@ -54,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);
@@ -94,5 +144,24 @@ sdb_proto_send_msg(int fd, uint32_t code,
        return sdb_proto_send(fd, len, buffer);
 } /* sdb_proto_send_msg */
 
+uint32_t
+sdb_proto_get_int(sdb_strbuf_t *buf, size_t offset)
+{
+       const char *data;
+       uint32_t n;
+
+       if (! buf)
+               return UINT32_MAX;
+
+       /* not enough data to read */
+       if (offset + sizeof(uint32_t) > sdb_strbuf_len(buf))
+               return UINT32_MAX;
+
+       data = sdb_strbuf_string(buf);
+       data += offset;
+       memcpy(&n, data, sizeof(n));
+       return ntohl(n);
+} /* sdb_proto_get_int */
+
 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */