Fix various compile warnings
[splice.git] / splice-fromnet.c
index 59682669978839f357224efb8f1f73a2f0010875..7493e5b0308a871e7cc5df24819afa99edb7ee7a 100644 (file)
@@ -1,8 +1,5 @@
 /*
- * Splice from network to pipe. Currently splicing from a socket is not
- * supported, so this test case demonstrates how to use read + vmsplice/splice
- * to achieve the desired effect. This still involves a copy, so it's
- * not as fast as real splice from socket would be.
+ * Splice from network to stdout
  */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/time.h>
 #include <errno.h>
+#include <sys/poll.h>
 
 #include "splice.h"
 
-#define PSIZE  4096
-#define MASK   (PSIZE - 1)
-
-#define ALIGN(buf)     (void *) (((unsigned long) (buf) + MASK) & ~MASK)
-
-static int splice_flags;
+static unsigned int splice_size = SPLICE_SIZE;
+static unsigned int splice_flags;
+static int wait_for_poll;
 
 static int usage(char *name)
 {
-       fprintf(stderr, "%s: [-g] port\n", name);
+       fprintf(stderr, "%s: [-s splice size] [-w wait for poll] [-n non-blocking] port\n", name);
        return 1;
 }
 
-static unsigned long mtime_since(struct timeval *s, struct timeval *e)
+static int splice_from_net(int fd)
 {
-       double sec, usec;
+       while (1) {
+               int ret;
 
-       sec = e->tv_sec - s->tv_sec;
-       usec = e->tv_usec - s->tv_usec;
-       if (sec > 0 && usec < 0) {
-               sec--;
-               usec += 1000000;
-       }
+               if (wait_for_poll) {
+                       struct pollfd pfd = {
+                               .fd = fd,
+                               .events = POLLIN,
+                       };
 
-       sec *= (double) 1000;
-       usec /= (double) 1000;
+                       ret = poll(&pfd, 1, -1);
+                       if (ret < 0)
+                               return error("poll");
+                       else if (!ret)
+                               continue;
 
-       return sec + usec;
-}
+                       if (!(pfd.revents & POLLIN))
+                               continue;
+               }
 
-static unsigned long mtime_since_now(struct timeval *s)
-{
-       struct timeval t;
+               ret = ssplice(fd, NULL, STDOUT_FILENO, NULL, splice_size, 0);
+
+               if (ret < 0)
+                       return error("splice");
+               else if (!ret)
+                       break;
+       }
 
-       gettimeofday(&t, NULL);
-       return mtime_since(s, &t);
+       return 0;
 }
 
-static int recv_loop(int fd, char *buf)
+static int get_connect(int fd, struct sockaddr_in *addr)
 {
-       unsigned long kb_recv = 0, spent;
-       struct timeval s;
-       struct iovec iov;
-       int idx = 0;
-
-       gettimeofday(&s, NULL);
+       socklen_t socklen = sizeof(*addr);
+       int ret, connfd;
 
        do {
-               char *ptr = buf + idx * SPLICE_SIZE;
-               int ret;
-
-               ret = recv(fd, ptr, SPLICE_SIZE, MSG_WAITALL);
-               if (ret < 0) {
-                       perror("recv");
-                       return 1;
-               } else if (ret != SPLICE_SIZE)
-                       break;
-
-               iov.iov_base = ptr;
-               iov.iov_len = SPLICE_SIZE;
-               ret = vmsplice(STDOUT_FILENO, &iov, 1, splice_flags);
-               if (ret < 0) {
-                       perror("vmsplice");
-                       return 1;
-               } else if (ret != SPLICE_SIZE) {
-                       fprintf(stderr, "bad vmsplice %d\n", ret);
-                       return 1;
-               }
-               idx = (idx + 1) & 0x01;
-               kb_recv += (SPLICE_SIZE / 1024);
+               struct pollfd pfd = {
+                       .fd = fd,
+                       .events = POLLIN,
+               };
+
+               ret = poll(&pfd, 1, -1);
+               if (ret < 0)
+                       return error("poll");
+               else if (!ret)
+                       continue;
+
+               connfd = accept(fd, (struct sockaddr *) addr, &socklen);
+               if (connfd < 0)
+                       return error("accept");
+               break;
        } while (1);
-
-       spent = mtime_since_now(&s);
-       fprintf(stderr, "%lu MiB/sec (%luKiB in %lu msec)\n", kb_recv / spent, kb_recv, spent);
-
-       return 0;
+                       
+       return connfd;
 }
 
 static int parse_options(int argc, char *argv[])
 {
        int c, index = 1;
 
-       while ((c = getopt(argc, argv, "g")) != -1) {
+       while ((c = getopt(argc, argv, "s:w:n")) != -1) {
                switch (c) {
-               case 'g':
-                       splice_flags = SPLICE_F_GIFT;
+               case 's':
+                       splice_size = atoi(optarg);
+                       index++;
+                       break;
+               case 'w':
+                       wait_for_poll = atoi(optarg);
+                       index++;
+                       break;
+               case 'n':
+                       splice_flags |= SPLICE_F_NONBLOCK;
                        index++;
                        break;
                default:
@@ -115,13 +111,15 @@ static int parse_options(int argc, char *argv[])
        return index;
 }
 
+
 int main(int argc, char *argv[])
 {
        struct sockaddr_in addr;
        unsigned short port;
-       unsigned int len;
-       int fd, opt, sk, index;
-       char *buf;
+       int connfd, opt, fd, index;
+
+       if (argc < 2)
+               return usage(argv[0]);
 
        if (check_output_pipe())
                return usage(argv[0]);
@@ -132,7 +130,7 @@ int main(int argc, char *argv[])
 
        port = atoi(argv[index]);
 
-       fd = socket(PF_INET, SOCK_STREAM, 0);
+       fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (fd < 0)
                return error("socket");
 
@@ -141,26 +139,18 @@ int main(int argc, char *argv[])
                return error("setsockopt");
 
        memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
        addr.sin_port = htons(port);
 
        if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
                return error("bind");
-
        if (listen(fd, 1) < 0)
                return error("listen");
 
-       len = sizeof(addr);
-       sk = accept(fd, &addr, &len);
-       if (sk < 0)
-               return error("accept");
+       connfd = get_connect(fd, &addr);
+       if (connfd < 0)
+               return connfd;
 
-       fprintf(stderr, "Connected\n");
-
-       buf = ALIGN(malloc(2 * SPLICE_SIZE - 1));
-
-       return recv_loop(sk, buf);
-
-       close(fd);
-       return 0;
+       return splice_from_net(connfd);
 }