def test_long_header_then_short_header(self): builder = create_builder() crypto = create_crypto() # INITIAL, full length builder.start_packet(PACKET_TYPE_INITIAL, crypto) self.assertEqual(builder.remaining_flight_space, 1236) buf = builder.start_frame(QuicFrameType.CRYPTO) buf.push_bytes(bytes(builder.remaining_flight_space)) self.assertFalse(builder.packet_is_empty) # INITIAL, empty builder.start_packet(PACKET_TYPE_INITIAL, crypto) self.assertTrue(builder.packet_is_empty) # ONE_RTT, full length builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) self.assertEqual(builder.remaining_flight_space, 1253) buf = builder.start_frame(QuicFrameType.STREAM_BASE) buf.push_bytes(bytes(builder.remaining_flight_space)) self.assertFalse(builder.packet_is_empty) # ONE_RTT, empty builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) self.assertTrue(builder.packet_is_empty) # check datagrams datagrams, packets = builder.flush() self.assertEqual(len(datagrams), 2) self.assertEqual(len(datagrams[0]), 1280) self.assertEqual(len(datagrams[1]), 1280) self.assertEqual( packets, [ QuicSentPacket( epoch=Epoch.INITIAL, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=0, packet_type=PACKET_TYPE_INITIAL, sent_bytes=1280, ), QuicSentPacket( epoch=Epoch.ONE_RTT, in_flight=True, is_ack_eliciting=True, is_crypto_packet=False, packet_number=1, packet_type=PACKET_TYPE_ONE_RTT, sent_bytes=1280, ), ], ) # check builder self.assertEqual(builder.packet_number, 2)
def test_long_header_then_short_header(self): builder = QuicPacketBuilder( host_cid=bytes(8), packet_number=0, peer_cid=bytes(8), peer_token=b"", spin_bit=False, version=QuicProtocolVersion.DRAFT_20, ) crypto = CryptoPair() crypto.setup_initial(bytes(8), is_client=True) # INITIAL, fully padded builder.start_packet(PACKET_TYPE_INITIAL, crypto) self.assertEqual(builder.remaining_space, 1236) builder.start_frame(QuicFrameType.CRYPTO) builder.buffer.push_bytes(bytes(builder.remaining_space)) self.assertTrue(builder.end_packet()) self.assertEqual(builder.buffer.tell(), 1280) # ONE_RTT, fully padded builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) self.assertEqual(builder.remaining_space, 1253) builder.start_frame(QuicFrameType.STREAM_BASE) builder.buffer.push_bytes(bytes(builder.remaining_space)) self.assertTrue(builder.end_packet()) self.assertEqual(builder.buffer.tell(), 0) # check datagrams datagrams, packets = builder.flush() self.assertEqual(len(datagrams), 2) self.assertEqual(len(datagrams[0]), 1280) self.assertEqual(len(datagrams[1]), 1280) self.assertEqual( packets, [ QuicSentPacket( epoch=Epoch.INITIAL, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=0, packet_type=PACKET_TYPE_INITIAL, sent_bytes=1280, ), QuicSentPacket( epoch=Epoch.ONE_RTT, in_flight=True, is_ack_eliciting=True, is_crypto_packet=False, packet_number=1, packet_type=PACKET_TYPE_ONE_RTT, sent_bytes=1280, ), ], )
def test_short_header_max_total_bytes_3(self): builder = create_builder() builder.max_total_bytes = 2000 crypto = create_crypto() builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) self.assertEqual(builder.remaining_flight_space, 1253) buf = builder.start_frame(QuicFrameType.CRYPTO) buf.push_bytes(bytes(builder.remaining_flight_space)) self.assertFalse(builder.packet_is_empty) builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) self.assertEqual(builder.remaining_flight_space, 693) buf = builder.start_frame(QuicFrameType.CRYPTO) buf.push_bytes(bytes(builder.remaining_flight_space)) self.assertFalse(builder.packet_is_empty) with self.assertRaises(QuicPacketBuilderStop): builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) # check datagrams datagrams, packets = builder.flush() self.assertEqual(len(datagrams), 2) self.assertEqual(len(datagrams[0]), 1280) self.assertEqual(len(datagrams[1]), 720) self.assertEqual( packets, [ QuicSentPacket( epoch=Epoch.ONE_RTT, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=0, packet_type=PACKET_TYPE_ONE_RTT, sent_bytes=1280, ), QuicSentPacket( epoch=Epoch.ONE_RTT, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=1, packet_type=PACKET_TYPE_ONE_RTT, sent_bytes=720, ), ], ) # check builder self.assertEqual(builder.packet_number, 2)
def test_on_ack_received_ack_eliciting(self): packet = QuicSentPacket( epoch=tls.Epoch.ONE_RTT, in_flight=True, is_ack_eliciting=True, is_crypto_packet=False, packet_number=0, packet_type=PACKET_TYPE_ONE_RTT, sent_bytes=1280, sent_time=0.0, ) space = self.ONE_RTT_SPACE # packet sent self.recovery.on_packet_sent(packet, space) self.assertEqual(self.recovery.bytes_in_flight, 1280) self.assertEqual(space.ack_eliciting_in_flight, 1) self.assertEqual(len(space.sent_packets), 1) # packet ack'd self.recovery.on_ack_received(space, ack_rangeset=RangeSet([range(0, 1)]), ack_delay=0.0, now=10.0) self.assertEqual(self.recovery.bytes_in_flight, 0) self.assertEqual(space.ack_eliciting_in_flight, 0) self.assertEqual(len(space.sent_packets), 0) # check RTT self.assertTrue(self.recovery._rtt_initialized) self.assertEqual(self.recovery._rtt_latest, 10.0) self.assertEqual(self.recovery._rtt_min, 10.0) self.assertEqual(self.recovery._rtt_smoothed, 10.0)
def test_short_header_ping_only(self): """ The payload is too short to provide enough data for header protection, so padding needs to be applied. """ builder = create_builder() crypto = create_crypto() # HANDSHAKE, with only a PING frame builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) builder.start_frame(QuicFrameType.PING) self.assertFalse(builder.packet_is_empty) # check datagrams datagrams, packets = builder.flush() self.assertEqual(len(datagrams), 1) self.assertEqual(len(datagrams[0]), 29) self.assertEqual( packets, [ QuicSentPacket( epoch=Epoch.ONE_RTT, in_flight=True, is_ack_eliciting=True, is_crypto_packet=False, packet_number=0, packet_type=PACKET_TYPE_ONE_RTT, sent_bytes=29, ) ], )
def test_long_header_padding(self): builder = create_builder(pad_first_datagram=True) crypto = create_crypto() # INITIAL, fully padded builder.start_packet(PACKET_TYPE_INITIAL, crypto) self.assertEqual(builder.remaining_space, 1236) builder.start_frame(QuicFrameType.CRYPTO) builder.buffer.push_bytes(bytes(100)) self.assertTrue(builder.end_packet()) self.assertEqual(builder.buffer.tell(), 1280) # check datagrams datagrams, packets = builder.flush() self.assertEqual(len(datagrams), 1) self.assertEqual(len(datagrams[0]), 1280) self.assertEqual( packets, [ QuicSentPacket( epoch=Epoch.INITIAL, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=0, packet_type=PACKET_TYPE_INITIAL, sent_bytes=1280, ) ], )
def test_short_header_padding(self): builder = create_builder() crypto = create_crypto() # ONE_RTT, fully padded builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) self.assertEqual(builder.remaining_space, 1253) builder.start_frame(QuicFrameType.CRYPTO) builder.buffer.push_bytes(bytes(builder.remaining_space)) self.assertTrue(builder.end_packet()) # check builder self.assertEqual(builder.buffer.tell(), 0) self.assertEqual(builder.packet_number, 1) # check datagrams datagrams, packets = builder.flush() self.assertEqual(len(datagrams), 1) self.assertEqual(len(datagrams[0]), 1280) self.assertEqual( packets, [ QuicSentPacket( epoch=Epoch.ONE_RTT, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=0, packet_type=PACKET_TYPE_ONE_RTT, sent_bytes=1280, ) ], )
def test_short_header_max_flight_bytes_zero_ack(self): """ max_flight_bytes = 0 only allows ACKs and CONNECTION_CLOSE. Check ACK is allowed. """ builder = create_builder() builder.max_flight_bytes = 0 crypto = create_crypto() builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) buf = builder.start_frame(QuicFrameType.ACK) buf.push_bytes(bytes(64)) with self.assertRaises(QuicPacketBuilderStop): builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) builder.start_frame(QuicFrameType.CRYPTO) # check datagrams datagrams, packets = builder.flush() self.assertEqual(len(datagrams), 1) self.assertEqual(len(datagrams[0]), 92) self.assertEqual( packets, [ QuicSentPacket( epoch=Epoch.ONE_RTT, in_flight=False, is_ack_eliciting=False, is_crypto_packet=False, packet_number=0, packet_type=PACKET_TYPE_ONE_RTT, sent_bytes=92, ), ], ) # check builder self.assertEqual(builder.packet_number, 1)
def test_on_packet_lost_crypto(self): packet = QuicSentPacket( epoch=tls.Epoch.INITIAL, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=0, packet_type=PACKET_TYPE_INITIAL, sent_bytes=1280, sent_time=0.0, ) space = self.INITIAL_SPACE self.recovery.on_packet_sent(packet, space) self.assertEqual(self.recovery.bytes_in_flight, 1280) self.assertEqual(space.ack_eliciting_in_flight, 1) self.assertEqual(len(space.sent_packets), 1) self.recovery._detect_loss(space, now=1.0) self.assertEqual(self.recovery.bytes_in_flight, 0) self.assertEqual(space.ack_eliciting_in_flight, 0) self.assertEqual(len(space.sent_packets), 0)
def test_long_header_initial_server(self): builder = create_builder() crypto = create_crypto() # INITIAL builder.start_packet(PACKET_TYPE_INITIAL, crypto) self.assertEqual(builder.remaining_flight_space, 1236) buf = builder.start_frame(QuicFrameType.CRYPTO) buf.push_bytes(bytes(100)) self.assertFalse(builder.packet_is_empty) # INITIAL, empty builder.start_packet(PACKET_TYPE_INITIAL, crypto) self.assertTrue(builder.packet_is_empty) # check datagrams datagrams, packets = builder.flush() self.assertEqual(len(datagrams), 1) self.assertEqual(len(datagrams[0]), 145) self.assertEqual( packets, [ QuicSentPacket( epoch=Epoch.INITIAL, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=0, packet_type=PACKET_TYPE_INITIAL, sent_bytes=145, ) ], ) # check builder self.assertEqual(builder.packet_number, 1)
def test_long_header_then_long_header(self): builder = create_builder() crypto = create_crypto() # INITIAL builder.start_packet(PACKET_TYPE_INITIAL, crypto) self.assertEqual(builder.remaining_flight_space, 1236) buf = builder.start_frame(QuicFrameType.CRYPTO) buf.push_bytes(bytes(199)) self.assertFalse(builder.packet_is_empty) # HANDSHAKE builder.start_packet(PACKET_TYPE_HANDSHAKE, crypto) self.assertEqual(builder.remaining_flight_space, 993) buf = builder.start_frame(QuicFrameType.CRYPTO) buf.push_bytes(bytes(299)) self.assertFalse(builder.packet_is_empty) # ONE_RTT builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) self.assertEqual(builder.remaining_flight_space, 666) buf = builder.start_frame(QuicFrameType.CRYPTO) buf.push_bytes(bytes(299)) self.assertFalse(builder.packet_is_empty) # check datagrams datagrams, packets = builder.flush() self.assertEqual(len(datagrams), 1) self.assertEqual(len(datagrams[0]), 914) self.assertEqual( packets, [ QuicSentPacket( epoch=Epoch.INITIAL, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=0, packet_type=PACKET_TYPE_INITIAL, sent_bytes=244, ), QuicSentPacket( epoch=Epoch.HANDSHAKE, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=1, packet_type=PACKET_TYPE_HANDSHAKE, sent_bytes=343, ), QuicSentPacket( epoch=Epoch.ONE_RTT, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=2, packet_type=PACKET_TYPE_ONE_RTT, sent_bytes=327, ), ], ) # check builder self.assertEqual(builder.packet_number, 3)
def test_long_header_then_long_header(self): builder = QuicPacketBuilder( host_cid=bytes(8), packet_number=0, peer_cid=bytes(8), peer_token=b"", spin_bit=False, version=QuicProtocolVersion.DRAFT_20, ) crypto = CryptoPair() crypto.setup_initial(bytes(8), is_client=True) # INITIAL builder.start_packet(PACKET_TYPE_INITIAL, crypto) self.assertEqual(builder.remaining_space, 1236) builder.start_frame(QuicFrameType.CRYPTO) builder.buffer.push_bytes(bytes(199)) self.assertEqual(builder.buffer.tell(), 228) self.assertTrue(builder.end_packet()) self.assertEqual(builder.buffer.tell(), 244) # HANDSHAKE builder.start_packet(PACKET_TYPE_HANDSHAKE, crypto) self.assertEqual(builder.buffer.tell(), 271) self.assertEqual(builder.remaining_space, 993) builder.start_frame(QuicFrameType.CRYPTO) builder.buffer.push_bytes(bytes(299)) self.assertEqual(builder.buffer.tell(), 571) self.assertTrue(builder.end_packet()) self.assertEqual(builder.buffer.tell(), 587) # ONE_RTT builder.start_packet(PACKET_TYPE_ONE_RTT, crypto) self.assertEqual(builder.remaining_space, 666) builder.start_frame(QuicFrameType.CRYPTO) builder.buffer.push_bytes(bytes(299)) self.assertTrue(builder.end_packet()) self.assertEqual(builder.buffer.tell(), 0) # check datagrams datagrams, packets = builder.flush() self.assertEqual(len(datagrams), 1) self.assertEqual(len(datagrams[0]), 914) self.assertEqual( packets, [ QuicSentPacket( epoch=Epoch.INITIAL, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=0, packet_type=PACKET_TYPE_INITIAL, sent_bytes=244, ), QuicSentPacket( epoch=Epoch.HANDSHAKE, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=1, packet_type=PACKET_TYPE_HANDSHAKE, sent_bytes=343, ), QuicSentPacket( epoch=Epoch.ONE_RTT, in_flight=True, is_ack_eliciting=True, is_crypto_packet=True, packet_number=2, packet_type=PACKET_TYPE_ONE_RTT, sent_bytes=327, ), ], )