mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-07-28 00:21:48 +03:00
Add support for event-driven IO in ssl_client2 and ssl_server2
This commit is contained in:
@ -101,6 +101,7 @@ int main( void )
|
||||
#define DFL_SERVER_PORT "4433"
|
||||
#define DFL_DEBUG_LEVEL 0
|
||||
#define DFL_NBIO 0
|
||||
#define DFL_EVENT 0
|
||||
#define DFL_READ_TIMEOUT 0
|
||||
#define DFL_CA_FILE ""
|
||||
#define DFL_CA_PATH ""
|
||||
@ -331,6 +332,8 @@ int main( void )
|
||||
" debug_level=%%d default: 0 (disabled)\n" \
|
||||
" nbio=%%d default: 0 (blocking I/O)\n" \
|
||||
" options: 1 (non-blocking), 2 (added delays)\n" \
|
||||
" event=%%d default: 0 (loop)\n" \
|
||||
" options: 1 (level-triggered, implies nbio=1),\n" \
|
||||
" read_timeout=%%d default: 0 ms (no timeout)\n" \
|
||||
"\n" \
|
||||
USAGE_DTLS \
|
||||
@ -399,6 +402,7 @@ struct options
|
||||
const char *server_port; /* port on which the ssl service runs */
|
||||
int debug_level; /* level of debugging */
|
||||
int nbio; /* should I/O be blocking? */
|
||||
int event; /* loop or event-driven IO? level or edge triggered? */
|
||||
uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */
|
||||
const char *ca_file; /* the file with the CA certificate(s) */
|
||||
const char *ca_path; /* the path with the CA certificate(s) reside */
|
||||
@ -837,6 +841,78 @@ static int ssl_sig_hashes_for_test[] = {
|
||||
};
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
/*
|
||||
* Wait for an event from the underlying transport or the timer
|
||||
* (Used in event-driven IO mode).
|
||||
*/
|
||||
#if !defined(MBEDTLS_TIMING_C)
|
||||
void idle( mbedtls_ssl_context *ssl,
|
||||
mbedtls_net_context *fd,
|
||||
int idle_reason )
|
||||
{
|
||||
#else
|
||||
void idle( mbedtls_ssl_context *ssl,
|
||||
mbedtls_net_context *fd,
|
||||
mbedtls_timing_delay_context *timer,
|
||||
int idle_reason )
|
||||
{
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
struct mbedtls_timing_hr_time tm;
|
||||
unsigned long time_elapsed;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int poll_type = 0;
|
||||
|
||||
if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
poll_type = MBEDTLS_NET_POLL_WRITE;
|
||||
else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ )
|
||||
poll_type = MBEDTLS_NET_POLL_READ;
|
||||
#if !defined(MBEDTLS_TIMING_C)
|
||||
else
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "WARNING: No reason for idling given" ) );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* One should not idle on the underlying transport
|
||||
* if data is still pending to be processed. */
|
||||
if( mbedtls_ssl_check_pending( ssl ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "WARNING: Data still pending, "
|
||||
"but idling requested!" ) );
|
||||
}
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "idle, waiting for event... " ) );
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C) && defined(MBEDTLS_DEBUG_C)
|
||||
mbedtls_timing_get_timer( &tm, 1 /* restart */ );
|
||||
#endif
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
time_elapsed = mbedtls_timing_get_timer( &tm, 0 );
|
||||
#endif
|
||||
if( mbedtls_timing_get_delay( timer ) == 2 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "[%lu ms] timer expired - continue",
|
||||
time_elapsed ) );
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( poll_type != 0 &&
|
||||
mbedtls_net_poll( fd, poll_type, 0 ) == poll_type )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "[%lu ms] net_context signals data - "
|
||||
"continue", time_elapsed ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
int ret = 0, len, written, frags, exchanges_left;
|
||||
@ -969,6 +1045,7 @@ int main( int argc, char *argv[] )
|
||||
opt.server_addr = DFL_SERVER_ADDR;
|
||||
opt.server_port = DFL_SERVER_PORT;
|
||||
opt.debug_level = DFL_DEBUG_LEVEL;
|
||||
opt.event = DFL_EVENT;
|
||||
opt.nbio = DFL_NBIO;
|
||||
opt.read_timeout = DFL_READ_TIMEOUT;
|
||||
opt.ca_file = DFL_CA_FILE;
|
||||
@ -1047,6 +1124,12 @@ int main( int argc, char *argv[] )
|
||||
if( opt.nbio < 0 || opt.nbio > 2 )
|
||||
goto usage;
|
||||
}
|
||||
else if( strcmp( p, "event" ) == 0 )
|
||||
{
|
||||
opt.event = atoi( q );
|
||||
if( opt.event < 0 || opt.event > 2 )
|
||||
goto usage;
|
||||
}
|
||||
else if( strcmp( p, "read_timeout" ) == 0 )
|
||||
opt.read_timeout = atoi( q );
|
||||
else if( strcmp( p, "ca_file" ) == 0 )
|
||||
@ -1328,6 +1411,16 @@ int main( int argc, char *argv[] )
|
||||
goto usage;
|
||||
}
|
||||
|
||||
/* Event-driven IO is incompatible with the above custom
|
||||
* receive and send functions, as the polling builds on
|
||||
* refers to the underlying net_context. */
|
||||
if( opt.event == 1 && opt.nbio != 1 )
|
||||
{
|
||||
mbedtls_printf( "Warning: event-driven IO mandates nbio=1"
|
||||
" - overwrite\n" );
|
||||
opt.nbio = 1;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
mbedtls_debug_set_threshold( opt.debug_level );
|
||||
#endif
|
||||
@ -2113,9 +2206,22 @@ handshake:
|
||||
mbedtls_printf( " . Performing the SSL/TLS handshake..." );
|
||||
fflush( stdout );
|
||||
|
||||
do ret = mbedtls_ssl_handshake( &ssl );
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
|
||||
{
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
break;
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &ssl, &client_fd, &timer, ret );
|
||||
#else
|
||||
idle( &ssl, &client_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
|
||||
{
|
||||
@ -2221,7 +2327,18 @@ data_exchange:
|
||||
|
||||
if( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
{
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &ssl, &client_fd, &timer, ret );
|
||||
#else
|
||||
idle( &ssl, &client_fd, ret );
|
||||
#endif
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ret <= 0 )
|
||||
{
|
||||
@ -2309,9 +2426,24 @@ data_exchange:
|
||||
len = sizeof( buf ) - 1;
|
||||
memset( buf, 0, sizeof( buf ) );
|
||||
|
||||
do ret = mbedtls_ssl_read( &ssl, buf, len );
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
while( 1 )
|
||||
{
|
||||
ret = mbedtls_ssl_read( &ssl, buf, len );
|
||||
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
break;
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &ssl, &client_fd, &timer, ret );
|
||||
#else
|
||||
idle( &ssl, &client_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if( ret <= 0 )
|
||||
{
|
||||
@ -2352,6 +2484,16 @@ data_exchange:
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret );
|
||||
goto reset;
|
||||
}
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &ssl, &client_fd, &timer, ret );
|
||||
#else
|
||||
idle( &ssl, &client_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_printf( " ok\n" );
|
||||
@ -2386,14 +2528,39 @@ data_exchange:
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
|
||||
goto reset;
|
||||
}
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &ssl, &client_fd, &timer, ret );
|
||||
#else
|
||||
idle( &ssl, &client_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Not stream, so datagram */
|
||||
{
|
||||
do ret = mbedtls_ssl_write( &ssl, buf, len );
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
while( 1 )
|
||||
{
|
||||
ret = mbedtls_ssl_write( &ssl, buf, len );
|
||||
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
break;
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &ssl, &client_fd, &timer, ret );
|
||||
#else
|
||||
idle( &ssl, &client_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if( ret < 0 )
|
||||
{
|
||||
|
Reference in New Issue
Block a user