| /** @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/QUICPathValidator.h" |
| #include "quic/Mock.h" |
| #include "stdio.h" |
| #include "stdlib.h" |
| |
| TEST_CASE("QUICPathValidator", "[quic]") |
| { |
| MockQUICConnectionInfoProvider cinfo_provider; |
| QUICPathValidator pv_c(cinfo_provider, [](bool x) {}); |
| QUICPathValidator pv_s(cinfo_provider, [](bool x) {}); |
| |
| SECTION("interests") |
| { |
| auto interests = pv_c.interests(); |
| CHECK(std::find_if(interests.begin(), interests.end(), [](QUICFrameType t) { return t == QUICFrameType::PATH_CHALLENGE; }) != |
| interests.end()); |
| CHECK(std::find_if(interests.begin(), interests.end(), [](QUICFrameType t) { return t == QUICFrameType::PATH_RESPONSE; }) != |
| interests.end()); |
| CHECK(std::find_if(interests.begin(), interests.end(), [](QUICFrameType t) { |
| return t != QUICFrameType::PATH_CHALLENGE && t != QUICFrameType::PATH_RESPONSE; |
| }) == interests.end()); |
| } |
| |
| SECTION("basic scenario") |
| { |
| uint8_t frame_buf[1024]; |
| uint32_t seq_num = 1; |
| IpEndpoint local, remote; |
| ats_ip_pton("127.0.0.1:4433", &local); |
| ats_ip_pton("127.0.0.1:12345", &remote); |
| QUICPath path = {local, remote}; |
| |
| // Send a challenge |
| CHECK(!pv_c.is_validating(path)); |
| CHECK(!pv_c.is_validated(path)); |
| REQUIRE(!pv_c.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, false, seq_num)); |
| pv_c.validate(path); |
| CHECK(pv_c.is_validating(path)); |
| CHECK(!pv_c.is_validated(path)); |
| REQUIRE(pv_c.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, false, seq_num)); |
| auto frame = pv_c.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 1024, 1024, 0, seq_num); |
| REQUIRE(frame); |
| CHECK(frame->type() == QUICFrameType::PATH_CHALLENGE); |
| CHECK(pv_c.is_validating(path)); |
| CHECK(!pv_c.is_validated(path)); |
| ++seq_num; |
| |
| // Receive the challenge and respond |
| CHECK(!pv_s.is_validating(path)); |
| CHECK(!pv_s.is_validated(path)); |
| REQUIRE(!pv_s.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, false, seq_num)); |
| auto error = pv_s.handle_frame(QUICEncryptionLevel::ONE_RTT, *frame); |
| REQUIRE(!error); |
| CHECK(!pv_s.is_validating(path)); |
| CHECK(!pv_s.is_validated(path)); |
| REQUIRE(pv_s.will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, false, seq_num)); |
| frame->~QUICFrame(); |
| frame = pv_s.generate_frame(frame_buf, QUICEncryptionLevel::ONE_RTT, 1024, 1024, 0, seq_num); |
| REQUIRE(frame); |
| CHECK(frame->type() == QUICFrameType::PATH_RESPONSE); |
| CHECK(!pv_s.is_validating(path)); |
| CHECK(!pv_s.is_validated(path)); |
| ++seq_num; |
| |
| uint8_t buf[1024]; |
| size_t len = 0; |
| uint8_t received_frame_buf[1024]; |
| Ptr<IOBufferBlock> ibb = frame->to_io_buffer_block(sizeof(buf)); |
| for (auto b = ibb; b; b = b->next) { |
| memcpy(buf + len, b->start(), b->size()); |
| len += b->size(); |
| } |
| MockQUICPacket mock_packet; |
| auto received_frame = QUICFrameFactory::create(received_frame_buf, buf, len, &mock_packet); |
| mock_packet.set_from(remote); |
| mock_packet.set_to(local); |
| |
| // Receive the response |
| error = pv_c.handle_frame(QUICEncryptionLevel::ONE_RTT, *received_frame); |
| REQUIRE(!error); |
| CHECK(!pv_c.is_validating(path)); |
| CHECK(pv_c.is_validated(path)); |
| |
| frame->~QUICFrame(); |
| received_frame->~QUICFrame(); |
| } |
| } |