def test_hex_bytes_untruncated(): """Test whether the hex_bytes correctly renders buffers without truncation.""" short = bytes([0x00, 0x01, 0x02]) assert (hex_bytes(short, truncate=None)) == '0x00 0x01 0x02' buffer = bytes(range(5)) assert hex_bytes(buffer, truncate=6) == '0x00 0x01 0x02 0x03 0x04' assert hex_bytes(buffer, truncate=5) == '0x00 0x01 0x02 0x03 0x04'
def receiver_process(self, event): """Implement CommunicationLink.receiver_process.""" if isinstance(event, LinkException): yield event return result = self.parse_data_unit(event) if isinstance(result, LinkException): yield result return if not self.is_exposable_data_unit(result): self.on_internal_data(result, event) return try: self.logger.debug('Receiving: {}'.format(hex_bytes(result))) except (TypeError, ValueError): self.logger.debug('Receiving: {}'.format(result)) context = {} if isinstance(result, DataUnit): data_unit = result if data_unit.header is not None: context['header'] = data_unit.header if data_unit.footer is not None: context['footer'] = data_unit.footer yield self.make_link_received_event(result, event, context)
def __str__(self): """Represent as a string.""" return '{} passed {} in ({}){}: {}{}'.format( self.__class__.__qualname__, self.direction, self.link, ' with context({})'.format(self.context) if self.context else '', hex_bytes(self.data) if isinstance(self.data, (bytes, bytearray)) else self.data, ', due to ({})'.format(self.previous) if self.previous is not None else '' )
def send_data(stack, data, log=True, **expected_data_kwargs): """Send data on the stack.""" if log: try: logger.info('Sending: {}'.format(hex_bytes(data))) except (TypeError, ValueError): logger.info('Sending: {}'.format(data)) if expected_data_kwargs: stack.send_data(data, **expected_data_kwargs) else: stack.send(data)
def send_data(stack, data, log=True, **expected_data_kwargs): """Send data on the stack.""" if log: try: logger.info('Sending: {}'.format(hex_bytes(data))) except TypeError: logger.info('Sending: {}'.format(data)) with stack.pipeline_lock: if expected_data_kwargs: stack.send_data(data, **expected_data_kwargs) else: stack.send(data)
def __str__(self): """Override LinkData.__str__.""" return '{} passed {} in ({}){} of type {}{}{}: {}{}'.format( self.__class__.__qualname__, self.direction, self.link, ' with context({})'.format(self.context) if self.context else '', self.type_string, ' and format {}'.format(self.format_string) if self.format is not None else '', ' and schema {}'.format( self.schema_string) if self.schema is not None else '', hex_bytes(self.data) if isinstance(self.data, (bytes, bytearray)) else self.data, ', due to ({})'.format(self.previous) if self.previous is not None else '')
def reader_processor(self, chunk_separator): """Override ChunkedStreamLink.reader_processor.""" while True: buffer = yield from read_until(chunk_separator) self.reader_counter['to_read'] += 1 if len(buffer) == 0: continue self.logger.debug('Reading: {}'.format(hex_bytes(buffer))) self._update_read_length_stats(buffer) data_event = self.make_link_data(buffer, 'up', None, type=self.TYPE) self.reader_counter['receive'] += 1 self._event_link.to_receive(data_event)
def test_hex_bytes_truncated(): """Test whether the hex_bytes correctly renders buffers with truncation.""" buffer = bytes(range(5)) assert hex_bytes(buffer, truncate=4) == '0x00 0x01 0x02 0x03 ...(1 more byte)' assert hex_bytes(buffer, truncate=3) == '0x00 0x01 0x02 ...(2 more bytes)' assert hex_bytes(buffer, truncate=2) == '0x00 0x01 ...(3 more bytes)' assert hex_bytes(buffer, truncate=1) == '0x00 ...(4 more bytes)' assert hex_bytes(buffer, truncate=0) == '(5 bytes)' assert hex_bytes(bytes([0x00]), truncate=0) == '(1 byte)'
def sender_process(self, event): """Implement CommunicationLink.sender_process.""" data_unit = self.make_data_unit(event) if data_unit is None: return try: self.logger.debug('Sending: {}'.format(hex_bytes(data_unit))) except (TypeError, ValueError): self.logger.debug('Sending: {}'.format(data_unit)) data_event = self.make_link_data( self.make_send_data_event_data(data_unit), 'down', event, type=self.DATA_UNIT.TYPE) yield data_event
def sender_processor(self, chunk_separator, begin_chunk_separator): """Override ChunkedStreamLink.sender_processor.""" while True: event = yield from receive() data_event = self.get_link_data(event, 'down') if data_event.type not in self.SENDABLE_TYPES: self.logger.error('{} cannot send data of type {}!'.format( self.__class__.__qualname__, data_event.type_string)) continue payload = data_event.data if len(payload) == 0: continue self.sender_counter['send'] += 1 stream_contents = payload + chunk_separator if begin_chunk_separator: stream_contents = chunk_separator + stream_contents self.logger.debug('Writing: {}'.format(hex_bytes(stream_contents))) self._update_send_length_stats(stream_contents) self._stream_link.write(stream_contents)
def body_members_str(self): """Override DataUnit.body.""" return [hex_bytes(self.topic, truncate=None), self.full_payload_string]
def full_payload_string(self): """Return a full string representation of the payload.""" return hex_bytes(self.payload, truncate=None)
def test_hex_bytes_empty(): """Test whether the hex_bytes correctly renders empty buffers.""" assert hex_bytes(bytes([]), truncate=1) == '(0 bytes)' assert hex_bytes(bytes([]), truncate=0) == '(0 bytes)'
def test_hex_bytes_negative_truncate(): """Test whether the hex_bytes correctly handles invalid truncate parameter values.""" with pytest.raises(ValueError): hex_bytes(bytes([0x00, 0x01, 0x02]), truncate=-1) with pytest.raises(ValueError): hex_bytes(bytes([]), truncate=-1)
def test_gbn_sender(): """Test GBNSender in normal behavior.""" print('Testing GBN Sender...') clock = Clock(time=0) sender = GBNSender(clock) print('Testing send queue:') assert sender.counter['send_flushed'] == 0 assert len(list(sender.flush_send_queue())) == 0 assert sender.counter['send_flushed'] == 0 assert sender.counter['send_queued'] == 0 for i in range(sender.SENDER_WINDOW_SIZE - 1): dummy_reliable_buffer = ReliableBuffer(payload=bytes([i])) sender.send(dummy_reliable_buffer) assert sender.send_queue_availability assert sender.counter['send_queued'] == i + 1 assert sender.counter['availability_filled'] == 0 sender.send(ReliableBuffer(payload=bytes([i + 1]))) assert sender.counter['send_queued'] == sender.SENDER_WINDOW_SIZE assert sender.counter['send_availability_filled'] == 1 assert sender.send_queue_availability == 0 assert len(sender.send_queue) == sender.SENDER_WINDOW_SIZE print( 'Expect a warning about over-stuffed send queue with reliable_buffer of ' 'payload {}:'.format(hex_bytes([i + 2]))) assert sender.counter['send_availability_exceeded'] == 0 sender.send(ReliableBuffer(payload=bytes([i + 2]))) assert sender.counter['send_queued'] == sender.SENDER_WINDOW_SIZE + 1 assert sender.counter['send_availability_exceeded'] == 1 assert sender.send_queue_availability == 0 assert len(sender.send_queue) == sender.SENDER_WINDOW_SIZE + 1 print('Testing send queue transmission:') assert sender.counter['send_flushed'] == 0 assert sender.counter['in_flight_queued'] == 0 assert_payload_contents(sender.flush_send_queue(), 0, sender.SENDER_WINDOW_SIZE - 1) assert sender.counter['send_emptied'] == 0 assert sender.counter['send_flushed'] == sender.SENDER_WINDOW_SIZE assert sender.counter['in_flight_queued'] == sender.SENDER_WINDOW_SIZE assert sender.counter['in_flight_availability_filled'] == 1 assert len(sender.in_flight_queue) == sender.SENDER_WINDOW_SIZE assert sender.in_flight_queue_availability == 0 assert len(sender.send_queue) == 1 assert sender.send_queue_availability == sender.SENDER_WINDOW_SIZE - 1 print('Testing in-flight queue timeout:') assert not sender.retransmit_from_timeout clock.update(time=sender.send_timeout) assert sender.retransmit_from_timeout assert sender.counter['in_flight_resent'] == 0 assert len(list( sender.resend_in_flight('timeout'))) == sender.SENDER_WINDOW_SIZE assert sender.counter['in_flight_resent'] == sender.SENDER_WINDOW_SIZE assert not sender.retransmit_from_timeout clock.update(time=2 * sender.send_timeout) assert sender.retransmit_from_timeout assert len(list( sender.resend_in_flight('timeout'))) == sender.SENDER_WINDOW_SIZE assert sender.counter['in_flight_resent'] == 2 * sender.SENDER_WINDOW_SIZE assert not sender.retransmit_from_timeout print('Testing valid ACK:') dummy_ack = ReliableBuffer(header=ReliableBufferHeader( ack_num=1, flags=ReliableBufferFlags(ack=True)), payload=bytes([128])) assert not sender.retransmit_from_received(dummy_ack) assert sender.counter['in_flight_emptied'] == 0 sender.to_receive(dummy_ack) assert sender.counter['acknowledge'] == 1 assert sender.last_acknowledged == 1 assert len(sender.in_flight_queue) == sender.SENDER_WINDOW_SIZE - 1 assert_payload_contents(sender.in_flight_queue, 1, sender.SENDER_WINDOW_SIZE - 1) assert sender.counter['send_emptied'] == 0 assert_payload_contents(sender.flush_send_queue(), sender.SENDER_WINDOW_SIZE, sender.SENDER_WINDOW_SIZE) assert sender.counter['send_emptied'] == 1 assert sender.counter['send_flushed'] == sender.SENDER_WINDOW_SIZE + 1 assert sender.counter['in_flight_queued'] == sender.SENDER_WINDOW_SIZE + 1 assert sender.counter['send_availability_filled'] == 2 assert sender.counter['in_flight_emptied'] == 0 assert len(sender.in_flight_queue) == sender.SENDER_WINDOW_SIZE assert sender.in_flight_queue_availability == 0 assert len(sender.send_queue) == 0 assert sender.send_queue_availability == sender.SENDER_WINDOW_SIZE print('Testing invalid ACK behind:') print('Expect an error about unexpected ACK {}:'.format(0)) dummy_ack = ReliableBuffer(header=ReliableBufferHeader( ack_num=0, flags=ReliableBufferFlags(ack=True)), payload=bytes([128])) assert not sender.retransmit_from_received(dummy_ack) assert sender.counter['acknowledge_unexpected'] == 0 sender.to_receive(dummy_ack) assert sender.counter['acknowledge_unexpected'] == 1 assert sender.counter['acknowledge'] == 1 assert sender.last_acknowledged == 1 assert len(sender.in_flight_queue) == sender.SENDER_WINDOW_SIZE print('Testing invalid ACK ahead:') print('Expect an error about unexpected ACK {}:'.format(100)) dummy_ack = ReliableBuffer(header=ReliableBufferHeader( ack_num=100, flags=ReliableBufferFlags(ack=True)), payload=bytes([128])) assert not sender.retransmit_from_received(dummy_ack) assert sender.counter['acknowledge_unexpected'] == 1 sender.to_receive(dummy_ack) assert sender.counter['acknowledge_unexpected'] == 2 assert sender.counter['acknowledge'] == 1 assert sender.last_acknowledged == 1 assert len(sender.in_flight_queue) == sender.SENDER_WINDOW_SIZE print('Testing NAK:') for ack_num in range(sender.SEQUENCE_NUMBER_SPACE): assert sender.retransmit_from_received( ReliableBuffer(header=ReliableBufferHeader( ack_num=ack_num, flags=ReliableBufferFlags(ack=True, nak=True)), payload=bytes([128]))) assert not sender.retransmit_from_received( ReliableBuffer(header=ReliableBufferHeader( ack_num=1, flags=ReliableBufferFlags(nak=True)), payload=bytes([128]))) print('Testing valid multiple ACK:') dummy_ack = ReliableBuffer(header=ReliableBufferHeader( ack_num=9, flags=ReliableBufferFlags(ack=True)), payload=bytes([128])) assert not sender.retransmit_from_received(dummy_ack) assert sender.counter['in_flight_emptied'] == 0 assert sender.counter['acknowledge'] == 1 sender.to_receive(dummy_ack) assert sender.counter['acknowledge'] == 9 assert sender.last_acknowledged == 9 assert len(sender.in_flight_queue) == 0 assert sender.counter['send_emptied'] == 1 assert len(sender.send_queue) == 0 assert sender.in_flight_queue_availability == sender.SENDER_WINDOW_SIZE assert len(list(sender.flush_send_queue())) == 0 assert sender.counter['send_emptied'] == 1 assert sender.counter['send_flushed'] == sender.SENDER_WINDOW_SIZE + 1 assert sender.counter['in_flight_queued'] == sender.SENDER_WINDOW_SIZE + 1 assert sender.counter['send_availability_filled'] == 2 assert sender.counter['in_flight_emptied'] == 1 assert len(sender.in_flight_queue) == 0 assert sender.in_flight_queue_availability == sender.SENDER_WINDOW_SIZE assert len(sender.send_queue) == 0 assert sender.send_queue_availability == sender.SENDER_WINDOW_SIZE
def test_reliable_buffer_link(): """Test ReliableBufferLink in normal behavior.""" print('Testing ReliableBuffer Link...') reliable_buffer_counter = 0 reliable_buffer_link = ReliableBufferLink() print('Requesting to send {} reliable buffers...'.format( 2 * GBNSender.SENDER_WINDOW_SIZE)) for i in range(2 * GBNSender.SENDER_WINDOW_SIZE): reliable_buffer_link.send(bytes([0, reliable_buffer_counter])) reliable_buffer_counter += 1 assert (reliable_buffer_link.sender_counter['send_reliable_buffer'] == 2 * GBNSender.SENDER_WINDOW_SIZE) assert (reliable_buffer_link.arq_sender.counter['send_flushed'] == GBNSender.SENDER_WINDOW_SIZE) assert (reliable_buffer_link.arq_sender.counter['send_queued'] == 2 * GBNSender.SENDER_WINDOW_SIZE) assert (reliable_buffer_link.arq_sender.counter['send_availability_filled'] == 1) assert (reliable_buffer_link.arq_sender. counter['send_availability_exceeded'] == 0) assert (reliable_buffer_link.sender_counter['to_send_in_flight'] == GBNSender.SENDER_WINDOW_SIZE) assert (reliable_buffer_link.arq_sender.counter['in_flight_queued'] == GBNSender.SENDER_WINDOW_SIZE) assert (reliable_buffer_link.arq_sender. counter['in_flight_availability_filled'] == 1) assert not reliable_buffer_link.arq_sender.send_queue_availability assert reliable_buffer_link.has_to_send() to_send = list(reliable_buffer_link.to_send_all()) assert len(to_send) == GBNSender.SENDER_WINDOW_SIZE + 1 assert isinstance(to_send[1], LinkClockRequest) assert to_send[ 1].requested_time == reliable_buffer_link.arq_sender.send_timeout del to_send[1] assert_send_reliable_buffer_ranges(to_send, 0, GBNSender.SENDER_WINDOW_SIZE - 1, DATA_TYPES[('bytes', 'buffer')], 0, 0, GBNSender.SENDER_WINDOW_SIZE - 1) print( 'Requesting to send another reliable buffer to over-stuff the send queue...' ) print( 'Expect a warning about over-stuffed send queue with reliable buffer ' 'of payload {}:'.format(hex_bytes([reliable_buffer_counter]))) reliable_buffer_link.send(bytes([0, reliable_buffer_counter])) reliable_buffer_counter += 1 assert (reliable_buffer_link.sender_counter['send_reliable_buffer'] == reliable_buffer_counter) assert (reliable_buffer_link.arq_sender.counter['send_queued'] == reliable_buffer_counter) assert (reliable_buffer_link.arq_sender. counter['send_availability_exceeded'] == 1) print('Letting in-flight reliable buffers time out...') assert not reliable_buffer_link.has_to_send() reliable_buffer_link.update_clock( reliable_buffer_link.arq_sender.send_timeout) assert (reliable_buffer_link.clock.time == reliable_buffer_link.arq_sender.send_timeout) assert reliable_buffer_link.sender_counter['timeout_retransmission'] == 1 assert (reliable_buffer_link.sender_counter['to_send_retransmission'] == GBNSender.SENDER_WINDOW_SIZE) assert (reliable_buffer_link.arq_sender.counter['in_flight_resent'] == GBNSender.SENDER_WINDOW_SIZE) assert (reliable_buffer_link.sender_counter['to_send_in_flight'] == GBNSender.SENDER_WINDOW_SIZE) assert reliable_buffer_link.has_to_send() to_send = list(reliable_buffer_link.to_send_all()) assert len(to_send) == GBNSender.SENDER_WINDOW_SIZE + 1 assert isinstance(to_send[-1], LinkClockRequest) assert (to_send[-1].requested_time == 2 * reliable_buffer_link.arq_sender.send_timeout) del to_send[-1] assert_send_reliable_buffer_ranges(to_send, 0, GBNSender.SENDER_WINDOW_SIZE - 1, DATA_TYPES[('bytes', 'buffer')], 0, 0, GBNSender.SENDER_WINDOW_SIZE - 1) print('Receiving a valid ACK...') ack = ReliableBuffer(header=ReliableBufferHeader( seq_num=0, ack_num=1, flags=ReliableBufferFlags(ack=True), type=DATA_TYPES[('transport', 'validated_datagram')]), payload=bytes([255, 0])) assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 0 reliable_buffer_link.to_receive(ack.buffer) # Check receive assert reliable_buffer_link.receiver_counter[ 'to_receive_reliable_buffer'] == 1 assert reliable_buffer_link.receiver_counter[ 'unexpected_reliable_buffer'] == 0 assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1 assert reliable_buffer_link.arq_sender.counter['acknowledge_rollover'] == 0 assert reliable_buffer_link.arq_sender.counter[ 'acknowledge_unexpected'] == 0 assert reliable_buffer_link.arq_sender.counter['in_flight_emptied'] == 0 assert reliable_buffer_link.has_receive() receive = list(reliable_buffer_link.receive_all()) assert len(receive) == 1 assert_receive_reliable_buffer_ranges( receive, 0, 0, DATA_TYPES[('transport', 'validated_datagram')], 255, 0, 0) # Check to_send assert reliable_buffer_link.receiver_counter[ 'requested_retransmission'] == 0 assert reliable_buffer_link.receiver_counter['to_send_retransmission'] == 0 assert reliable_buffer_link.receiver_counter['to_send_in_flight'] == 1 assert (reliable_buffer_link.arq_sender.counter['in_flight_queued'] == GBNSender.SENDER_WINDOW_SIZE + 1) assert (reliable_buffer_link.arq_sender. counter['in_flight_availability_filled'] == 2) assert reliable_buffer_link.has_to_send() to_send = list(reliable_buffer_link.to_send_all()) assert_send_reliable_buffer_ranges(to_send, 8, 8, DATA_TYPES[('bytes', 'buffer')], 0, 8, 8) print('Letting in-flight reliable buffers time out...') assert not reliable_buffer_link.has_to_send() reliable_buffer_link.update_clock( 2 * reliable_buffer_link.arq_sender.send_timeout) assert (reliable_buffer_link.clock.time == 2 * reliable_buffer_link.arq_sender.send_timeout) assert reliable_buffer_link.sender_counter['timeout_retransmission'] == 2 assert ( reliable_buffer_link.sender_counter['to_send_retransmission'] == 2 * GBNSender.SENDER_WINDOW_SIZE) assert (reliable_buffer_link.arq_sender.counter['in_flight_resent'] == 2 * GBNSender.SENDER_WINDOW_SIZE) assert (reliable_buffer_link.sender_counter['to_send_in_flight'] == GBNSender.SENDER_WINDOW_SIZE) assert reliable_buffer_link.has_to_send() to_send = list(reliable_buffer_link.to_send_all()) assert len(to_send) == GBNSender.SENDER_WINDOW_SIZE + 1 assert isinstance(to_send[-1], LinkClockRequest) assert (to_send[-1].requested_time == 3 * reliable_buffer_link.arq_sender.send_timeout) del to_send[-1] assert_send_reliable_buffer_ranges(to_send, 1, GBNSender.SENDER_WINDOW_SIZE, DATA_TYPES[('bytes', 'buffer')], 0, 1, GBNSender.SENDER_WINDOW_SIZE) print('Receiving an invalid ACK behind...') ack = ReliableBuffer(header=ReliableBufferHeader( seq_num=1, ack_num=0, flags=ReliableBufferFlags(ack=True)), payload=bytes([255, 1])) assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1 assert reliable_buffer_link.receiver_counter[ 'unexpected_reliable_buffer'] == 0 print('Expect two errors about unexpected ACK {}:'.format(0)) reliable_buffer_link.to_receive(ack.buffer) # Check receive assert reliable_buffer_link.receiver_counter[ 'to_receive_reliable_buffer'] == 2 assert reliable_buffer_link.receiver_counter[ 'unexpected_reliable_buffer'] == 1 assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1 assert reliable_buffer_link.arq_sender.counter['acknowledge_rollover'] == 0 assert reliable_buffer_link.arq_sender.counter[ 'acknowledge_unexpected'] == 1 assert reliable_buffer_link.arq_sender.counter['in_flight_emptied'] == 0 assert not reliable_buffer_link.has_receive() # Check to_send assert reliable_buffer_link.receiver_counter[ 'requested_retransmission'] == 0 assert reliable_buffer_link.receiver_counter['to_send_retransmission'] == 0 assert reliable_buffer_link.receiver_counter['to_send_in_flight'] == 1 print('Receiving an invalid ACK ahead...') ack = ReliableBuffer(header=ReliableBufferHeader( seq_num=2, ack_num=255, flags=ReliableBufferFlags(ack=True)), payload=bytes([255, 2])) print('Expect two errors about unexpected ACK {}:'.format(255)) assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1 reliable_buffer_link.to_receive(ack.buffer) # Check receive assert reliable_buffer_link.receiver_counter[ 'to_receive_reliable_buffer'] == 3 assert reliable_buffer_link.receiver_counter[ 'unexpected_reliable_buffer'] == 2 assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1 assert reliable_buffer_link.arq_sender.counter['acknowledge_rollover'] == 0 assert reliable_buffer_link.arq_sender.counter[ 'acknowledge_unexpected'] == 2 assert reliable_buffer_link.arq_sender.counter['in_flight_emptied'] == 0 assert not reliable_buffer_link.has_receive() # Check to_send assert reliable_buffer_link.receiver_counter[ 'requested_retransmission'] == 0 assert reliable_buffer_link.receiver_counter['to_send_retransmission'] == 0 assert reliable_buffer_link.receiver_counter['to_send_in_flight'] == 1 assert not reliable_buffer_link.has_to_send() print('Receiving a NAK...') nak = ReliableBuffer(header=ReliableBufferHeader( seq_num=3, ack_num=1, flags=ReliableBufferFlags(ack=True, nak=True), type=DATA_TYPES[('layer', 'control')], ), payload=bytes([255, 3])) assert reliable_buffer_link.receiver_counter[ 'requested_retransmission'] == 0 assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1 assert not reliable_buffer_link.has_to_send() reliable_buffer_link.to_receive(nak.buffer) # Check receive assert reliable_buffer_link.receiver_counter[ 'to_receive_reliable_buffer'] == 4 assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1 assert reliable_buffer_link.receiver_counter[ 'requested_retransmission'] == 1 assert (reliable_buffer_link.receiver_counter['to_send_retransmission'] == GBNSender.SENDER_WINDOW_SIZE) assert (reliable_buffer_link.arq_sender.counter['in_flight_resent'] == 3 * GBNSender.SENDER_WINDOW_SIZE) assert not reliable_buffer_link.has_receive() # Check send assert (reliable_buffer_link.sender_counter['to_send_in_flight'] == GBNSender.SENDER_WINDOW_SIZE) assert reliable_buffer_link.has_to_send() assert_send_reliable_buffer_ranges( list(reliable_buffer_link.to_send_all()), 1, GBNSender.SENDER_WINDOW_SIZE, DATA_TYPES[('bytes', 'buffer')], 0, 1, GBNSender.SENDER_WINDOW_SIZE) print('Receiving a valid multiple ACK...') ack = ReliableBuffer(header=ReliableBufferHeader( seq_num=4, ack_num=9, flags=ReliableBufferFlags(ack=True), type=DATA_TYPES[('transport', 'datagram')]), payload=bytes([255, 4])) assert reliable_buffer_link.receiver_counter[ 'to_receive_reliable_buffer'] == 4 assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1 assert reliable_buffer_link.arq_sender.counter['acknowledge_rollover'] == 0 assert reliable_buffer_link.arq_sender.counter['in_flight_emptied'] == 0 reliable_buffer_link.to_receive(ack.buffer) # Check receive assert reliable_buffer_link.receiver_counter[ 'to_receive_reliable_buffer'] == 5 assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 9 assert reliable_buffer_link.arq_sender.counter['acknowledge_rollover'] == 0 assert reliable_buffer_link.arq_sender.counter['in_flight_emptied'] == 0 assert reliable_buffer_link.has_receive() assert_receive_reliable_buffer_ranges( list(reliable_buffer_link.receive_all()), 4, 4, DATA_TYPES[('transport', 'datagram')], 255, 4, 4) # Check send assert reliable_buffer_link.receiver_counter['to_send_in_flight'] == 9 assert reliable_buffer_link.arq_sender.counter['in_flight_queued'] == ( 2 * GBNSender.SENDER_WINDOW_SIZE + 1) assert (reliable_buffer_link.arq_sender. counter['in_flight_availability_filled'] == 3) assert reliable_buffer_link.has_to_send() assert_send_reliable_buffer_ranges( list(reliable_buffer_link.to_send_all()), GBNSender.SENDER_WINDOW_SIZE + 1, GBNSender.SENDER_WINDOW_SIZE * 2, DATA_TYPES[('bytes', 'buffer')], 0, GBNSender.SENDER_WINDOW_SIZE + 1, GBNSender.SENDER_WINDOW_SIZE * 2)