1
mirror of https://code.videolan.org/videolan/vlc synced 2024-09-28 23:09:59 +02:00

tls: add dedicated helpers for I/O

This commit is contained in:
Rémi Denis-Courmont 2015-05-07 23:59:01 +03:00
parent 04d62b00d2
commit 58686f3ce1
3 changed files with 134 additions and 4 deletions

View File

@ -52,11 +52,12 @@ int vlc_tls_SessionHandshake (vlc_tls_t *, const char *host, const char *serv,
char ** /*restrict*/ alp);
VLC_API void vlc_tls_SessionDelete (vlc_tls_t *);
/* NOTE: It is assumed that a->sock.p_sys = a */
# define tls_Send( a, b, c ) (((vlc_tls_t *)a)->sock.pf_send (a, b, c))
# define tls_Recv( a, b, c ) (((vlc_tls_t *)a)->sock.pf_recv (a, b, c))
VLC_API int vlc_tls_Read(vlc_tls_t *, void *buf, size_t len, bool waitall);
VLC_API char *vlc_tls_GetLine(vlc_tls_t *);
VLC_API int vlc_tls_Write(vlc_tls_t *, const void *buf, size_t len);
# define tls_Recv(a,b,c) vlc_tls_Read(a,b,c,false)
# define tls_Send(a,b,c) vlc_tls_Write(a,b,c)
/** TLS credentials (certificate, private and trust settings) */
struct vlc_tls_creds

View File

@ -421,6 +421,9 @@ vlc_tls_ClientCreate
vlc_tls_Delete
vlc_tls_ClientSessionCreate
vlc_tls_SessionDelete
vlc_tls_Read
vlc_tls_Write
vlc_tls_GetLine
ToCharset
update_Check
update_Delete

View File

@ -34,6 +34,9 @@
# include <poll.h>
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <vlc_common.h>
#include "libvlc.h"
@ -233,3 +236,126 @@ error:
vlc_tls_SessionDelete (session);
return NULL;
}
int vlc_tls_Read(vlc_tls_t *session, void *buf, size_t len, bool waitall)
{
struct pollfd ufd[2];
ufd[0].fd = session->fd;
ufd[0].events = POLLIN;
ufd[1].fd = vlc_object_waitpipe(session->p_parent);
ufd[1].events = POLLIN;
if (unlikely(ufd[1].fd == -1))
{
vlc_testcancel();
return -1;
}
for (size_t rcvd = 0;;)
{
ssize_t val = session->sock.pf_recv(session, buf, len);
if (val > 0)
{
if (!waitall)
return val;
buf = ((char *)buf) + val;
len -= val;
rcvd += val;
}
if (len == 0 || val == 0)
return rcvd;
if (val == -1 && errno != EINTR && errno != EAGAIN)
return rcvd ? (ssize_t)rcvd : -1;
val = poll(ufd, 2, -1);
if (val == -1)
continue;
if (ufd[1].revents)
{
if (rcvd > 0)
return rcvd;
msg_Dbg(session, "socket %d polling interrupted", session->fd);
errno = EINTR;
return -1;
}
}
}
int vlc_tls_Write(vlc_tls_t *session, const void *buf, size_t len)
{
struct pollfd ufd[2];
ufd[0].fd = session->fd;
ufd[0].events = POLLOUT;
ufd[1].fd = vlc_object_waitpipe(session->p_parent);
ufd[1].events = POLLIN;
if (unlikely(ufd[1].fd == -1))
{
vlc_testcancel();
return -1;
}
for (size_t sent = 0;;)
{
ssize_t val = session->sock.pf_send(session, buf, len);
if (val > 0)
{
buf = ((const char *)buf) + val;
len -= val;
sent += val;
}
if (len == 0 || val == 0)
return sent;
if (val == -1 && errno != EINTR && errno != EAGAIN)
return sent ? (ssize_t)sent : -1;
val = poll(ufd, 2, -1);
if (val == -1)
continue;
if (ufd[1].revents)
{
if (sent > 0)
return sent;
msg_Dbg(session, "socket %d polling interrupted", session->fd);
errno = EINTR;
return -1;
}
}
}
char *vlc_tls_GetLine(vlc_tls_t *session)
{
char *line = NULL;
size_t linelen = 0, linesize = 0;
do
{
if (linelen == linesize)
{
linesize += 1024;
char *newline = realloc(line, linesize);
if (unlikely(newline == NULL))
goto error;
line = newline;
}
if (vlc_tls_Read(session, line + linelen, 1, false) <= 0)
goto error;
}
while (line[linelen++] != '\n');
if (linelen >= 2 && line[linelen - 2] == '\r')
line[linelen - 2] = '\0';
return line;
error:
free(line);
return NULL;
}