From 890b5ca33060a23131fe08fef18f11accd52d7c3 Mon Sep 17 00:00:00 2001 From: Piotr Nowicki Date: Wed, 15 Jan 2020 16:19:07 +0100 Subject: [PATCH] Change non-blocking read/write in TCP mock socket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously mocked non-blocking read/write was returning 0 when buffer was empty/full. That was causing ERR_SSL_CONN_EOF error in tests which was using these mocked callbacks. Beside that non-blocking read/write was returning ERR_SSL_WANT_READ/_WRITE depending on block pattern set by test design. Such behavior forced to redesign of these functions so that they could be used in other testsĀ  --- tests/suites/test_suite_ssl.data | 30 +--- tests/suites/test_suite_ssl.function | 224 +++++++++++++-------------- 2 files changed, 118 insertions(+), 136 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 83ef691c7..59b476966 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -35,34 +35,16 @@ Test mock socket sanity ssl_mock_sanity: Test mock blocking TCP connection -ssl_mock_tcp:1:0:0 +ssl_mock_tcp:1 -Test mock non-blocking TCP connection: would not block -ssl_mock_tcp:0:0:0 - -Test mock non-blocking TCP connection: client would block -ssl_mock_tcp:0:0xB509:0 - -Test mock non-blocking TCP connection: server would block -ssl_mock_tcp:0:0x0FB1:0 - -Test mock non-blocking TCP connection: both peers would block -ssl_mock_tcp:0:0x1111:0xEEEE +Test mock non-blocking TCP connection +ssl_mock_tcp:0 Test mock blocking TCP connection (interleaving) -ssl_mock_tcp_interleaving:1:0:0 +ssl_mock_tcp_interleaving:1 -Test mock non-blocking TCP connection: would not block (interleaving) -ssl_mock_tcp_interleaving:0:0:0 - -Test mock non-blocking TCP connection: client would block (interleaving) -ssl_mock_tcp_interleaving:0:0xB509:0 - -Test mock non-blocking TCP connection: server would block (interleaving) -ssl_mock_tcp_interleaving:0:0x0FB1:0 - -Test mock non-blocking TCP connection: both peers would block (interleaving) -ssl_mock_tcp_interleaving:0:0x1111:0xEEEE +Test mock non-blocking TCP connection (interleaving) +ssl_mock_tcp_interleaving:0 SSL DTLS replay: initial state, seqnum 0 ssl_dtls_replay:"":"000000000000":0 diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 250fbe047..8816048c4 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -159,7 +159,6 @@ int mbedtls_test_buffer_get( mbedtls_test_buffer *buf, typedef struct mbedtls_mock_socket { int status; - uint32_t blocking_pattern; mbedtls_test_buffer *input; mbedtls_test_buffer *output; struct mbedtls_mock_socket *peer; @@ -268,26 +267,6 @@ exit: return ret; } -/* - * Set the blocking pattern for the socket. - * - * For every bit of \p blocking_pattern set to one the socket will simulate a - * "would block" event. The bits are processed starting with the least - * significant bit and every call to a non-blocking I/O function consumes one. - * - * The behaviour of blocking I/O functions remains unchanged. - */ -int mbedtls_mock_socket_set_block( mbedtls_mock_socket* socket, - uint32_t blocking_pattern ) -{ - if( socket == NULL ) - return -1; - - socket->blocking_pattern = blocking_pattern; - - return 0; -} - /* * Callbacks for simulating blocking I/O over connection-oriented transport. */ @@ -323,14 +302,11 @@ int mbedtls_mock_tcp_send_nb( void *ctx, const unsigned char *buf, size_t len ) if( socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED ) return -1; - if( socket->blocking_pattern & 1 ) + if( socket->output->capacity == socket->output->content_length ) { - socket->blocking_pattern >>= 1; return MBEDTLS_ERR_SSL_WANT_WRITE; } - socket->blocking_pattern >>= 1; - return mbedtls_test_buffer_put( socket->output, buf, len ); } @@ -341,14 +317,11 @@ int mbedtls_mock_tcp_recv_nb( void *ctx, unsigned char *buf, size_t len ) if( socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED ) return -1; - if( socket->blocking_pattern & 1 ) + if( socket->input->content_length == 0) { - socket->blocking_pattern >>= 1; return MBEDTLS_ERR_SSL_WANT_READ; } - socket->blocking_pattern >>= 1; - return mbedtls_test_buffer_get( socket->input, buf, len ); } @@ -928,9 +901,10 @@ exit: */ /* BEGIN_CASE */ -void ssl_mock_tcp( int blocking, int client_pattern, int server_pattern ) +void ssl_mock_tcp( int blocking ) { enum { MSGLEN = 105 }; + enum { BUFLEN = MSGLEN / 5 }; unsigned char message[MSGLEN]; unsigned char received[MSGLEN]; mbedtls_mock_socket client; @@ -939,8 +913,6 @@ void ssl_mock_tcp( int blocking, int client_pattern, int server_pattern ) int send_ret, recv_ret; mbedtls_ssl_send_t *send; mbedtls_ssl_recv_t *recv; - uint32_t client_block = client_pattern; - uint32_t server_block = server_pattern; unsigned i; if( blocking == 0 ) @@ -965,10 +937,7 @@ void ssl_mock_tcp( int blocking, int client_pattern, int server_pattern ) } /* Make sure that sending a message takes a few iterations. */ - TEST_ASSERT( 0 == mbedtls_mock_socket_connect( &client, &server, - MSGLEN / 5 ) ); - TEST_ASSERT( 0 == mbedtls_mock_socket_set_block( &client, client_block ) ); - TEST_ASSERT( 0 == mbedtls_mock_socket_set_block( &server, server_block ) ); + TEST_ASSERT( 0 == mbedtls_mock_socket_connect( &client, &server, BUFLEN ) ); /* Send the message to the server */ send_ret = recv_ret = 1; @@ -977,28 +946,56 @@ void ssl_mock_tcp( int blocking, int client_pattern, int server_pattern ) { send_ret = send( &client, message + written, MSGLEN - written ); - if( ( blocking == 0 ) && ( client_block & 1 ) ) + TEST_ASSERT( send_ret >= 0 ); + TEST_ASSERT( send_ret <= BUFLEN ); + written += send_ret; + + /* If the buffer is full we can test blocking and non-blocking send */ + if ( send_ret == BUFLEN ) { - TEST_ASSERT( send_ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + int blocking_ret = send( &client, message , 1 ); + if ( blocking ) + { + TEST_ASSERT( blocking_ret == 0 ); + } + else + { + TEST_ASSERT( blocking_ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + } } - else - { - TEST_ASSERT( send_ret >= 0 ); - written += send_ret; - } - client_block >>= 1; recv_ret = recv( &server, received + read, MSGLEN - read ); - if( ( blocking == 0 ) && ( server_block & 1 ) ) + + /* The result depends on whether any data was sent */ + if ( send_ret > 0 ) { - TEST_ASSERT( recv_ret == MBEDTLS_ERR_SSL_WANT_READ ); + TEST_ASSERT( recv_ret > 0 ); + TEST_ASSERT( recv_ret <= BUFLEN ); + read += recv_ret; + } + else if( blocking ) + { + TEST_ASSERT( recv_ret == 0 ); } else { - TEST_ASSERT( recv_ret >= 0 ); - read += recv_ret; + TEST_ASSERT( recv_ret == MBEDTLS_ERR_SSL_WANT_READ ); + recv_ret = 0; + } + + /* If the buffer is empty we can test blocking and non-blocking read */ + if ( recv_ret == BUFLEN ) + { + int blocking_ret = recv( &server, received, 1 ); + if ( blocking ) + { + TEST_ASSERT( blocking_ret == 0 ); + } + else + { + TEST_ASSERT( blocking_ret == MBEDTLS_ERR_SSL_WANT_READ ); + } } - server_block >>= 1; } TEST_ASSERT( memcmp( message, received, MSGLEN ) == 0 ); @@ -1016,11 +1013,11 @@ exit: */ /* BEGIN_CASE */ -void ssl_mock_tcp_interleaving( int blocking, - int client_pattern, int server_pattern ) +void ssl_mock_tcp_interleaving( int blocking ) { enum { ROUNDS = 2 }; enum { MSGLEN = 105 }; + enum { BUFLEN = MSGLEN / 5 }; unsigned char message[ROUNDS][MSGLEN]; unsigned char received[ROUNDS][MSGLEN]; mbedtls_mock_socket client; @@ -1032,8 +1029,6 @@ void ssl_mock_tcp_interleaving( int blocking, unsigned i, j, progress; mbedtls_ssl_send_t *send; mbedtls_ssl_recv_t *recv; - uint32_t client_block = client_pattern; - uint32_t server_block = server_pattern; if( blocking == 0 ) { @@ -1060,10 +1055,7 @@ void ssl_mock_tcp_interleaving( int blocking, } /* Make sure that sending a message takes a few iterations. */ - TEST_ASSERT( 0 == mbedtls_mock_socket_connect( &client, &server, - MSGLEN / 5 ) ); - TEST_ASSERT( 0 == mbedtls_mock_socket_set_block( &client, client_block ) ); - TEST_ASSERT( 0 == mbedtls_mock_socket_set_block( &server, server_block ) ); + TEST_ASSERT( 0 == mbedtls_mock_socket_connect( &client, &server, BUFLEN ) ); /* Send the message from both sides, interleaving. */ progress = 1; @@ -1076,72 +1068,80 @@ void ssl_mock_tcp_interleaving( int blocking, * of at least one byte on either side. */ while( progress != 0 ) { - send_ret[0] = send( &client, message[0] + written[0], - MSGLEN - written[0] ); - if( ( blocking == 0 ) && ( client_block & 1 ) ) - { - TEST_ASSERT( send_ret[0] == MBEDTLS_ERR_SSL_WANT_WRITE ); - } - else - { - TEST_ASSERT( send_ret[0] >= 0 ); - written[0] += send_ret[0]; - } - client_block >>= 1; + mbedtls_mock_socket *socket; - send_ret[1] = send( &server, message[1] + written[1], - MSGLEN - written[1] ); - if( ( blocking == 0 ) && ( server_block & 1 ) ) + for( i = 0; i < ROUNDS; i++ ) { - TEST_ASSERT( send_ret[1] == MBEDTLS_ERR_SSL_WANT_WRITE ); - } - else - { - TEST_ASSERT( send_ret[1] >= 0 ); - written[1] += send_ret[1]; - } - server_block >>= 1; + /* First sending is from the client */ + socket = ( i % 2 == 0 ) ? ( &client ) : ( &server ); - recv_ret[0] = recv( &server, received[0] + read[0], - MSGLEN - read[0] ); - if( ( blocking == 0 ) && ( server_block & 1 ) ) - { - TEST_ASSERT( recv_ret[0] == MBEDTLS_ERR_SSL_WANT_READ ); - } - else - { - TEST_ASSERT( recv_ret[0] >= 0 ); - read[0] += recv_ret[0]; - } - server_block >>= 1; + send_ret[i] = send( socket, message[i] + written[i], + MSGLEN - written[i] ); + TEST_ASSERT( send_ret[i] >= 0 ); + TEST_ASSERT( send_ret[i] <= BUFLEN ); + written[i] += send_ret[i]; - recv_ret[1] = recv( &client, received[1] + read[1], - MSGLEN - read[1] ); - if( ( blocking == 0 ) && ( client_block & 1 ) ) - { - TEST_ASSERT( recv_ret[1] == MBEDTLS_ERR_SSL_WANT_READ ); + /* If the buffer is full we can test blocking and non-blocking + * send */ + if ( send_ret[i] == BUFLEN ) + { + int blocking_ret = send( socket, message[i] , 1 ); + if ( blocking ) + { + TEST_ASSERT( blocking_ret == 0 ); + } + else + { + TEST_ASSERT( blocking_ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + } + } } - else + + for( i = 0; i < ROUNDS; i++ ) { - TEST_ASSERT( recv_ret[1] >= 0 ); - read[1] += recv_ret[1]; + /* First receiving is from the server */ + socket = ( i % 2 == 0 ) ? ( &server ) : ( &client ); + + recv_ret[i] = recv( socket, received[i] + read[i], + MSGLEN - read[i] ); + + /* The result depends on whether any data was sent */ + if ( send_ret[i] > 0 ) + { + TEST_ASSERT( recv_ret[i] > 0 ); + TEST_ASSERT( recv_ret[i] <= BUFLEN ); + read[i] += recv_ret[i]; + } + else if( blocking ) + { + TEST_ASSERT( recv_ret[i] == 0 ); + } + else + { + TEST_ASSERT( recv_ret[i] == MBEDTLS_ERR_SSL_WANT_READ ); + recv_ret[i] = 0; + } + + /* If the buffer is empty we can test blocking and non-blocking + * read */ + if ( recv_ret[i] == BUFLEN ) + { + int blocking_ret = recv( socket, received[i], 1 ); + if ( blocking ) + { + TEST_ASSERT( blocking_ret == 0 ); + } + else + { + TEST_ASSERT( blocking_ret == MBEDTLS_ERR_SSL_WANT_READ ); + } + } } - client_block >>= 1; progress = 0; for( i = 0; i < ROUNDS; i++ ) { - if( ( send_ret[i] > 0 ) || - ( send_ret[i] == MBEDTLS_ERR_SSL_WANT_WRITE ) ) - { - progress++; - } - - if( ( recv_ret[i] > 0 ) || - ( recv_ret[i] == MBEDTLS_ERR_SSL_WANT_READ ) ) - { - progress++; - } + progress += send_ret[i] + recv_ret[i]; } }