[vlc-commits] tcp: gather socket accept/listen helpers

Rémi Denis-Courmont git at videolan.org
Sun Nov 11 16:33:27 CET 2018


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Fri Nov  9 22:49:12 2018 +0200| [14827d5587753a3e91cbd50d50ce8fa39fe0a190] | committer: Rémi Denis-Courmont

tcp: gather socket accept/listen helpers

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=14827d5587753a3e91cbd50d50ce8fa39fe0a190
---

 src/network/io.c  | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/network/tcp.c | 199 ------------------------------------------------------
 2 files changed, 185 insertions(+), 199 deletions(-)

diff --git a/src/network/io.c b/src/network/io.c
index 5aa5d65c65..a35e0767a9 100644
--- a/src/network/io.c
+++ b/src/network/io.c
@@ -39,6 +39,9 @@
 #include <assert.h>
 
 #include <unistd.h>
+#ifdef HAVE_POLL
+# include <poll.h>
+#endif
 #ifdef HAVE_LINUX_DCCP_H
 /* TODO: use glibc instead of linux-kernel headers */
 # include <linux/dccp.h>
@@ -48,6 +51,14 @@
 #include <vlc_common.h>
 #include <vlc_network.h>
 #include <vlc_interrupt.h>
+#if defined (_WIN32)
+#   undef EINPROGRESS
+#   define EINPROGRESS WSAEWOULDBLOCK
+#   undef EWOULDBLOCK
+#   define EWOULDBLOCK WSAEWOULDBLOCK
+#   undef EAGAIN
+#   define EAGAIN WSAEWOULDBLOCK
+#endif
 
 extern int rootwrap_bind (int family, int socktype, int protocol,
                           const struct sockaddr *addr, size_t alen);
@@ -102,6 +113,100 @@ int net_Socket (vlc_object_t *p_this, int family, int socktype,
     return fd;
 }
 
+int (net_Connect)(vlc_object_t *obj, const char *host, int serv,
+                  int type, int proto)
+{
+    struct addrinfo hints = {
+        .ai_socktype = type,
+        .ai_protocol = proto,
+        .ai_flags = AI_NUMERICSERV | AI_IDN,
+    }, *res;
+    int ret = -1;
+
+    int val = vlc_getaddrinfo_i11e(host, serv, &hints, &res);
+    if (val)
+    {
+        msg_Err(obj, "cannot resolve %s port %d : %s", host, serv,
+                gai_strerror (val));
+        return -1;
+    }
+
+    vlc_tick_t timeout = VLC_TICK_FROM_MS(var_InheritInteger(obj,
+                                                             "ipv4-timeout"));
+
+    for (struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
+    {
+        int fd = net_Socket(obj, ptr->ai_family,
+                            ptr->ai_socktype, ptr->ai_protocol);
+        if (fd == -1)
+        {
+            msg_Dbg(obj, "socket error: %s", vlc_strerror_c(net_errno));
+            continue;
+        }
+
+        if (connect(fd, ptr->ai_addr, ptr->ai_addrlen))
+        {
+            if (net_errno != EINPROGRESS && errno != EINTR)
+            {
+                msg_Err(obj, "connection failed: %s",
+                        vlc_strerror_c(net_errno));
+                goto next_ai;
+            }
+
+            struct pollfd ufd;
+            vlc_tick_t deadline = VLC_TICK_INVALID;
+
+            ufd.fd = fd;
+            ufd.events = POLLOUT;
+            deadline = vlc_tick_now() + timeout;
+
+            do
+            {
+                vlc_tick_t now = vlc_tick_now();
+
+                if (vlc_killed())
+                    goto next_ai;
+
+                if (now > deadline)
+                    now = deadline;
+
+                val = vlc_poll_i11e(&ufd, 1, MS_FROM_VLC_TICK(deadline - now));
+            }
+            while (val == -1 && errno == EINTR);
+
+            switch (val)
+            {
+                 case -1: /* error */
+                     msg_Err(obj, "polling error: %s",
+                             vlc_strerror_c(net_errno));
+                     goto next_ai;
+
+                 case 0: /* timeout */
+                     msg_Warn(obj, "connection timed out");
+                     goto next_ai;
+            }
+
+            /* There is NO WAY around checking SO_ERROR.
+             * Don't ifdef it out!!! */
+            if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &val,
+                           &(socklen_t){ sizeof (val) }) || val)
+            {
+                msg_Err(obj, "connection failed: %s", vlc_strerror_c(val));
+                goto next_ai;
+            }
+        }
+
+        msg_Dbg(obj, "connection succeeded (socket = %d)", fd);
+        ret = fd; /* success! */
+        break;
+
+next_ai: /* failure */
+        net_Close(fd);
+    }
+
+    freeaddrinfo(res);
+    return ret;
+}
 
 int *net_Listen (vlc_object_t *p_this, const char *psz_host,
                  unsigned i_port, int type, int protocol)
@@ -224,6 +329,86 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host,
     return sockv;
 }
 
+void net_ListenClose(int *fds)
+{
+    if (fds != NULL)
+    {
+        for (int *p = fds; *p != -1; p++)
+            net_Close(*p);
+
+        free(fds);
+    }
+}
+
+int net_AcceptSingle(vlc_object_t *obj, int lfd)
+{
+    int fd = vlc_accept(lfd, NULL, NULL, true);
+    if (fd == -1)
+    {
+        if (net_errno != EAGAIN)
+#if (EAGAIN != EWOULDBLOCK)
+          if (net_errno != EWOULDBLOCK)
+#endif
+            msg_Err(obj, "accept failed (from socket %d): %s", lfd,
+                    vlc_strerror_c(net_errno));
+        return -1;
+    }
+
+    msg_Dbg(obj, "accepted socket %d (from socket %d)", fd, lfd);
+    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
+    return fd;
+}
+
+#undef net_Accept
+int net_Accept(vlc_object_t *obj, int *fds)
+{
+    assert(fds != NULL);
+
+    unsigned n = 0;
+    while (fds[n] != -1)
+        n++;
+
+    struct pollfd ufd[n];
+    /* Initialize file descriptor set */
+    for (unsigned i = 0; i < n; i++)
+    {
+        ufd[i].fd = fds[i];
+        ufd[i].events = POLLIN;
+    }
+
+    for (;;)
+    {
+        while (poll(ufd, n, -1) == -1)
+        {
+            if (net_errno != EINTR)
+            {
+                msg_Err(obj, "poll error: %s", vlc_strerror_c(net_errno));
+                return -1;
+            }
+        }
+
+        for (unsigned i = 0; i < n; i++)
+        {
+            if (ufd[i].revents == 0)
+                continue;
+
+            int sfd = ufd[i].fd;
+            int fd = net_AcceptSingle(obj, sfd);
+            if (fd == -1)
+                continue;
+
+            /*
+             * Move listening socket to the end to let the others in the
+             * set a chance next time.
+             */
+            memmove(fds + i, fds + i + 1, n - (i + 1));
+            fds[n - 1] = sfd;
+            return fd;
+        }
+    }
+    return -1;
+}
+
 ssize_t (net_Read)(vlc_object_t *restrict obj, int fd,
                    void *restrict buf, size_t len)
 {
diff --git a/src/network/tcp.c b/src/network/tcp.c
index fab3032249..eb398c9336 100644
--- a/src/network/tcp.c
+++ b/src/network/tcp.c
@@ -32,199 +32,12 @@
 
 #include <vlc_common.h>
 
-#include <errno.h>
-#include <assert.h>
-#include <limits.h>
 #include <unistd.h>
-#ifdef HAVE_POLL
-# include <poll.h>
-#endif
 
 #include <vlc_network.h>
-#if defined (_WIN32)
-#   undef EINPROGRESS
-#   define EINPROGRESS WSAEWOULDBLOCK
-#   undef EWOULDBLOCK
-#   define EWOULDBLOCK WSAEWOULDBLOCK
-#   undef EAGAIN
-#   define EAGAIN WSAEWOULDBLOCK
-#endif
 #include <vlc_interrupt.h>
 
 /*****************************************************************************
- * net_Connect:
- *****************************************************************************
- * Open a network connection.
- * @return socket handler or -1 on error.
- *****************************************************************************/
-int (net_Connect)(vlc_object_t *obj, const char *host, int serv,
-                  int type, int proto)
-{
-    struct addrinfo hints = {
-        .ai_socktype = type,
-        .ai_protocol = proto,
-        .ai_flags = AI_NUMERICSERV | AI_IDN,
-    }, *res;
-    int ret = -1;
-
-    int val = vlc_getaddrinfo_i11e(host, serv, &hints, &res);
-    if (val)
-    {
-        msg_Err(obj, "cannot resolve %s port %d : %s", host, serv,
-                gai_strerror (val));
-        return -1;
-    }
-
-    vlc_tick_t timeout = VLC_TICK_FROM_MS(var_InheritInteger(obj,
-                                                             "ipv4-timeout"));
-
-    for (struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
-    {
-        int fd = net_Socket(obj, ptr->ai_family,
-                            ptr->ai_socktype, ptr->ai_protocol);
-        if (fd == -1)
-        {
-            msg_Dbg(obj, "socket error: %s", vlc_strerror_c(net_errno));
-            continue;
-        }
-
-        if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) )
-        {
-            if( net_errno != EINPROGRESS && errno != EINTR )
-            {
-                msg_Err(obj, "connection failed: %s",
-                        vlc_strerror_c(net_errno));
-                goto next_ai;
-            }
-
-            struct pollfd ufd;
-            vlc_tick_t deadline = VLC_TICK_INVALID;
-
-            ufd.fd = fd;
-            ufd.events = POLLOUT;
-            deadline = vlc_tick_now() + timeout;
-
-            do
-            {
-                vlc_tick_t now = vlc_tick_now();
-
-                if (vlc_killed())
-                    goto next_ai;
-
-                if (now > deadline)
-                    now = deadline;
-
-                val = vlc_poll_i11e(&ufd, 1, MS_FROM_VLC_TICK(deadline - now));
-            }
-            while (val == -1 && errno == EINTR);
-
-            switch (val)
-            {
-                 case -1: /* error */
-                     msg_Err(obj, "polling error: %s",
-                             vlc_strerror_c(net_errno));
-                     goto next_ai;
-
-                 case 0: /* timeout */
-                     msg_Warn(obj, "connection timed out");
-                     goto next_ai;
-            }
-
-            /* There is NO WAY around checking SO_ERROR.
-             * Don't ifdef it out!!! */
-            if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &val,
-                            &(socklen_t){ sizeof (val) }) || val)
-            {
-                msg_Err(obj, "connection failed: %s", vlc_strerror_c(val));
-                goto next_ai;
-            }
-        }
-
-        msg_Dbg(obj, "connection succeeded (socket = %d)", fd);
-        ret = fd; /* success! */
-        break;
-
-next_ai: /* failure */
-        net_Close( fd );
-    }
-
-    freeaddrinfo( res );
-    return ret;
-}
-
-
-int net_AcceptSingle (vlc_object_t *obj, int lfd)
-{
-    int fd = vlc_accept (lfd, NULL, NULL, true);
-    if (fd == -1)
-    {
-        if (net_errno != EAGAIN)
-#if (EAGAIN != EWOULDBLOCK)
-          if (net_errno != EWOULDBLOCK)
-#endif
-            msg_Err (obj, "accept failed (from socket %d): %s", lfd,
-                     vlc_strerror_c(net_errno));
-        return -1;
-    }
-
-    msg_Dbg (obj, "accepted socket %d (from socket %d)", fd, lfd);
-    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
-    return fd;
-}
-
-
-#undef net_Accept
-int net_Accept (vlc_object_t *p_this, int *pi_fd)
-{
-    assert (pi_fd != NULL);
-
-    unsigned n = 0;
-    while (pi_fd[n] != -1)
-        n++;
-
-    struct pollfd ufd[n];
-    /* Initialize file descriptor set */
-    for (unsigned i = 0; i < n; i++)
-    {
-        ufd[i].fd = pi_fd[i];
-        ufd[i].events = POLLIN;
-    }
-
-    for (;;)
-    {
-        while (poll (ufd, n, -1) == -1)
-        {
-            if (net_errno != EINTR)
-            {
-                msg_Err (p_this, "poll error: %s", vlc_strerror_c(net_errno));
-                return -1;
-            }
-        }
-
-        for (unsigned i = 0; i < n; i++)
-        {
-            if (ufd[i].revents == 0)
-                continue;
-
-            int sfd = ufd[i].fd;
-            int fd = net_AcceptSingle (p_this, sfd);
-            if (fd == -1)
-                continue;
-
-            /*
-             * Move listening socket to the end to let the others in the
-             * set a chance next time.
-             */
-            memmove (pi_fd + i, pi_fd + i + 1, n - (i + 1));
-            pi_fd[n - 1] = sfd;
-            return fd;
-        }
-    }
-    return -1;
-}
-
-
-/*****************************************************************************
  * SocksNegotiate:
  *****************************************************************************
  * Negotiate authentication with a SOCKS server.
@@ -482,15 +295,3 @@ int (net_ConnectTCP)(vlc_object_t *obj, const char *host, int serv)
 
     return fd;
 }
-
-void net_ListenClose( int *pi_fd )
-{
-    if( pi_fd != NULL )
-    {
-        int *pi;
-
-        for( pi = pi_fd; *pi != -1; pi++ )
-            net_Close( *pi );
-        free( pi_fd );
-    }
-}



More information about the vlc-commits mailing list