def test_encode_quic_version_negotiation(self): data = encode_quic_version_negotiation( destination_cid=binascii.unhexlify("dae1889b81a91c26"), source_cid=binascii.unhexlify("f49243784f9bf3be"), supported_versions=[QuicProtocolVersion.DRAFT_18, 0x1A2A3A4A], ) self.assertEqual(data[1:], load("version_negotiation.bin")[1:])
def datagram_received(self, datagram, addr): buf = Buffer(data=datagram) header = pull_quic_header(buf, host_cid_length=8) # version negotiation if (header.version is not None and header.version not in QuicConnection.supported_versions): self._transport.sendto( encode_quic_version_negotiation( source_cid=header.destination_cid, destination_cid=header.source_cid, supported_versions=QuicConnection.supported_versions, ), addr, ) return connection = self._connections.get(header.destination_cid, None) if connection is None and header.packet_type == PACKET_TYPE_INITIAL: # create new connection connection = QuicConnection(is_client=False, **self._kwargs) connection.connection_made(QuicConnectionTransport(self, addr)) connection.stream_created_cb = self.stream_created self._connections[connection.host_cid] = connection logger.info("%s New connection from %s" % (connection_id(connection), addr)) if connection is not None: connection.datagram_received(datagram, addr)
def test_version_negotiation_ok(self): client = create_standalone_client(self) # found a common version, retry client.receive_datagram( encode_quic_version_negotiation( source_cid=client._peer_cid, destination_cid=client.host_cid, supported_versions=[QuicProtocolVersion.DRAFT_19], ), SERVER_ADDR, now=time.time(), ) self.assertEqual(drop(client), 1)
def test_version_negotiation_ok(self): client, client_transport = create_standalone_client() self.assertEqual(client_transport.sent, 1) # found a common version, retry client.datagram_received( encode_quic_version_negotiation( source_cid=client.peer_cid, destination_cid=client.host_cid, supported_versions=[QuicProtocolVersion.DRAFT_19], ), SERVER_ADDR, ) self.assertEqual(client_transport.sent, 2)
def test_version_negotiation_fail(self): client, client_transport = create_standalone_client() self.assertEqual(client_transport.sent, 1) # no common version, no retry client.datagram_received( encode_quic_version_negotiation( source_cid=client.peer_cid, destination_cid=client.host_cid, supported_versions=[0xFF000011], # DRAFT_16 ), SERVER_ADDR, ) self.assertEqual(client_transport.sent, 1)
def test_version_negotiation_ok(self): client = QuicConnection(is_client=True) client_transport = FakeTransport() client.connection_made(client_transport) self.assertEqual(client_transport.sent, 1) # found a common version, retry client.datagram_received( encode_quic_version_negotiation( source_cid=client.peer_cid, destination_cid=client.host_cid, supported_versions=[QuicProtocolVersion.DRAFT_19], ), None, ) self.assertEqual(client_transport.sent, 2)
def test_version_negotiation_fail(self): client = QuicConnection(is_client=True) client_transport = FakeTransport() client.connection_made(client_transport) self.assertEqual(client_transport.sent, 1) # no common version, no retry client.datagram_received( encode_quic_version_negotiation( source_cid=client.peer_cid, destination_cid=client.host_cid, supported_versions=[0xFF000011], # DRAFT_16 ), None, ) self.assertEqual(client_transport.sent, 1)
def test_version_negotiation_fail(self): client = create_standalone_client(self) # no common version, no retry client.receive_datagram( encode_quic_version_negotiation( source_cid=client._peer_cid, destination_cid=client.host_cid, supported_versions=[0xFF000011], # DRAFT_16 ), SERVER_ADDR, now=time.time(), ) self.assertEqual(drop(client), 0) event = client.next_event() self.assertEqual(type(event), events.ConnectionTerminated) self.assertEqual(event.error_code, QuicErrorCode.INTERNAL_ERROR) self.assertEqual(event.frame_type, None) self.assertEqual(event.reason_phrase, "Could not find a common protocol version")
def test_version_negotiation_fail(self): client, client_transport = create_standalone_client() self.assertEqual(client_transport.sent, 1) # no common version, no retry client.datagram_received( encode_quic_version_negotiation( source_cid=client._peer_cid, destination_cid=client.host_cid, supported_versions=[0xFF000011], # DRAFT_16 ), SERVER_ADDR, ) self.assertEqual(client_transport.sent, 1) with self.assertRaises(QuicConnectionError) as cm: run(client.wait_connected()) self.assertEqual(cm.exception.error_code, QuicErrorCode.INTERNAL_ERROR) self.assertEqual(cm.exception.frame_type, None) self.assertEqual(cm.exception.reason_phrase, "Could not find a common protocol version")
def datagram_received(self, data: Union[bytes, Text], addr: NetworkAddress) -> None: data = cast(bytes, data) buf = Buffer(data=data) header = pull_quic_header(buf, host_cid_length=8) # version negotiation if (header.version is not None and header.version not in self._configuration.supported_versions): self._transport.sendto( encode_quic_version_negotiation( source_cid=header.destination_cid, destination_cid=header.source_cid, supported_versions=self._configuration.supported_versions, ), addr, ) return connection = self._connections.get(header.destination_cid, None) original_connection_id: Optional[bytes] = None if connection is None and header.packet_type == PACKET_TYPE_INITIAL: # stateless retry if self._retry is not None: if not header.token: # create a retry token self._transport.sendto( encode_quic_retry( version=header.version, source_cid=os.urandom(8), destination_cid=header.source_cid, original_destination_cid=header.destination_cid, retry_token=self._retry.create_token( addr, header.destination_cid), ), addr, ) return else: # validate retry token try: original_connection_id = self._retry.validate_token( addr, header.token) except ValueError: return # create new connection connection = QuicConnection( configuration=self._configuration, original_connection_id=original_connection_id, session_ticket_fetcher=self._session_ticket_fetcher, session_ticket_handler=self._session_ticket_handler, ) self._connections[header.destination_cid] = connection self._connections[connection.host_cid] = connection if connection is not None: connection.receive_datagram(cast(bytes, data), addr, now=self._loop.time()) self._consume_events(connection)