Commit bffbaf4f authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

tls: add convenience wrappers for vlc_tls_SocketOpen()

parent b439a28f
......@@ -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,
......
......@@ -443,6 +443,7 @@ vlc_tls_Read
vlc_tls_Write
vlc_tls_GetLine
vlc_tls_SocketOpen
vlc_tls_SocketOpenTCP
ToCharset
update_Check
update_Delete
......
......@@ -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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment