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

tls: make vlc_tls_ClientSessionCreate() cancellation-safe

parent cc80d6a2
...@@ -50,7 +50,8 @@ struct vlc_tls ...@@ -50,7 +50,8 @@ struct vlc_tls
* Initiates a client TLS session. * Initiates a client TLS session.
* *
* Performs client side of TLS handshake through a connected socket, and * Performs client side of TLS handshake through a connected socket, and
* establishes a secure channel. This is a blocking network operation. * establishes a secure channel. This is a blocking network operation and may
* be a thread cancellation point.
* *
* @param fd socket through which to establish the secure channel * @param fd socket through which to establish the secure channel
* @param hostname expected server name, used both as Server Name Indication * @param hostname expected server name, used both as Server Name Indication
......
...@@ -159,13 +159,27 @@ void vlc_tls_SessionDelete (vlc_tls_t *session) ...@@ -159,13 +159,27 @@ void vlc_tls_SessionDelete (vlc_tls_t *session)
vlc_object_release (session); vlc_object_release (session);
} }
static void cleanup_tls(void *data)
{
vlc_tls_t *session = data;
vlc_tls_SessionDelete (session);
}
vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd, vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd,
const char *host, const char *service, const char *host, const char *service,
const char *const *alpn, char **alp) const char *const *alpn, char **alp)
{ {
vlc_tls_t *session = vlc_tls_SessionCreate (crd, fd, host, alpn); vlc_tls_t *session;
int canc, val;
canc = vlc_savecancel();
session = vlc_tls_SessionCreate (crd, fd, host, alpn);
if (session == NULL) if (session == NULL)
{
vlc_restorecancel(canc);
return NULL; return NULL;
}
mtime_t deadline = mdate (); mtime_t deadline = mdate ();
deadline += var_InheritInteger (crd, "ipv4-timeout") * 1000; deadline += var_InheritInteger (crd, "ipv4-timeout") * 1000;
...@@ -173,13 +187,16 @@ vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd, ...@@ -173,13 +187,16 @@ vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd,
struct pollfd ufd[1]; struct pollfd ufd[1];
ufd[0].fd = fd; ufd[0].fd = fd;
int val; vlc_cleanup_push (cleanup_tls, session);
while ((val = vlc_tls_SessionHandshake (session, host, service, alp)) != 0) while ((val = vlc_tls_SessionHandshake (session, host, service, alp)) != 0)
{ {
if (val < 0) if (val < 0)
{ {
msg_Err (session, "TLS client session handshake error"); msg_Err (session, "TLS client session handshake error");
goto error; error:
vlc_tls_SessionDelete (session);
session = NULL;
break;
} }
mtime_t now = mdate (); mtime_t now = mdate ();
...@@ -189,16 +206,18 @@ vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd, ...@@ -189,16 +206,18 @@ vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *crd, int fd,
assert (val <= 2); assert (val <= 2);
ufd[0] .events = (val == 1) ? POLLIN : POLLOUT; ufd[0] .events = (val == 1) ? POLLIN : POLLOUT;
if (poll (ufd, 1, (deadline - now) / 1000) == 0) vlc_restorecancel(canc);
val = poll (ufd, 1, (deadline - now) / 1000);
canc = vlc_savecancel();
if (val == 0)
{ {
msg_Err (session, "TLS client session handshake timeout"); msg_Err (session, "TLS client session handshake timeout");
goto error; goto error;
} }
} }
vlc_cleanup_pop();
vlc_restorecancel(canc);
return session; return session;
error:
vlc_tls_SessionDelete (session);
return NULL;
} }
int vlc_tls_Read(vlc_tls_t *session, void *buf, size_t len, bool waitall) int vlc_tls_Read(vlc_tls_t *session, void *buf, size_t len, bool waitall)
......
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