[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