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


The following commit(s) were added to refs/heads/quic-latest by this push:
     new dbdd3d2  Check version in QUICPacketHandlerIn
dbdd3d2 is described below

commit dbdd3d29115d11d474c3d18c2474c0cd530b5a24
Author: Masaori Koshiba <[email protected]>
AuthorDate: Fri Jun 15 10:25:30 2018 +0900

    Check version in QUICPacketHandlerIn
---
 .gitignore                                         |   1 +
 iocore/net/P_QUICPacketHandler.h                   |   2 -
 iocore/net/QUICPacketHandler.cc                    | 136 +++++++++++--------
 iocore/net/quic/QUICConfig.h                       |   2 +
 iocore/net/quic/QUICHandshake.cc                   |   3 +-
 iocore/net/quic/QUICPacket.cc                      |  10 +-
 iocore/net/quic/QUICPacket.h                       |  10 +-
 iocore/net/quic/QUICTypes.cc                       |  96 +++++++++++++-
 iocore/net/quic/QUICTypes.h                        |  21 ++-
 iocore/net/quic/test/Makefile.am                   |  17 +++
 iocore/net/quic/test/test_QUICInvariants.cc        | 147 +++++++++++++++++++++
 iocore/net/quic/test/test_QUICPacketFactory.cc     |  30 +----
 iocore/net/quic/test/test_QUICVersionNegotiator.cc |   3 +-
 13 files changed, 385 insertions(+), 93 deletions(-)

diff --git a/.gitignore b/.gitignore
index 5514f1c..2f58694 100644
--- a/.gitignore
+++ b/.gitignore
@@ -99,6 +99,7 @@ iocore/net/quic/test/test_QUICFrameDispatcher
 iocore/net/quic/test/test_QUICLossDetector
 iocore/net/quic/test/test_QUICHandshake
 iocore/net/quic/test/test_QUICIncomingFrameBuffer
+iocore/net/quic/test/test_QUICInvariants
 iocore/net/quic/test/test_QUICKeyGenerator
 iocore/net/quic/test/test_QUICPacket
 iocore/net/quic/test/test_QUICPacketFactory
diff --git a/iocore/net/P_QUICPacketHandler.h b/iocore/net/P_QUICPacketHandler.h
index dd7067d..3e982bc 100644
--- a/iocore/net/P_QUICPacketHandler.h
+++ b/iocore/net/P_QUICPacketHandler.h
@@ -44,8 +44,6 @@ public:
 
 protected:
   static void _send_packet(Continuation *c, const QUICPacket &packet, 
UDPConnection *udp_con, IpEndpoint &addr, uint32_t pmtu);
-  static QUICConnectionId _read_destination_connection_id(IOBufferBlock 
*block);
-  static QUICConnectionId _read_source_connection_id(IOBufferBlock *block);
 
   Event *_collector_event                       = nullptr;
   QUICClosedConCollector *_closed_con_collector = nullptr;
diff --git a/iocore/net/QUICPacketHandler.cc b/iocore/net/QUICPacketHandler.cc
index 732a1ae..a596c35 100644
--- a/iocore/net/QUICPacketHandler.cc
+++ b/iocore/net/QUICPacketHandler.cc
@@ -30,11 +30,13 @@
 #include "QUICDebugNames.h"
 #include "QUICEvents.h"
 
-#define QUICDebugQC(qc, fmt, ...) Debug("quic_sec", "[%s] " fmt, 
qc->cids().data(), ##__VA_ARGS__)
+static constexpr char tag[] = "quic_sec";
+
+#define QUICDebug(fmt, ...) Debug(tag, fmt, ##__VA_ARGS__)
+#define QUICDebugQC(qc, fmt, ...) Debug(tag, "[%s] " fmt, qc->cids().data(), 
##__VA_ARGS__)
 
 // ["local dcid" - "local scid"]
-#define QUICDebugDS(dcid, scid, fmt, ...) \
-  Debug("quic_sec", "[%08" PRIx32 "-%08" PRIx32 "] " fmt, dcid.h32(), 
scid.h32(), ##__VA_ARGS__)
+#define QUICDebugDS(dcid, scid, fmt, ...) Debug(tag, "[%08" PRIx32 "-%08" 
PRIx32 "] " fmt, dcid.h32(), scid.h32(), ##__VA_ARGS__)
 
 //
 // QUICPacketHandler
@@ -78,33 +80,21 @@ QUICPacketHandler::_send_packet(Continuation *c, const 
QUICPacket &packet, UDPCo
 
   UDPPacket *udp_packet = new_UDPPacket(addr, 0, udp_payload);
 
-  // NOTE: p will be enqueued to udpOutQueue of UDPNetHandler
-  ip_port_text_buffer ipb;
-  QUICConnectionId dcid = packet.destination_cid();
-  QUICConnectionId scid = QUICConnectionId::ZERO();
-  if (packet.type() != QUICPacketType::PROTECTED) {
-    scid = packet.source_cid();
+  if (is_debug_tag_set(tag)) {
+    ip_port_text_buffer ipb;
+    QUICConnectionId dcid = packet.destination_cid();
+    QUICConnectionId scid = QUICConnectionId::ZERO();
+    if (packet.type() != QUICPacketType::PROTECTED) {
+      scid = packet.source_cid();
+    }
+    QUICDebugDS(dcid, scid, "send %s packet to %s size=%" PRId64, 
QUICDebugNames::packet_type(packet.type()),
+                ats_ip_nptop(&udp_packet->to.sa, ipb, sizeof(ipb)), 
udp_packet->getPktLength());
   }
-  QUICDebugDS(dcid, scid, "send %s packet to %s size=%" PRId64, 
QUICDebugNames::packet_type(packet.type()),
-              ats_ip_nptop(&udp_packet->to.sa, ipb, sizeof(ipb)), 
udp_packet->getPktLength());
 
+  // NOTE: packet will be enqueued to udpOutQueue of UDPNetHandler
   udp_con->send(c, udp_packet);
 }
 
-QUICConnectionId
-QUICPacketHandler::_read_destination_connection_id(IOBufferBlock *block)
-{
-  const uint8_t *buf = reinterpret_cast<const uint8_t *>(block->buf());
-  return QUICPacket::destination_connection_id(buf);
-}
-
-QUICConnectionId
-QUICPacketHandler::_read_source_connection_id(IOBufferBlock *block)
-{
-  const uint8_t *buf = reinterpret_cast<const uint8_t *>(block->buf());
-  return QUICPacket::source_connection_id(buf);
-}
-
 //
 // QUICPacketHandlerIn
 //
@@ -182,54 +172,91 @@ QUICPacketHandlerIn::init_accept(EThread *t = nullptr)
 void
 QUICPacketHandlerIn::_recv_packet(int event, UDPPacket *udp_packet)
 {
-  EThread *eth           = nullptr;
-  QUICPollEvent *qe      = nullptr;
-  QUICNetVConnection *vc = nullptr;
-  IOBufferBlock *block   = udp_packet->getIOBlockChain();
+  // Assumption: udp_packet has only one IOBufferBlock
+  IOBufferBlock *block = udp_packet->getIOBlockChain();
+  const uint8_t *buf   = reinterpret_cast<uint8_t *>(block->buf());
+  uint64_t buf_len     = block->size();
 
-  if (is_debug_tag_set("quic_sec")) {
-    ip_port_text_buffer ipb;
-    QUICConnectionId dcid = this->_read_destination_connection_id(block);
-    QUICConnectionId scid = QUICConnectionId::ZERO();
-    if (QUICTypeUtil::has_long_header(reinterpret_cast<const uint8_t 
*>(block->buf()))) {
-      scid = this->_read_source_connection_id(block);
+  if (buf_len == 0) {
+    QUICDebug("Ignore packet - payload is too small");
+    udp_packet->free();
+    return;
+  }
+
+  QUICConnectionId dcid = QUICConnectionId::ZERO();
+  QUICConnectionId scid = QUICConnectionId::ZERO();
+
+  // TODO: lookup by 5-Tuple
+  // When ATS omits SCID, endpoint omits DCID. In this case, we can't get DCID 
from SH packet, we need to lookup QC by 5-Tuple.
+  if (!QUICInvariants::dcid(dcid, buf, buf_len)) {
+    QUICDebug("Ignore packet - payload is too small");
+    udp_packet->free();
+    return;
+  }
+
+  if (QUICInvariants::is_long_header(buf)) {
+    if (!QUICInvariants::scid(scid, buf, buf_len)) {
+      QUICDebug("Ignore packet - payload is too small");
+      udp_packet->free();
+      return;
+    }
+
+    if (is_debug_tag_set(tag)) {
+      ip_port_text_buffer ipb;
+      QUICDebugDS(scid, dcid, "recv LH packet from %s size=%" PRId64, 
ats_ip_nptop(&udp_packet->from.sa, ipb, sizeof(ipb)),
+                  udp_packet->getPktLength());
+    }
+
+    QUICVersion v;
+    if (unlikely(!QUICInvariants::version(v, buf, buf_len))) {
+      QUICDebug("Ignore packet - payload is too small");
+      udp_packet->free();
+      return;
+    }
+
+    if (!QUICInvariants::is_version_negotiation(v) && 
!QUICTypeUtil::is_supported_version(v)) {
+      QUICDebugDS(scid, dcid, "Unsupported version: 0x%x", v);
+
+      QUICPacketUPtr vn = 
QUICPacketFactory::create_version_negotiation_packet(scid, dcid);
+      this->_send_packet(this, *vn, udp_packet->getConnection(), 
udp_packet->from, 1200);
+      udp_packet->free();
+      return;
+    }
+  } else {
+    if (is_debug_tag_set(tag)) {
+      ip_port_text_buffer ipb;
+      QUICDebugDS(scid, dcid, "recv SH packet from %s size=%" PRId64, 
ats_ip_nptop(&udp_packet->from.sa, ipb, sizeof(ipb)),
+                  udp_packet->getPktLength());
     }
-    // Remote dst cid is src cid in local
-    // TODO: print packet type
-    QUICDebugDS(scid, dcid, "recv packet from %s, size=%" PRId64, 
ats_ip_nptop(&udp_packet->from.sa, ipb, sizeof(ipb)),
-                udp_packet->getPktLength());
   }
 
-  QUICConnection *qc =
-    this->_ctable->lookup(reinterpret_cast<const uint8_t *>(block->buf()), 
{udp_packet->from, udp_packet->to, SOCK_DGRAM});
+  QUICConnection *qc     = this->_ctable->lookup(buf, {udp_packet->from, 
udp_packet->to, SOCK_DGRAM});
+  QUICNetVConnection *vc = static_cast<QUICNetVConnection *>(qc);
 
-  vc = static_cast<QUICNetVConnection *>(qc);
   // 7.1. Matching Packets to Connections
   // A server that discards a packet that cannot be associated with a 
connection MAY also generate a stateless reset
   // Send stateless reset if the packet is not a initial packet or connection 
is closed.
   if ((!vc && !QUICTypeUtil::has_long_header(reinterpret_cast<const uint8_t 
*>(block->buf()))) || (vc && vc->in_closed_queue)) {
-    Connection con;
-    con.setRemote(&udp_packet->from.sa);
-    QUICConnectionId cid = this->_read_destination_connection_id(block);
     QUICStatelessResetToken token;
     {
       QUICConfig::scoped_config params;
-      token.generate(cid, params->server_id());
+      token.generate(dcid, params->server_id());
     }
-    auto packet = QUICPacketFactory::create_stateless_reset_packet(cid, token);
-    this->_send_packet(this, *packet, udp_packet->getConnection(), con.addr, 
1200);
+    auto packet = QUICPacketFactory::create_stateless_reset_packet(dcid, 
token);
+    this->_send_packet(this, *packet, udp_packet->getConnection(), 
udp_packet->from, 1200);
     udp_packet->free();
     return;
   }
 
+  EThread *eth = nullptr;
   if (!vc) {
+    // Create a new NetVConnection
     Connection con;
     con.setRemote(&udp_packet->from.sa);
 
-    eth = eventProcessor.assign_thread(ET_NET);
-    // Create a new NetVConnection
-    QUICConnectionId original_cid = 
this->_read_destination_connection_id(block);
-    QUICConnectionId peer_cid     = this->_read_source_connection_id(block);
+    eth                           = eventProcessor.assign_thread(ET_NET);
+    QUICConnectionId original_cid = dcid;
+    QUICConnectionId peer_cid     = scid;
 
     if (is_debug_tag_set("quic_sec")) {
       char client_dcid_hex_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
@@ -256,11 +283,12 @@ QUICPacketHandlerIn::_recv_packet(int event, UDPPacket 
*udp_packet)
     eth = vc->thread;
   }
 
-  qe = quicPollEventAllocator.alloc();
-
+  QUICPollEvent *qe = quicPollEventAllocator.alloc();
   qe->init(qc, static_cast<UDPPacketInternal *>(udp_packet));
   // Push the packet into QUICPollCont
   get_QUICPollCont(eth)->inQueue.push(qe);
+
+  return;
 }
 
 // TODO: Should be called via eventProcessor?
diff --git a/iocore/net/quic/QUICConfig.h b/iocore/net/quic/QUICConfig.h
index 36a7ee4..5b403bb 100644
--- a/iocore/net/quic/QUICConfig.h
+++ b/iocore/net/quic/QUICConfig.h
@@ -69,6 +69,8 @@ public:
   uint32_t cc_minimum_window() const;
   float cc_loss_reduction_factor() const;
 
+  static const uint8_t SCIL = 5;
+
 private:
   static int _connection_table_size;
 
diff --git a/iocore/net/quic/QUICHandshake.cc b/iocore/net/quic/QUICHandshake.cc
index ea1c7fe..7ef84ae 100644
--- a/iocore/net/quic/QUICHandshake.cc
+++ b/iocore/net/quic/QUICHandshake.cc
@@ -141,8 +141,7 @@ QUICHandshake::start(const QUICPacket *initial_packet, 
QUICPacketFactory *packet
         
this->_load_local_server_transport_parameters(initial_packet->version());
         
packet_factory->set_version(this->_version_negotiator->negotiated_version());
       } else {
-        
this->_qc->transmit_packet(packet_factory->create_version_negotiation_packet(initial_packet));
-        QUICHSDebug("Version negotiation failed: %x", 
initial_packet->version());
+        ink_assert(!"Unsupported version initial packet should be droped 
QUICPakcetHandler");
       }
     } else {
       return QUICErrorUPtr(new 
QUICConnectionError(QUICTransErrorCode::PROTOCOL_VIOLATION));
diff --git a/iocore/net/quic/QUICPacket.cc b/iocore/net/quic/QUICPacket.cc
index 247e6cd..9b09c6d 100644
--- a/iocore/net/quic/QUICPacket.cc
+++ b/iocore/net/quic/QUICPacket.cc
@@ -21,11 +21,14 @@
  *  limitations under the License.
  */
 
+#include "QUICPacket.h"
+
 #include <ts/ink_assert.h>
 #include <ts/Diags.h>
+
 #include "QUICIntUtil.h"
-#include "QUICPacket.h"
 #include "QUICDebugNames.h"
+#include "QUICConfig.h"
 
 static constexpr std::string_view tag  = "quic_packet"sv;
 static constexpr uint64_t aead_tag_len = 16;
@@ -821,7 +824,7 @@ QUICPacketFactory::create(IpEndpoint from, ats_unique_buf 
buf, size_t len, QUICP
 }
 
 QUICPacketUPtr
-QUICPacketFactory::create_version_negotiation_packet(const QUICPacket 
*packet_sent_by_client)
+QUICPacketFactory::create_version_negotiation_packet(QUICConnectionId dcid, 
QUICConnectionId scid)
 {
   size_t len = sizeof(QUICVersion) * countof(QUIC_SUPPORTED_VERSIONS);
   ats_unique_buf versions(reinterpret_cast<uint8_t *>(ats_malloc(len)), 
[](void *p) { ats_free(p); });
@@ -835,8 +838,7 @@ QUICPacketFactory::create_version_negotiation_packet(const 
QUICPacket *packet_se
 
   // VN packet dosen't have packet number field and version field is always 
0x00000000
   QUICPacketHeaderUPtr header =
-    QUICPacketHeader::build(QUICPacketType::VERSION_NEGOTIATION, 
packet_sent_by_client->source_cid(),
-                            packet_sent_by_client->destination_cid(), 0x00, 
0x00, 0x00, std::move(versions), len);
+    QUICPacketHeader::build(QUICPacketType::VERSION_NEGOTIATION, dcid, scid, 
0x00, 0x00, 0x00, std::move(versions), len);
 
   return QUICPacketFactory::_create_unprotected_packet(std::move(header));
 }
diff --git a/iocore/net/quic/QUICPacket.h b/iocore/net/quic/QUICPacket.h
index febd398..f95c9bf 100644
--- a/iocore/net/quic/QUICPacket.h
+++ b/iocore/net/quic/QUICPacket.h
@@ -362,10 +362,12 @@ class QUICPacketFactory
 {
 public:
   static QUICPacketUPtr create_null_packet();
+  static QUICPacketUPtr create_version_negotiation_packet(QUICConnectionId 
dcid, QUICConnectionId scid);
+  static QUICPacketUPtr create_stateless_reset_packet(QUICConnectionId 
connection_id,
+                                                      QUICStatelessResetToken 
stateless_reset_token);
 
   QUICPacketUPtr create(IpEndpoint from, ats_unique_buf buf, size_t len, 
QUICPacketNumber base_packet_number,
                         QUICPacketCreationResult &result);
-  QUICPacketUPtr create_version_negotiation_packet(const QUICPacket 
*packet_sent_by_client);
   QUICPacketUPtr create_initial_packet(QUICConnectionId destination_cid, 
QUICConnectionId source_cid,
                                        QUICPacketNumber base_packet_number, 
ats_unique_buf payload, size_t len);
   QUICPacketUPtr create_retry_packet(QUICConnectionId destination_cid, 
QUICConnectionId source_cid, ats_unique_buf payload,
@@ -375,18 +377,16 @@ public:
                                          bool retransmittable);
   QUICPacketUPtr create_server_protected_packet(QUICConnectionId 
connection_id, QUICPacketNumber base_packet_number,
                                                 ats_unique_buf payload, size_t 
len, bool retransmittable);
-  static QUICPacketUPtr create_stateless_reset_packet(QUICConnectionId 
connection_id,
-                                                      QUICStatelessResetToken 
stateless_reset_token);
   void set_version(QUICVersion negotiated_version);
   void set_hs_protocol(QUICHandshakeProtocol *hs_protocol);
-  void set_dcil(uint8_t len);
+  [[deprecated]] void set_dcil(uint8_t len);
 
 private:
   QUICVersion _version                = QUIC_SUPPORTED_VERSIONS[0];
   QUICHandshakeProtocol *_hs_protocol = nullptr;
   QUICPacketNumberGenerator _packet_number_generator;
-  uint8_t _dcil = 0;
 
   static QUICPacketUPtr _create_unprotected_packet(QUICPacketHeaderUPtr 
header);
   QUICPacketUPtr _create_encrypted_packet(QUICPacketHeaderUPtr header, bool 
retransmittable);
+  [[deprecated]] uint8_t _dcil = 0;
 };
diff --git a/iocore/net/quic/QUICTypes.cc b/iocore/net/quic/QUICTypes.cc
index b84b568..faf3bb6 100644
--- a/iocore/net/quic/QUICTypes.cc
+++ b/iocore/net/quic/QUICTypes.cc
@@ -24,6 +24,7 @@
 #include <algorithm>
 #include "QUICTypes.h"
 #include "QUICIntUtil.h"
+#include "QUICConfig.h"
 
 // TODO: move to somewhere in lib/ts/
 static int
@@ -46,7 +47,6 @@ to_hex_str(char *dst, size_t dst_len, const uint8_t *src, 
size_t src_len)
 }
 
 bool
-#include <algorithm>
 QUICTypeUtil::has_long_header(const uint8_t *buf)
 {
   return (buf[0] & 0x80) != 0;
@@ -337,3 +337,97 @@ QUICConnectionId::hex(char *buf, size_t len) const
 {
   return to_hex_str(buf, len, this->_id, this->_len);
 }
+
+//
+// QUICInvariants
+//
+bool
+QUICInvariants::is_long_header(const uint8_t *buf)
+{
+  return (buf[0] & 0x80) != 0;
+}
+
+bool
+QUICInvariants::is_version_negotiation(QUICVersion v)
+{
+  return v == 0x0;
+}
+
+bool
+QUICInvariants::version(QUICVersion &dst, const uint8_t *buf, uint64_t buf_len)
+{
+  if (!QUICInvariants::is_long_header(buf) || buf_len < 
QUICInvariants::LH_DCIL_OFFSET) {
+    return false;
+  }
+
+  dst = QUICTypeUtil::read_QUICVersion(buf + 
QUICInvariants::LH_VERSION_OFFSET);
+
+  return true;
+}
+
+bool
+QUICInvariants::dcid(QUICConnectionId &dst, const uint8_t *buf, uint64_t 
buf_len)
+{
+  uint8_t dcil       = 0;
+  size_t dcid_offset = 0;
+
+  if (QUICInvariants::is_long_header(buf)) {
+    if (buf_len < QUICInvariants::LH_DCIL_OFFSET) {
+      return false;
+    }
+
+    dcil = buf[QUICInvariants::LH_DCIL_OFFSET] >> 4;
+    if (dcil) {
+      dcil += QUICInvariants::CIL_BASE;
+    } else {
+      dst = QUICConnectionId::ZERO();
+      return true;
+    }
+
+    dcid_offset = QUICInvariants::LH_DCID_OFFSET;
+  } else {
+    // remote dcil is local scil
+    dcil        = QUICConfigParams::SCIL + QUICInvariants::CIL_BASE;
+    dcid_offset = QUICInvariants::SH_DCID_OFFSET;
+  }
+
+  if (dcid_offset + dcil > buf_len) {
+    return false;
+  }
+
+  dst = QUICTypeUtil::read_QUICConnectionId(buf + dcid_offset, dcil);
+
+  return true;
+}
+
+bool
+QUICInvariants::scid(QUICConnectionId &dst, const uint8_t *buf, uint64_t 
buf_len)
+{
+  ink_assert(QUICInvariants::is_long_header(buf));
+
+  if (buf_len < QUICInvariants::LH_DCIL_OFFSET) {
+    return false;
+  }
+
+  uint8_t dcil = buf[QUICInvariants::LH_DCIL_OFFSET] >> 4;
+  if (dcil) {
+    dcil += CIL_BASE;
+  }
+
+  uint8_t scid_offset = QUICInvariants::LH_DCID_OFFSET + dcil;
+  uint8_t scil        = buf[QUICInvariants::LH_DCIL_OFFSET] & 0x0F;
+  if (scil) {
+    scil += CIL_BASE;
+  } else {
+    dst = QUICConnectionId::ZERO();
+    return true;
+  }
+
+  if (scid_offset + scil > buf_len) {
+    return false;
+  }
+
+  dst = QUICTypeUtil::read_QUICConnectionId(buf + scid_offset, scil);
+
+  return true;
+}
diff --git a/iocore/net/quic/QUICTypes.h b/iocore/net/quic/QUICTypes.h
index 54646f8..307a447 100644
--- a/iocore/net/quic/QUICTypes.h
+++ b/iocore/net/quic/QUICTypes.h
@@ -312,10 +312,11 @@ private:
   uint64_t _hash_code = 0;
 };
 
+// TODO: move version independent functions to QUICInvariants
 class QUICTypeUtil
 {
 public:
-  static bool has_long_header(const uint8_t *buf);
+  [[deprecated]] static bool has_long_header(const uint8_t *buf);
   static bool has_connection_id(const uint8_t *buf);
   static bool is_supported_version(QUICVersion version);
   static QUICStreamType detect_stream_type(QUICStreamId id);
@@ -341,3 +342,21 @@ public:
 
 private:
 };
+
+class QUICInvariants
+{
+public:
+  static bool is_long_header(const uint8_t *buf);
+  static bool is_version_negotiation(QUICVersion v);
+  static bool version(QUICVersion &dst, const uint8_t *buf, uint64_t buf_len);
+  static bool dcid(QUICConnectionId &dst, const uint8_t *buf, uint64_t 
buf_len);
+  static bool scid(QUICConnectionId &dst, const uint8_t *buf, uint64_t 
buf_len);
+
+  const static size_t CIL_BASE          = 3;
+  const static size_t LH_VERSION_OFFSET = 1;
+  const static size_t LH_DCIL_OFFSET    = 5;
+  const static size_t LH_DCID_OFFSET    = 6;
+  const static size_t SH_DCID_OFFSET    = 1;
+  const static size_t LH_MIN_LEN        = 6;
+  const static size_t SH_MIN_LEN        = 1;
+};
diff --git a/iocore/net/quic/test/Makefile.am b/iocore/net/quic/test/Makefile.am
index 3634ae5..b28e654 100644
--- a/iocore/net/quic/test/Makefile.am
+++ b/iocore/net/quic/test/Makefile.am
@@ -18,6 +18,7 @@
 
 TESTS = $(check_PROGRAMS)
 check_PROGRAMS = \
+  test_QUICInvariants \
   test_QUICPacket \
   test_QUICPacketFactory \
   test_QUICFrame \
@@ -80,6 +81,22 @@ test_LDADD = \
   @HWLOC_LIBS@
 
 #
+# test_QUICInvariants
+#
+test_QUICInvariants_CPPFLAGS = \
+  $(AM_CPPFLAGS)
+
+test_QUICInvariants_LDFLAGS = \
+  @AM_LDFLAGS@
+
+test_QUICInvariants_SOURCES = \
+  $(catch_main) \
+  test_QUICInvariants.cc
+
+test_QUICInvariants_LDADD = \
+  $(test_LDADD)
+
+#
 # test_QUICPacket
 #
 test_QUICPacket_CPPFLAGS = \
diff --git a/iocore/net/quic/test/test_QUICInvariants.cc 
b/iocore/net/quic/test/test_QUICInvariants.cc
new file mode 100644
index 0000000..4f7ad05
--- /dev/null
+++ b/iocore/net/quic/test/test_QUICInvariants.cc
@@ -0,0 +1,147 @@
+/** @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/QUICTypes.h"
+
+TEST_CASE("Long Header - regular case", "[quic]")
+{
+  const uint8_t buf[] = {
+    0x80,                                           // Long header, Type: NONE
+    0x11, 0x22, 0x33, 0x44,                         // Version
+    0x55,                                           // DCIL/SCIL
+    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection 
ID
+    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID
+  };
+  uint64_t buf_len = sizeof(buf);
+
+  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 expected_dcid(raw_dcid, 8);
+  QUICConnectionId expected_scid(raw_scid, 8);
+
+  QUICVersion version   = 0;
+  QUICConnectionId dcid = QUICConnectionId::ZERO();
+  QUICConnectionId scid = QUICConnectionId::ZERO();
+
+  CHECK(QUICInvariants::version(version, buf, buf_len));
+  CHECK(version == 0x11223344);
+  CHECK(QUICInvariants::dcid(dcid, buf, buf_len));
+  CHECK(dcid == expected_dcid);
+  CHECK(QUICInvariants::scid(scid, buf, buf_len));
+  CHECK(scid == expected_scid);
+}
+
+TEST_CASE("Long Header - error cases", "[quic]")
+{
+  SECTION("version")
+  {
+    const uint8_t buf[] = {
+      0x80, // Long header, Type: NONE
+    };
+    uint64_t buf_len = sizeof(buf);
+
+    QUICVersion version = 0;
+
+    CHECK(QUICInvariants::version(version, buf, buf_len) == false);
+  }
+
+  SECTION("dcid")
+  {
+    const uint8_t buf[] = {
+      0x80,                   // Long header, Type: NONE
+      0x11, 0x22, 0x33, 0x44, // Version
+      0x55,                   // DCIL/SCIL
+      0x01, 0x02, 0x03, 0x04, // Invalid Destination Connection ID
+    };
+    uint64_t buf_len = sizeof(buf);
+
+    const uint8_t raw_dcid[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
0x08};
+    QUICConnectionId expected_dcid(raw_dcid, 8);
+
+    QUICVersion version   = 0;
+    QUICConnectionId dcid = QUICConnectionId::ZERO();
+
+    CHECK(QUICInvariants::version(version, buf, buf_len));
+    CHECK(version == 0x11223344);
+    CHECK(QUICInvariants::dcid(dcid, buf, buf_len) == false);
+  }
+
+  SECTION("scid")
+  {
+    const uint8_t buf[] = {
+      0x80,                                           // Long header, Type: 
NONE
+      0x11, 0x22, 0x33, 0x44,                         // Version
+      0x55,                                           // DCIL/SCIL
+      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination 
Connection ID
+      0x11, 0x12, 0x13, 0x14,                         // Invalid Source 
Connection ID
+    };
+    uint64_t buf_len = sizeof(buf);
+
+    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 expected_dcid(raw_dcid, 8);
+    QUICConnectionId expected_scid(raw_scid, 8);
+
+    QUICVersion version   = 0;
+    QUICConnectionId dcid = QUICConnectionId::ZERO();
+    QUICConnectionId scid = QUICConnectionId::ZERO();
+
+    CHECK(QUICInvariants::version(version, buf, buf_len));
+    CHECK(version == 0x11223344);
+    CHECK(QUICInvariants::dcid(dcid, buf, buf_len));
+    CHECK(dcid == expected_dcid);
+    CHECK(QUICInvariants::scid(scid, buf, buf_len) == false);
+  }
+}
+
+TEST_CASE("Short Header - regular case", "[quic]")
+{
+  const uint8_t buf[] = {
+    0x00,                                           // Long header, Type: NONE
+    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection 
ID
+  };
+  uint64_t buf_len = sizeof(buf);
+
+  const uint8_t raw_dcid[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
+  QUICConnectionId expected_dcid(raw_dcid, 8);
+
+  QUICConnectionId dcid = QUICConnectionId::ZERO();
+
+  CHECK(QUICInvariants::dcid(dcid, buf, buf_len));
+  CHECK(dcid == expected_dcid);
+}
+
+// When ATS change QUICConfigParams::SCIL, this test should be failed
+TEST_CASE("Short Header - error case", "[quic]")
+{
+  const uint8_t buf[] = {
+    0x00,                   // Long header, Type: NONE
+    0x01, 0x02, 0x03, 0x04, // Invalid Destination Connection ID
+  };
+  uint64_t buf_len = sizeof(buf);
+
+  QUICConnectionId dcid = QUICConnectionId::ZERO();
+  CHECK(QUICInvariants::dcid(dcid, buf, buf_len) == false);
+}
diff --git a/iocore/net/quic/test/test_QUICPacketFactory.cc 
b/iocore/net/quic/test/test_QUICPacketFactory.cc
index 0ebc38b..cd3bb50 100644
--- a/iocore/net/quic/test/test_QUICPacketFactory.cc
+++ b/iocore/net/quic/test/test_QUICPacketFactory.cc
@@ -32,32 +32,16 @@ 
TEST_CASE("QUICPacketFactory_Create_VersionNegotiationPacket", "[quic]")
   MockQUICHandshakeProtocol hs_protocol;
   factory.set_hs_protocol(&hs_protocol);
 
-  uint8_t initial_packet_header[] = {
-    0xFF,                                           // Type
-    0xaa, 0xbb, 0xcc, 0xdd,                         // Version
-    0x55,                                           // DCIL/SCIL
-    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection 
id
-    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection id
-    0x01,                                           // Payload Length
-    0x00, 0x00, 0x00, 0x00,                         // Packet number
-  };
-  uint8_t initial_packet_payload[] = {
-    0x00 // Payload
-  };
-
-  QUICPacketHeaderUPtr header =
-    QUICPacketHeader::load({}, {initial_packet_header, [](void *) {}}, 
sizeof(initial_packet_header), 0, 8);
-
-  QUICPacket initial_packet(std::move(header), 
ats_unique_buf(initial_packet_payload, [](void *) {}),
-                            sizeof(initial_packet_payload), 0);
+  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 vn_packet = 
factory.create_version_negotiation_packet(&initial_packet);
+  QUICPacketUPtr vn_packet = factory.create_version_negotiation_packet(scid, 
dcid);
   CHECK(vn_packet->type() == QUICPacketType::VERSION_NEGOTIATION);
 
-  uint8_t dst_cid[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
-  uint8_t src_cid[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
-  CHECK((vn_packet->source_cid() == QUICConnectionId(dst_cid, 
sizeof(dst_cid))));
-  CHECK((vn_packet->destination_cid() == QUICConnectionId(src_cid, 
sizeof(src_cid))));
+  CHECK(vn_packet->destination_cid() == scid);
+  CHECK(vn_packet->source_cid() == dcid);
   CHECK(vn_packet->version() == 0x00);
 
   QUICVersion supported_version = 
QUICTypeUtil::read_QUICVersion(vn_packet->payload());
diff --git a/iocore/net/quic/test/test_QUICVersionNegotiator.cc 
b/iocore/net/quic/test/test_QUICVersionNegotiator.cc
index 07dcdd7..78142b6 100644
--- a/iocore/net/quic/test/test_QUICVersionNegotiator.cc
+++ b/iocore/net/quic/test/test_QUICVersionNegotiator.cc
@@ -121,7 +121,8 @@ TEST_CASE("QUICVersionNegotiator - Client Side", "[quic]")
     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());
+    QUICPacketUPtr vn_packet =
+      
packet_factory.create_version_negotiation_packet(initial_packet->source_cid(), 
initial_packet->destination_cid());
 
     // Negotiate version
     vn.negotiate(vn_packet.get());

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to