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].

Reply via email to