mirror of https://code.videolan.org/videolan/vlc
- Non blocking TLS handshaking
This commit is contained in:
parent
c818ae899f
commit
1c672a3d5c
|
@ -59,7 +59,8 @@ struct tls_session_t
|
|||
void *p_sys;
|
||||
|
||||
struct virtual_socket_t sock;
|
||||
tls_session_t * (*pf_handshake) ( tls_session_t *, int );
|
||||
int (*pf_handshake) ( tls_session_t *, int );
|
||||
int (*pf_handshake2) ( tls_session_t * );
|
||||
void (*pf_close) ( tls_session_t * );
|
||||
};
|
||||
|
||||
|
@ -102,6 +103,7 @@ VLC_EXPORT( tls_session_t *, tls_ClientCreate, ( vlc_object_t *, const char *, i
|
|||
VLC_EXPORT( void, tls_ClientDelete, ( tls_session_t * ) );
|
||||
|
||||
# define tls_SessionHandshake( a, b ) (((tls_session_t *)a)->pf_handshake (a, b))
|
||||
# define tls_SessionContinueHandshake( a ) (((tls_session_t *)a)->pf_handshake2 (a))
|
||||
|
||||
# define tls_SessionClose( a ) (((tls_session_t *)a)->pf_close (a))
|
||||
|
||||
|
|
|
@ -128,26 +128,25 @@ gnutls_Recv( void *p_session, void *buf, int i_length )
|
|||
|
||||
|
||||
/*****************************************************************************
|
||||
* tls_SessionHandshake:
|
||||
* tls_Session(Continue)?Handshake:
|
||||
*****************************************************************************
|
||||
* Establishes TLS session with a peer through socket <fd>.
|
||||
* Returns NULL on error (do NOT call tls_SessionClose in case of error or
|
||||
* re-use the session structure).
|
||||
* Returns -1 on error (you need not and must not call tls_SessionClose)
|
||||
* 0 on succesful handshake completion, 1 if more would-be blocking recv is
|
||||
* needed, 2 if more would-be blocking send is required.
|
||||
*****************************************************************************/
|
||||
static tls_session_t *
|
||||
gnutls_SessionHandshake( tls_session_t *p_session, int fd )
|
||||
static int
|
||||
gnutls_SessionContinueHandshake( tls_session_t *p_session)
|
||||
{
|
||||
tls_session_sys_t *p_sys;
|
||||
int val;
|
||||
|
||||
p_sys = (tls_session_sys_t *)(p_session->p_sys);
|
||||
|
||||
gnutls_transport_set_ptr (p_sys->session, (gnutls_transport_ptr)fd);
|
||||
|
||||
do
|
||||
/* TODO: handle fatal error */
|
||||
val = gnutls_handshake( p_sys->session );
|
||||
while( ( val == GNUTLS_E_AGAIN ) || ( val == GNUTLS_E_INTERRUPTED ) );
|
||||
/* TODO: handle fatal error */
|
||||
val = gnutls_handshake( p_sys->session );
|
||||
if( ( val == GNUTLS_E_AGAIN ) || ( val == GNUTLS_E_INTERRUPTED ) )
|
||||
return 1 + gnutls_record_get_direction( p_sys->session );
|
||||
|
||||
if( val < 0 )
|
||||
{
|
||||
|
@ -156,10 +155,22 @@ gnutls_SessionHandshake( tls_session_t *p_session, int fd )
|
|||
gnutls_strerror( val ) );
|
||||
free( p_sys );
|
||||
free( p_session );
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return p_session;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gnutls_SessionHandshake( tls_session_t *p_session, int fd )
|
||||
{
|
||||
tls_session_sys_t *p_sys;
|
||||
|
||||
p_sys = (tls_session_sys_t *)(p_session->p_sys);
|
||||
|
||||
gnutls_transport_set_ptr (p_sys->session, (gnutls_transport_ptr)fd);
|
||||
|
||||
return gnutls_SessionContinueHandshake( p_session );
|
||||
}
|
||||
|
||||
|
||||
|
@ -376,6 +387,7 @@ gnutls_ServerSessionPrepare( tls_server_t *p_server )
|
|||
p_session->sock.pf_send = gnutls_Send;
|
||||
p_session->sock.pf_recv = gnutls_Recv;
|
||||
p_session->pf_handshake = gnutls_SessionHandshake;
|
||||
p_session->pf_handshake2 = gnutls_SessionContinueHandshake;
|
||||
p_session->pf_close = gnutls_SessionClose;
|
||||
|
||||
return p_session;
|
||||
|
|
|
@ -264,6 +264,9 @@ enum
|
|||
HTTPD_CLIENT_WAITING,
|
||||
|
||||
HTTPD_CLIENT_DEAD,
|
||||
|
||||
HTTPD_CLIENT_TLS_HS_IN,
|
||||
HTTPD_CLIENT_TLS_HS_OUT
|
||||
};
|
||||
/* mode */
|
||||
enum
|
||||
|
@ -2020,6 +2023,41 @@ static void httpd_ClientSend( httpd_client_t *cl )
|
|||
}
|
||||
}
|
||||
|
||||
static void httpd_ClientTlsHsIn( httpd_client_t *cl )
|
||||
{
|
||||
switch( tls_SessionContinueHandshake( cl->p_tls ) )
|
||||
{
|
||||
case 0:
|
||||
cl->i_state = HTTPD_CLIENT_RECEIVING;
|
||||
break;
|
||||
|
||||
case -1:
|
||||
cl->i_state = HTTPD_CLIENT_DEAD;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
cl->i_state = HTTPD_CLIENT_TLS_HS_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
static void httpd_ClientTlsHsOut( httpd_client_t *cl )
|
||||
{
|
||||
switch( tls_SessionContinueHandshake( cl->p_tls ) )
|
||||
{
|
||||
case 0:
|
||||
cl->i_state = HTTPD_CLIENT_RECEIVING;
|
||||
break;
|
||||
|
||||
case -1:
|
||||
cl->i_state = HTTPD_CLIENT_DEAD;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
cl->i_state = HTTPD_CLIENT_TLS_HS_IN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void httpd_HostThread( httpd_host_t *host )
|
||||
{
|
||||
tls_session_t *p_tls = NULL;
|
||||
|
@ -2077,12 +2115,14 @@ static void httpd_HostThread( httpd_host_t *host )
|
|||
i_client--;
|
||||
continue;
|
||||
}
|
||||
else if( cl->i_state == HTTPD_CLIENT_RECEIVING )
|
||||
else if( ( cl->i_state == HTTPD_CLIENT_RECEIVING )
|
||||
|| ( cl->i_state == HTTPD_CLIENT_TLS_HS_IN ) )
|
||||
{
|
||||
FD_SET( cl->fd, &fds_read );
|
||||
i_handle_max = __MAX( i_handle_max, cl->fd );
|
||||
}
|
||||
else if( cl->i_state == HTTPD_CLIENT_SENDING )
|
||||
else if( ( cl->i_state == HTTPD_CLIENT_SENDING )
|
||||
|| ( cl->i_state == HTTPD_CLIENT_TLS_HS_OUT ) )
|
||||
{
|
||||
FD_SET( cl->fd, &fds_write );
|
||||
i_handle_max = __MAX( i_handle_max, cl->fd );
|
||||
|
@ -2422,6 +2462,8 @@ static void httpd_HostThread( httpd_host_t *host )
|
|||
fd = accept( host->fd, (struct sockaddr *)&sock, &i_sock_size );
|
||||
if( fd >= 0 )
|
||||
{
|
||||
int i_state = 0;
|
||||
|
||||
/* set this new socket non-block */
|
||||
#if defined( WIN32 ) || defined( UNDER_CE )
|
||||
{
|
||||
|
@ -2435,12 +2477,21 @@ static void httpd_HostThread( httpd_host_t *host )
|
|||
/* FIXME: that MUST be non-blocking */
|
||||
if( p_tls != NULL)
|
||||
{
|
||||
p_tls = tls_SessionHandshake( p_tls, fd );
|
||||
if ( p_tls == NULL )
|
||||
switch ( tls_SessionHandshake( p_tls, fd ) )
|
||||
{
|
||||
msg_Err( host, "Rejecting TLS connection" );
|
||||
net_Close( fd );
|
||||
fd = -1;
|
||||
case -1:
|
||||
msg_Err( host, "Rejecting TLS connection" );
|
||||
net_Close( fd );
|
||||
fd = -1;
|
||||
break;
|
||||
|
||||
case 1: /* missing input - most likely */
|
||||
i_state = HTTPD_CLIENT_TLS_HS_IN;
|
||||
break;
|
||||
|
||||
case 2: /* missing output */
|
||||
i_state = HTTPD_CLIENT_TLS_HS_OUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2455,7 +2506,9 @@ static void httpd_HostThread( httpd_host_t *host )
|
|||
TAB_APPEND( host->i_client, host->client, cl );
|
||||
vlc_mutex_unlock( &host->lock );
|
||||
|
||||
|
||||
if( i_state != 0 )
|
||||
cl->i_state = i_state; // override state for TLS
|
||||
|
||||
// FIXME: it sucks to allocate memory for debug
|
||||
ip = httpd_ClientIP( cl );
|
||||
msg_Dbg( host, "new connection (%s)",
|
||||
|
@ -2478,6 +2531,14 @@ static void httpd_HostThread( httpd_host_t *host )
|
|||
{
|
||||
httpd_ClientSend( cl );
|
||||
}
|
||||
else if( cl->i_state == HTTPD_CLIENT_TLS_HS_IN )
|
||||
{
|
||||
httpd_ClientTlsHsIn( cl );
|
||||
}
|
||||
else if( cl->i_state == HTTPD_CLIENT_TLS_HS_OUT )
|
||||
{
|
||||
httpd_ClientTlsHsOut( cl );
|
||||
}
|
||||
|
||||
if( cl->i_mode == HTTPD_CLIENT_BIDIR &&
|
||||
cl->i_state == HTTPD_CLIENT_SENDING &&
|
||||
|
|
|
@ -114,8 +114,7 @@ tls_ClientCreate( vlc_object_t *p_this, const char *psz_ca, int fd )
|
|||
p_session = __tls_ClientCreate( p_tls, psz_ca );
|
||||
if( p_session != NULL )
|
||||
{
|
||||
p_session = tls_SessionHandshake( p_session, fd );
|
||||
if( p_session != NULL )
|
||||
if( tls_SessionHandshake( p_session, fd ) )
|
||||
{
|
||||
msg_Dbg( p_this, "TLS/SSL provider initialized" );
|
||||
return p_session;
|
||||
|
|
Loading…
Reference in New Issue