static void flush_send_queue( int fd, void *user_data ) { UNUSED( fd ); UNUSED( user_data ); assert( send_queue != NULL ); assert( connection.fd >= 0 ); debug( "Flushing send queue ( length = %u ).", send_queue->length ); set_writable( connection.fd, false ); buffer *buf = NULL; while ( ( buf = peek_message( send_queue ) ) != NULL ) { ssize_t write_length = write( connection.fd, buf->data, buf->length ); if ( write_length < 0 ) { if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) { set_writable( connection.fd, true ); return; } error( "Failed to send a message to secure channel ( errno = %s [%d] ).", strerror( errno ), errno ); return; } if ( ( size_t ) write_length < buf->length ) { remove_front_buffer( buf, ( size_t ) write_length ); set_writable( connection.fd, true ); return; } buf = dequeue_message( send_queue ); free_buffer( buf ); } }
int flush_secure_channel( struct switch_info *sw_info ) { assert( sw_info != NULL ); assert( sw_info->send_queue != NULL ); assert( sw_info->secure_channel_fd >= 0 ); buffer *buf; ssize_t write_length; while ( ( buf = peek_message( sw_info->send_queue ) ) != NULL ) { write_length = write( sw_info->secure_channel_fd, buf->data, buf->length ); if ( write_length < 0 ) { if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) { return 0; } error( "Failed to send a message to secure channel ( errno = %s [%d] ).", strerror( errno ), errno ); return -1; } if ( ( size_t ) write_length < buf->length ) { remove_front_buffer( buf, ( size_t ) write_length ); return 0; } buf = dequeue_message( sw_info->send_queue ); free_buffer( buf ); } return 0; }
static void test_peek_message() { message_queue *queue = create_message_queue(); assert_true( queue != NULL ); buffer *peek_buf = peek_message( queue ); assert_true( peek_buf == NULL ); buffer *first_buf = alloc_buffer(); assert_true( enqueue_message( queue, first_buf ) ); assert_int_equal( queue->length, 1 ); buffer *second_buf = alloc_buffer(); assert_true( enqueue_message( queue, second_buf ) ); assert_int_equal( queue->length, 2 ); buffer *third_buf = alloc_buffer(); assert_true( enqueue_message( queue, third_buf ) ); assert_int_equal( queue->length, 3 ); peek_buf = peek_message( queue ); assert_true( peek_buf == first_buf ); buffer *deq_buf = dequeue_message( queue ); assert_true( deq_buf == first_buf ); free_buffer( deq_buf ); assert_int_equal( queue->length, 2 ); peek_buf = peek_message( queue ); assert_true( peek_buf == second_buf ); deq_buf = dequeue_message( queue ); assert_true( deq_buf == second_buf ); free_buffer( deq_buf ); assert_int_equal( queue->length, 1 ); peek_buf = peek_message( queue ); assert_true( peek_buf == third_buf ); deq_buf = dequeue_message( queue ); assert_true( deq_buf == third_buf ); free_buffer( deq_buf ); assert_int_equal( queue->length, 0 ); peek_buf = peek_message( queue ); assert_true( peek_buf == NULL ); deq_buf = dequeue_message( queue ); assert_true( deq_buf == NULL ); assert_int_equal( queue->length, 0 ); assert_true( delete_message_queue( queue ) ); }
int flush_secure_channel( struct switch_info *sw_info ) { assert( sw_info != NULL ); assert( sw_info->send_queue != NULL ); assert( sw_info->secure_channel_fd >= 0 ); buffer *buf; ssize_t write_length; if ( sw_info->send_queue->length == 0 ) { return 0; } set_writable( sw_info->secure_channel_fd, false ); writev_args args; args.iov = xmalloc( sizeof( struct iovec ) * ( size_t ) sw_info->send_queue->length ); args.iovcnt = 0; foreach_message_queue( sw_info->send_queue, append_to_writev_args, &args ); if ( args.iovcnt == 0 ) { xfree( args.iov ); return 0; } write_length = writev( sw_info->secure_channel_fd, args.iov, args.iovcnt ); xfree( args.iov ); if ( write_length < 0 ) { if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) { set_writable( sw_info->secure_channel_fd, true ); return 0; } error( "Failed to send a message to secure channel ( errno = %s [%d] ).", strerror( errno ), errno ); return -1; } if ( write_length == 0 ) { return 0; } while ( ( buf = peek_message( sw_info->send_queue ) ) != NULL ) { if ( write_length == 0 ) { set_writable( sw_info->secure_channel_fd, true ); return 0; } if ( ( size_t ) write_length < buf->length ) { remove_front_buffer( buf, ( size_t ) write_length ); set_writable( sw_info->secure_channel_fd, true ); return 0; } write_length -= ( ssize_t ) buf->length; buf = dequeue_message( sw_info->send_queue ); free_buffer( buf ); } return 0; }
static int flush_secure_channel_tls( struct switch_info *sw_info ) { assert( sw_info != NULL ); assert( sw_info->tls ); assert( sw_info->ssl != NULL ); assert( sw_info->send_queue->length > 0 ); buffer *buf = NULL; while ( ( buf = peek_message( sw_info->send_queue ) ) != NULL ) { int write_length = SSL_write( sw_info->ssl, buf->data, ( int ) buf->length ); if ( write_length < 0 ) { int error_no = SSL_get_error( sw_info->ssl, write_length ); switch ( error_no ) { case SSL_ERROR_WANT_READ: set_readable( sw_info->secure_channel_fd, true ); case SSL_ERROR_WANT_WRITE: set_writable( sw_info->secure_channel_fd, true ); return 0; default: error( "Failed to send a message to secure channel ( error = %d ).", error_no ); return -1; } } if ( write_length == 0 ) { set_writable( sw_info->secure_channel_fd, true ); return 0; } if ( ( size_t ) write_length < buf->length ) { remove_front_buffer( buf, ( size_t ) write_length ); set_writable( sw_info->secure_channel_fd, true ); return 0; } buf = dequeue_message( sw_info->send_queue ); free_buffer( buf ); } return 0; }
static void test_peek_message_if_queue_is_not_created() { message_queue *queue = NULL; expect_assert_failure( peek_message( queue ) ); }