blob: 348ec348d1cb73212f14076f70a0c9b42798af72 [file] [log] [blame]
/** @file
*
* A brief file description
*
* @section license License
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "catch.hpp"
#include "quic/QUICPacket.h"
#include "quic/QUICPacketFactory.h"
#include "quic/Mock.h"
TEST_CASE("QUICPacketFactory_Create_VersionNegotiationPacket", "[quic]")
{
MockQUICPacketProtectionKeyInfo pp_key_info;
QUICPacketFactory factory(pp_key_info);
const uint8_t raw_dcid[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
const uint8_t raw_scid[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
QUICConnectionId dcid(raw_dcid, 8);
QUICConnectionId scid(raw_scid, 8);
QUICPacketUPtr packet = factory.create_version_negotiation_packet(scid, dcid, QUIC_EXERCISE_VERSION1);
REQUIRE(packet != nullptr);
QUICVersionNegotiationPacket &vn_packet = static_cast<QUICVersionNegotiationPacket &>(*packet);
CHECK(vn_packet.type() == QUICPacketType::VERSION_NEGOTIATION);
CHECK(vn_packet.destination_cid() == scid);
CHECK(vn_packet.source_cid() == dcid);
CHECK(vn_packet.version() == 0x00);
QUICVersion supported_version = QUICTypeUtil::read_QUICVersion(reinterpret_cast<uint8_t *>(vn_packet.payload_block()->start()));
CHECK(supported_version == QUIC_SUPPORTED_VERSIONS[0]);
uint8_t expected[] = {
0xa7, // Long header, Type: NONE
0x00, 0x00, 0x00, 0x00, // Version
0x08, // DCID Len
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Destination Connection ID
0x08, // SCID Len
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Source Connection ID
0x00, 0x00, 0x00, 0x01, // Supported Version
0xff, 0x00, 0x00, 0x1d, // Supported Version
0x5a, 0x6a, 0x7a, 0x8a, // Exercise Version
};
uint8_t buf[1024] = {0};
size_t buf_len;
vn_packet.store(buf, &buf_len);
CHECK((buf[0] & 0x80) == 0x80); // Lower 7 bits of the first byte is random
CHECK(memcmp(buf + 1, expected + 1, buf_len - 1) == 0);
}
TEST_CASE("QUICPacketFactory_Create_Retry", "[quic]")
{
MockQUICPacketProtectionKeyInfo pp_key_info;
QUICPacketFactory factory(pp_key_info);
factory.set_version(0x11223344);
uint8_t raw[] = {0xaa, 0xbb, 0xcc, 0xdd};
QUICRetryToken token(raw, 4);
QUICPacketUPtr packet = factory.create_retry_packet(
QUIC_SUPPORTED_VERSIONS[0], QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04"), 4),
QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14"), 4), token);
REQUIRE(packet != nullptr);
QUICRetryPacket &retry_packet = static_cast<QUICRetryPacket &>(*packet);
CHECK(retry_packet.type() == QUICPacketType::RETRY);
CHECK(retry_packet.destination_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04"), 4));
CHECK(retry_packet.version() == QUIC_SUPPORTED_VERSIONS[0]);
CHECK(retry_packet.token() == token);
}
TEST_CASE("QUICPacketFactory_Create_Handshake", "[quic]")
{
MockQUICPacketProtectionKeyInfo pp_key_info;
pp_key_info.set_encryption_key_available(QUICKeyPhase::HANDSHAKE);
QUICPacketFactory factory(pp_key_info);
factory.set_version(0x11223344);
uint8_t raw[] = {0xaa, 0xbb, 0xcc, 0xdd};
Ptr<IOBufferBlock> payload = make_ptr<IOBufferBlock>(new_IOBufferBlock());
payload->alloc(iobuffer_size_to_index(sizeof(raw), BUFFER_SIZE_INDEX_32K));
payload->fill(sizeof(raw));
memcpy(payload->start(), raw, sizeof(raw));
uint8_t packet_buf[QUICPacket::MAX_INSTANCE_SIZE];
QUICPacketUPtr packet = factory.create_handshake_packet(
packet_buf, QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04"), 4),
QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14"), 4), 0, payload, sizeof(raw), true, false, true);
REQUIRE(packet != nullptr);
QUICHandshakePacket &handshake_packet = reinterpret_cast<QUICHandshakePacket &>(*packet);
CHECK(handshake_packet.type() == QUICPacketType::HANDSHAKE);
CHECK(handshake_packet.destination_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04"), 4));
CHECK(memcmp(handshake_packet.payload_block()->start(), raw, sizeof(raw)) != 0);
CHECK(handshake_packet.packet_number() <= 0xFFFFFBFF);
CHECK(handshake_packet.version() == 0x11223344);
}
TEST_CASE("QUICPacketFactory_Create_StatelessResetPacket", "[quic]")
{
MockQUICPacketProtectionKeyInfo pp_key_info;
QUICPacketFactory factory(pp_key_info);
QUICStatelessResetToken token({reinterpret_cast<const uint8_t *>("\x30\x39"), 2}, 67890);
QUICPacketUPtr packet = factory.create_stateless_reset_packet(token, 1200);
REQUIRE(packet != nullptr);
CHECK(packet->type() == QUICPacketType::STATELESS_RESET);
QUICStatelessResetPacket *sr_packet = dynamic_cast<QUICStatelessResetPacket *>(packet.get());
CHECK(sr_packet->token() == token);
}