[vlc-commits] tls: add convenience wrappers for vlc_tls_SocketOpen()

Rémi Denis-Courmont git at videolan.org
Wed Feb 22 21:37:36 CET 2017


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Feb 22 22:02:26 2017 +0200| [bffbaf4f383320159989abb4301836c6c8729e35] | committer: Rémi Denis-Courmont

tls: add convenience wrappers for vlc_tls_SocketOpen()

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

 include/vlc_tls.h  |  20 +++++++++++
 src/libvlccore.sym |   1 +
 src/network/tls.c  | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+)

diff --git a/include/vlc_tls.h b/include/vlc_tls.h
index a9f890c..99c5b65 100644
--- a/include/vlc_tls.h
+++ b/include/vlc_tls.h
@@ -232,6 +232,26 @@ VLC_API void vlc_tls_Delete (vlc_tls_creds_t *);
  */
 VLC_API vlc_tls_t *vlc_tls_SocketOpen(vlc_object_t *obj, int fd);
 
+struct addrinfo;
+
+/**
+ * Creates a transport-layer stream from a struct addrinfo.
+ *
+ * This is convenience wrapper for vlc_tls_SocketOpen().
+ * \note The function currently iterates through the addrinfo linked list.
+ * Future versions may implement different behaviour (e.g. RFC6555).
+ */
+vlc_tls_t *vlc_tls_SocketOpenAddrInfo(vlc_object_t *obj,
+                                      const struct addrinfo *);
+
+/**
+ * Creates a transport-layer TCP stream from a name and port.
+ *
+ * This is a convenience wrapper for vlc_tls_SocketOpenAddrInfo().
+ */
+VLC_API vlc_tls_t *vlc_tls_SocketOpenTCP(vlc_object_t *obj,
+                                         const char *hostname, unsigned port);
+
 VLC_DEPRECATED
 static inline vlc_tls_t *
 vlc_tls_ClientSessionCreateFD(vlc_tls_creds_t *crd, int fd, const char *host,
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 455a03b..8a29141 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -443,6 +443,7 @@ vlc_tls_Read
 vlc_tls_Write
 vlc_tls_GetLine
 vlc_tls_SocketOpen
+vlc_tls_SocketOpenTCP
 ToCharset
 update_Check
 update_Delete
diff --git a/src/network/tls.c b/src/network/tls.c
index 4a4ab67..0912a1e 100644
--- a/src/network/tls.c
+++ b/src/network/tls.c
@@ -404,3 +404,107 @@ vlc_tls_t *vlc_tls_SocketOpen(vlc_object_t *obj, int fd)
     session->p = NULL;
     return session;
 }
+
+static vlc_tls_t *vlc_tls_SocketOpenAddrInfoSingle(vlc_object_t *obj,
+                                          const struct addrinfo *restrict info)
+{
+    int fd = vlc_socket(info->ai_family, info->ai_socktype, info->ai_protocol,
+                        true /* nonblocking */);
+    if (fd == -1)
+    {
+        msg_Warn(obj, "socket error: %s", vlc_strerror_c(errno));
+        return NULL;
+    }
+
+    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof (int));
+
+    int val = connect(fd, info->ai_addr, info->ai_addrlen);
+    if (val != 0)
+    {
+        if (errno != EINPROGRESS)
+        {
+            msg_Err(obj, "connection error: %s", vlc_strerror_c(errno));
+            goto giveup;
+        }
+
+        struct pollfd ufd;
+
+        ufd.fd = fd;
+        ufd.events = POLLOUT;
+
+        do
+        {
+            if (vlc_killed())
+            {
+                errno = EINTR;
+                goto giveup;
+            }
+        }
+        while (vlc_poll_i11e(&ufd, 1, -1) <= 0);
+
+        socklen_t len = sizeof (val);
+        if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &len))
+        {
+            msg_Err(obj, "socket option error: %s",
+                    vlc_strerror_c(errno));
+            goto giveup;
+        }
+
+        if (val != 0)
+        {
+            msg_Err(obj, "connection error: %s", vlc_strerror_c(val));
+            errno = val;
+            goto giveup;
+        }
+    }
+
+    vlc_tls_t *tls = vlc_tls_SocketOpen(obj, fd);
+    if (unlikely(tls == NULL))
+        goto giveup;
+
+    return tls;
+
+giveup:
+    net_Close(fd);
+    return NULL;
+}
+
+vlc_tls_t *vlc_tls_SocketOpenAddrInfo(vlc_object_t *obj,
+                                      const struct addrinfo *restrict info)
+{
+    /* TODO: implement RFC6555 */
+    for (const struct addrinfo *p = info; p != NULL; p = p->ai_next)
+    {
+        vlc_tls_t *tls = vlc_tls_SocketOpenAddrInfoSingle(obj, p);
+        if (tls != NULL)
+            return tls;
+    }
+    return NULL;
+}
+
+vlc_tls_t *vlc_tls_SocketOpenTCP(vlc_object_t *obj, const char *name,
+                                 unsigned port)
+{
+    struct addrinfo hints =
+    {
+        .ai_socktype = SOCK_STREAM,
+        .ai_protocol = IPPROTO_TCP,
+    }, *res;
+
+    assert(name != NULL);
+    msg_Dbg(obj, "resolving %s ...", name);
+
+    int val = vlc_getaddrinfo_i11e(name, port, &hints, &res);
+    if (val != 0)
+    {   /* TODO: C locale for gai_strerror() */
+        msg_Err(obj, "cannot resolve %s port %u: %s", name, port,
+                gai_strerror(val));
+        return NULL;
+    }
+
+    msg_Dbg(obj, "connecting to %s port %u ...", name, port);
+
+    vlc_tls_t *tls = vlc_tls_SocketOpenAddrInfo(obj, res);
+    freeaddrinfo(res);
+    return tls;
+}



More information about the vlc-commits mailing list