Change non-blocking read/write in TCP mock socket
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
This commit is contained in:
parent
fb437d72ef
commit
890b5ca330
2 changed files with 118 additions and 136 deletions
|
@ -35,34 +35,16 @@ Test mock socket sanity
|
||||||
ssl_mock_sanity:
|
ssl_mock_sanity:
|
||||||
|
|
||||||
Test mock blocking TCP connection
|
Test mock blocking TCP connection
|
||||||
ssl_mock_tcp:1:0:0
|
ssl_mock_tcp:1
|
||||||
|
|
||||||
Test mock non-blocking TCP connection: would not block
|
Test mock non-blocking TCP connection
|
||||||
ssl_mock_tcp:0:0:0
|
ssl_mock_tcp: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 blocking TCP connection (interleaving)
|
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)
|
Test mock non-blocking TCP connection (interleaving)
|
||||||
ssl_mock_tcp_interleaving:0:0:0
|
ssl_mock_tcp_interleaving: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
|
|
||||||
|
|
||||||
SSL DTLS replay: initial state, seqnum 0
|
SSL DTLS replay: initial state, seqnum 0
|
||||||
ssl_dtls_replay:"":"000000000000":0
|
ssl_dtls_replay:"":"000000000000":0
|
||||||
|
|
|
@ -159,7 +159,6 @@ int mbedtls_test_buffer_get( mbedtls_test_buffer *buf,
|
||||||
typedef struct mbedtls_mock_socket
|
typedef struct mbedtls_mock_socket
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
uint32_t blocking_pattern;
|
|
||||||
mbedtls_test_buffer *input;
|
mbedtls_test_buffer *input;
|
||||||
mbedtls_test_buffer *output;
|
mbedtls_test_buffer *output;
|
||||||
struct mbedtls_mock_socket *peer;
|
struct mbedtls_mock_socket *peer;
|
||||||
|
@ -268,26 +267,6 @@ exit:
|
||||||
return ret;
|
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.
|
* 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 )
|
if( socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED )
|
||||||
return -1;
|
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;
|
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket->blocking_pattern >>= 1;
|
|
||||||
|
|
||||||
return mbedtls_test_buffer_put( socket->output, buf, len );
|
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 )
|
if( socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if( socket->blocking_pattern & 1 )
|
if( socket->input->content_length == 0)
|
||||||
{
|
{
|
||||||
socket->blocking_pattern >>= 1;
|
|
||||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket->blocking_pattern >>= 1;
|
|
||||||
|
|
||||||
return mbedtls_test_buffer_get( socket->input, buf, len );
|
return mbedtls_test_buffer_get( socket->input, buf, len );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,9 +901,10 @@ exit:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* BEGIN_CASE */
|
/* BEGIN_CASE */
|
||||||
void ssl_mock_tcp( int blocking, int client_pattern, int server_pattern )
|
void ssl_mock_tcp( int blocking )
|
||||||
{
|
{
|
||||||
enum { MSGLEN = 105 };
|
enum { MSGLEN = 105 };
|
||||||
|
enum { BUFLEN = MSGLEN / 5 };
|
||||||
unsigned char message[MSGLEN];
|
unsigned char message[MSGLEN];
|
||||||
unsigned char received[MSGLEN];
|
unsigned char received[MSGLEN];
|
||||||
mbedtls_mock_socket client;
|
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;
|
int send_ret, recv_ret;
|
||||||
mbedtls_ssl_send_t *send;
|
mbedtls_ssl_send_t *send;
|
||||||
mbedtls_ssl_recv_t *recv;
|
mbedtls_ssl_recv_t *recv;
|
||||||
uint32_t client_block = client_pattern;
|
|
||||||
uint32_t server_block = server_pattern;
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
if( blocking == 0 )
|
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. */
|
/* Make sure that sending a message takes a few iterations. */
|
||||||
TEST_ASSERT( 0 == mbedtls_mock_socket_connect( &client, &server,
|
TEST_ASSERT( 0 == mbedtls_mock_socket_connect( &client, &server, BUFLEN ) );
|
||||||
MSGLEN / 5 ) );
|
|
||||||
TEST_ASSERT( 0 == mbedtls_mock_socket_set_block( &client, client_block ) );
|
|
||||||
TEST_ASSERT( 0 == mbedtls_mock_socket_set_block( &server, server_block ) );
|
|
||||||
|
|
||||||
/* Send the message to the server */
|
/* Send the message to the server */
|
||||||
send_ret = recv_ret = 1;
|
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 );
|
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
|
else
|
||||||
{
|
{
|
||||||
TEST_ASSERT( send_ret >= 0 );
|
TEST_ASSERT( blocking_ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||||
written += send_ret;
|
}
|
||||||
}
|
}
|
||||||
client_block >>= 1;
|
|
||||||
|
|
||||||
recv_ret = recv( &server, received + read, MSGLEN - read );
|
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
|
else
|
||||||
{
|
{
|
||||||
TEST_ASSERT( recv_ret >= 0 );
|
TEST_ASSERT( recv_ret == MBEDTLS_ERR_SSL_WANT_READ );
|
||||||
read += recv_ret;
|
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 );
|
TEST_ASSERT( memcmp( message, received, MSGLEN ) == 0 );
|
||||||
|
|
||||||
|
@ -1016,11 +1013,11 @@ exit:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* BEGIN_CASE */
|
/* BEGIN_CASE */
|
||||||
void ssl_mock_tcp_interleaving( int blocking,
|
void ssl_mock_tcp_interleaving( int blocking )
|
||||||
int client_pattern, int server_pattern )
|
|
||||||
{
|
{
|
||||||
enum { ROUNDS = 2 };
|
enum { ROUNDS = 2 };
|
||||||
enum { MSGLEN = 105 };
|
enum { MSGLEN = 105 };
|
||||||
|
enum { BUFLEN = MSGLEN / 5 };
|
||||||
unsigned char message[ROUNDS][MSGLEN];
|
unsigned char message[ROUNDS][MSGLEN];
|
||||||
unsigned char received[ROUNDS][MSGLEN];
|
unsigned char received[ROUNDS][MSGLEN];
|
||||||
mbedtls_mock_socket client;
|
mbedtls_mock_socket client;
|
||||||
|
@ -1032,8 +1029,6 @@ void ssl_mock_tcp_interleaving( int blocking,
|
||||||
unsigned i, j, progress;
|
unsigned i, j, progress;
|
||||||
mbedtls_ssl_send_t *send;
|
mbedtls_ssl_send_t *send;
|
||||||
mbedtls_ssl_recv_t *recv;
|
mbedtls_ssl_recv_t *recv;
|
||||||
uint32_t client_block = client_pattern;
|
|
||||||
uint32_t server_block = server_pattern;
|
|
||||||
|
|
||||||
if( blocking == 0 )
|
if( blocking == 0 )
|
||||||
{
|
{
|
||||||
|
@ -1060,10 +1055,7 @@ void ssl_mock_tcp_interleaving( int blocking,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure that sending a message takes a few iterations. */
|
/* Make sure that sending a message takes a few iterations. */
|
||||||
TEST_ASSERT( 0 == mbedtls_mock_socket_connect( &client, &server,
|
TEST_ASSERT( 0 == mbedtls_mock_socket_connect( &client, &server, BUFLEN ) );
|
||||||
MSGLEN / 5 ) );
|
|
||||||
TEST_ASSERT( 0 == mbedtls_mock_socket_set_block( &client, client_block ) );
|
|
||||||
TEST_ASSERT( 0 == mbedtls_mock_socket_set_block( &server, server_block ) );
|
|
||||||
|
|
||||||
/* Send the message from both sides, interleaving. */
|
/* Send the message from both sides, interleaving. */
|
||||||
progress = 1;
|
progress = 1;
|
||||||
|
@ -1076,72 +1068,80 @@ void ssl_mock_tcp_interleaving( int blocking,
|
||||||
* of at least one byte on either side. */
|
* of at least one byte on either side. */
|
||||||
while( progress != 0 )
|
while( progress != 0 )
|
||||||
{
|
{
|
||||||
send_ret[0] = send( &client, message[0] + written[0],
|
mbedtls_mock_socket *socket;
|
||||||
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;
|
|
||||||
|
|
||||||
send_ret[1] = send( &server, message[1] + written[1],
|
for( i = 0; i < ROUNDS; i++ )
|
||||||
MSGLEN - written[1] );
|
|
||||||
if( ( blocking == 0 ) && ( server_block & 1 ) )
|
|
||||||
{
|
{
|
||||||
TEST_ASSERT( send_ret[1] == MBEDTLS_ERR_SSL_WANT_WRITE );
|
/* First sending is from the client */
|
||||||
}
|
socket = ( i % 2 == 0 ) ? ( &client ) : ( &server );
|
||||||
else
|
|
||||||
{
|
|
||||||
TEST_ASSERT( send_ret[1] >= 0 );
|
|
||||||
written[1] += send_ret[1];
|
|
||||||
}
|
|
||||||
server_block >>= 1;
|
|
||||||
|
|
||||||
recv_ret[0] = recv( &server, received[0] + read[0],
|
send_ret[i] = send( socket, message[i] + written[i],
|
||||||
MSGLEN - read[0] );
|
MSGLEN - written[i] );
|
||||||
if( ( blocking == 0 ) && ( server_block & 1 ) )
|
TEST_ASSERT( send_ret[i] >= 0 );
|
||||||
{
|
TEST_ASSERT( send_ret[i] <= BUFLEN );
|
||||||
TEST_ASSERT( recv_ret[0] == MBEDTLS_ERR_SSL_WANT_READ );
|
written[i] += send_ret[i];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TEST_ASSERT( recv_ret[0] >= 0 );
|
|
||||||
read[0] += recv_ret[0];
|
|
||||||
}
|
|
||||||
server_block >>= 1;
|
|
||||||
|
|
||||||
recv_ret[1] = recv( &client, received[1] + read[1],
|
/* If the buffer is full we can test blocking and non-blocking
|
||||||
MSGLEN - read[1] );
|
* send */
|
||||||
if( ( blocking == 0 ) && ( client_block & 1 ) )
|
if ( send_ret[i] == BUFLEN )
|
||||||
{
|
{
|
||||||
TEST_ASSERT( recv_ret[1] == MBEDTLS_ERR_SSL_WANT_READ );
|
int blocking_ret = send( socket, message[i] , 1 );
|
||||||
|
if ( blocking )
|
||||||
|
{
|
||||||
|
TEST_ASSERT( blocking_ret == 0 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TEST_ASSERT( recv_ret[1] >= 0 );
|
TEST_ASSERT( blocking_ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||||
read[1] += recv_ret[1];
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < ROUNDS; i++ )
|
||||||
|
{
|
||||||
|
/* 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;
|
progress = 0;
|
||||||
for( i = 0; i < ROUNDS; i++ )
|
for( i = 0; i < ROUNDS; i++ )
|
||||||
{
|
{
|
||||||
if( ( send_ret[i] > 0 ) ||
|
progress += send_ret[i] + recv_ret[i];
|
||||||
( send_ret[i] == MBEDTLS_ERR_SSL_WANT_WRITE ) )
|
|
||||||
{
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ( recv_ret[i] > 0 ) ||
|
|
||||||
( recv_ret[i] == MBEDTLS_ERR_SSL_WANT_READ ) )
|
|
||||||
{
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue