This is an automated email from the ASF dual-hosted git repository. masaori pushed a commit to branch quic-latest in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 528f1ee56b7857c716fd74352b4ba04f19772027 Author: Masaori Koshiba <[email protected]> AuthorDate: Wed Apr 4 15:06:13 2018 +0900 Add VERSION_NEGOTIATION packet support to QUICVersionNegotiator --- iocore/net/quic/QUICTransportParameters.cc | 12 +++++ iocore/net/quic/QUICTransportParameters.h | 1 + iocore/net/quic/QUICTypes.h | 2 + iocore/net/quic/QUICVersionNegotiator.cc | 63 ++++++++++++++++++++-- iocore/net/quic/QUICVersionNegotiator.h | 1 + .../net/quic/test/test_QUICTransportParameters.cc | 1 + iocore/net/quic/test/test_QUICVersionNegotiator.cc | 55 +++++++++++++++++-- 7 files changed, 128 insertions(+), 7 deletions(-) diff --git a/iocore/net/quic/QUICTransportParameters.cc b/iocore/net/quic/QUICTransportParameters.cc index 7b74a6f..9a8182f 100644 --- a/iocore/net/quic/QUICTransportParameters.cc +++ b/iocore/net/quic/QUICTransportParameters.cc @@ -439,6 +439,18 @@ QUICTransportParametersInEncryptedExtensions::add_version(QUICVersion version) this->_versions[this->_n_versions++] = version; } +bool +QUICTransportParametersInEncryptedExtensions::is_valid_negotiated_version() const +{ + for (int i = 0; QUICVersion v = this->_versions[i]; i++) { + if (this->_negotiated_version == v) { + return true; + } + } + + return false; +} + std::ptrdiff_t QUICTransportParametersInEncryptedExtensions::_parameters_offset(const uint8_t *buf) const { diff --git a/iocore/net/quic/QUICTransportParameters.h b/iocore/net/quic/QUICTransportParameters.h index 11bc8b0..96ff64b 100644 --- a/iocore/net/quic/QUICTransportParameters.h +++ b/iocore/net/quic/QUICTransportParameters.h @@ -136,6 +136,7 @@ public: QUICTransportParametersInEncryptedExtensions(const uint8_t *buf, size_t len); QUICVersion negotiated_version() const; void add_version(QUICVersion version); + bool is_valid_negotiated_version() const; protected: std::ptrdiff_t _parameters_offset(const uint8_t *buf) const override; diff --git a/iocore/net/quic/QUICTypes.h b/iocore/net/quic/QUICTypes.h index 78b9a01..57de391 100644 --- a/iocore/net/quic/QUICTypes.h +++ b/iocore/net/quic/QUICTypes.h @@ -49,6 +49,8 @@ using QUICOffset = uint64_t; constexpr QUICVersion QUIC_SUPPORTED_VERSIONS[] = { 0xff000009, }; +constexpr QUICVersion QUIC_EXERCISE_VERSIONS = 0x1a2a3a4a; + constexpr QUICStreamId STREAM_ID_FOR_HANDSHAKE = 0; enum class QUICHandshakeMsgType { diff --git a/iocore/net/quic/QUICVersionNegotiator.cc b/iocore/net/quic/QUICVersionNegotiator.cc index 2329c31..8aff8a9 100644 --- a/iocore/net/quic/QUICVersionNegotiator.cc +++ b/iocore/net/quic/QUICVersionNegotiator.cc @@ -31,12 +31,40 @@ QUICVersionNegotiator::status() } QUICVersionNegotiationStatus -QUICVersionNegotiator::negotiate(const QUICPacket *initial_packet) +QUICVersionNegotiator::negotiate(const QUICPacket *packet) { - if (QUICTypeUtil::is_supported_version(initial_packet->version())) { - this->_status = QUICVersionNegotiationStatus::NEGOTIATED; - this->_negotiated_version = initial_packet->version(); + switch (packet->type()) { + case QUICPacketType::INITIAL: { + if (QUICTypeUtil::is_supported_version(packet->version())) { + this->_status = QUICVersionNegotiationStatus::NEGOTIATED; + this->_negotiated_version = packet->version(); + } + + break; + } + case QUICPacketType::VERSION_NEGOTIATION: { + const uint8_t *supported_versions = packet->payload(); + uint16_t supported_versions_len = packet->payload_size(); + uint16_t len = 0; + + while (len < supported_versions_len) { + QUICVersion version = QUICTypeUtil::read_QUICVersion(supported_versions + len); + len += sizeof(QUICVersion); + + if (QUICTypeUtil::is_supported_version(version)) { + this->_status = QUICVersionNegotiationStatus::NEGOTIATED; + this->_negotiated_version = version; + break; + } + } + + break; } + default: + ink_assert(false); + break; + } + return this->_status; } @@ -46,6 +74,7 @@ QUICVersionNegotiator::validate(const QUICTransportParametersInClientHello *tp) if (this->_negotiated_version == tp->initial_version()) { this->_status = QUICVersionNegotiationStatus::VALIDATED; } else { + // Version negotiation was performed if (QUICTypeUtil::is_supported_version(tp->initial_version())) { this->_status = QUICVersionNegotiationStatus::FAILED; this->_negotiated_version = 0; @@ -56,6 +85,32 @@ QUICVersionNegotiator::validate(const QUICTransportParametersInClientHello *tp) return this->_status; } +QUICVersionNegotiationStatus +QUICVersionNegotiator::validate(const QUICTransportParametersInEncryptedExtensions *tp) +{ + if (!tp->is_valid_negotiated_version()) { + this->_status = QUICVersionNegotiationStatus::FAILED; + this->_negotiated_version = 0; + + return this->_status; + } + + if (this->_status == QUICVersionNegotiationStatus::NEGOTIATED) { + // Version negotiation was performed + if (this->_negotiated_version == tp->negotiated_version()) { + this->_status = QUICVersionNegotiationStatus::VALIDATED; + } else { + this->_status = QUICVersionNegotiationStatus::FAILED; + this->_negotiated_version = 0; + } + } else { + this->_status = QUICVersionNegotiationStatus::VALIDATED; + this->_negotiated_version = tp->negotiated_version(); + } + + return this->_status; +} + QUICVersion QUICVersionNegotiator::negotiated_version() { diff --git a/iocore/net/quic/QUICVersionNegotiator.h b/iocore/net/quic/QUICVersionNegotiator.h index 651a7db..c59d59e 100644 --- a/iocore/net/quic/QUICVersionNegotiator.h +++ b/iocore/net/quic/QUICVersionNegotiator.h @@ -37,6 +37,7 @@ public: QUICVersionNegotiationStatus status(); QUICVersionNegotiationStatus negotiate(const QUICPacket *initial_packet); QUICVersionNegotiationStatus validate(const QUICTransportParametersInClientHello *tp); + QUICVersionNegotiationStatus validate(const QUICTransportParametersInEncryptedExtensions *tp); QUICVersion negotiated_version(); private: diff --git a/iocore/net/quic/test/test_QUICTransportParameters.cc b/iocore/net/quic/test/test_QUICTransportParameters.cc index cc73714..3e26f93 100644 --- a/iocore/net/quic/test/test_QUICTransportParameters.cc +++ b/iocore/net/quic/test/test_QUICTransportParameters.cc @@ -153,6 +153,7 @@ TEST_CASE("QUICTransportParametersInEncryptedExtensions_read", "[quic]") QUICTransportParametersInEncryptedExtensions params_in_ee(buf, sizeof(buf)); CHECK(params_in_ee.is_valid()); + CHECK(params_in_ee.is_valid_negotiated_version()); CHECK(params_in_ee.negotiated_version() == 0x01020304); uint16_t len = 0; diff --git a/iocore/net/quic/test/test_QUICVersionNegotiator.cc b/iocore/net/quic/test/test_QUICVersionNegotiator.cc index be32502..a318c98 100644 --- a/iocore/net/quic/test/test_QUICVersionNegotiator.cc +++ b/iocore/net/quic/test/test_QUICVersionNegotiator.cc @@ -26,7 +26,7 @@ #include "quic/QUICVersionNegotiator.h" #include "quic/Mock.h" -TEST_CASE("QUICVersionNegotiator", "[quic]") +TEST_CASE("QUICVersionNegotiator - Server Side", "[quic]") { QUICPacketFactory packet_factory; MockQUICHandshakeProtocol hs_protocol; @@ -63,7 +63,7 @@ TEST_CASE("QUICVersionNegotiator", "[quic]") CHECK(vn.status() == QUICVersionNegotiationStatus::NEGOTIATED); // Validate version - QUICTransportParametersInClientHello tp(0xbabababa); + QUICTransportParametersInClientHello tp(QUIC_EXERCISE_VERSIONS); vn.validate(&tp); CHECK(vn.status() == QUICVersionNegotiationStatus::VALIDATED); CHECK(vn.negotiated_version() == QUIC_SUPPORTED_VERSIONS[0]); @@ -75,7 +75,7 @@ TEST_CASE("QUICVersionNegotiator", "[quic]") CHECK(vn.status() == QUICVersionNegotiationStatus::NOT_NEGOTIATED); // Negotiate version - packet_factory.set_version(0xbabababa); + packet_factory.set_version(QUIC_EXERCISE_VERSIONS); QUICPacketUPtr initial_packet = packet_factory.create_initial_packet({}, 0, ats_unique_malloc(0), 0); vn.negotiate(initial_packet.get()); CHECK(vn.status() == QUICVersionNegotiationStatus::NOT_NEGOTIATED); @@ -87,3 +87,52 @@ TEST_CASE("QUICVersionNegotiator", "[quic]") CHECK(vn.negotiated_version() != QUIC_SUPPORTED_VERSIONS[0]); } } + +TEST_CASE("QUICVersionNegotiator - Client Side", "[quic]") +{ + QUICPacketFactory packet_factory; + MockQUICHandshakeProtocol hs_protocol; + packet_factory.set_hs_protocol(&hs_protocol); + QUICVersionNegotiator vn; + + SECTION("Normal case") + { + // Check initial state + CHECK(vn.status() == QUICVersionNegotiationStatus::NOT_NEGOTIATED); + + // No Version Negotiation packet from server + + // Validate version + QUICTransportParametersInEncryptedExtensions tp(QUIC_SUPPORTED_VERSIONS[0]); + tp.add_version(QUIC_SUPPORTED_VERSIONS[0]); + + vn.validate(&tp); + CHECK(vn.status() == QUICVersionNegotiationStatus::VALIDATED); + CHECK(vn.negotiated_version() == QUIC_SUPPORTED_VERSIONS[0]); + } + + SECTION("Negotiation case") + { + // Check initial state + CHECK(vn.status() == QUICVersionNegotiationStatus::NOT_NEGOTIATED); + + // Negotiate version + packet_factory.set_version(QUIC_EXERCISE_VERSIONS); + QUICPacketUPtr initial_packet = packet_factory.create_initial_packet({}, 0, ats_unique_malloc(0), 0); + + // Server send VN packet based on Initial packet + QUICPacketUPtr vn_packet = packet_factory.create_version_negotiation_packet(initial_packet.get()); + + // Negotiate version + vn.negotiate(vn_packet.get()); + CHECK(vn.status() == QUICVersionNegotiationStatus::NEGOTIATED); + CHECK(vn.negotiated_version() == QUIC_SUPPORTED_VERSIONS[0]); + + // Validate version + QUICTransportParametersInEncryptedExtensions tp(QUIC_SUPPORTED_VERSIONS[0]); + tp.add_version(QUIC_SUPPORTED_VERSIONS[0]); + + vn.validate(&tp); + CHECK(vn.status() == QUICVersionNegotiationStatus::VALIDATED); + } +} -- To stop receiving notification emails like this one, please contact [email protected].
