You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2017/12/13 23:44:40 UTC

[trafficserver] 08/08: draft-08: Support new STREAM frame format

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 25fc8ab030b5af02283fe120a294eff0b58a4f7b
Author: Masaori Koshiba <ma...@apache.org>
AuthorDate: Wed Dec 13 16:07:35 2017 +0900

    draft-08: Support new STREAM frame format
---
 iocore/net/quic/QUICApplication.cc     |   2 +-
 iocore/net/quic/QUICEchoApp.cc         |   2 +-
 iocore/net/quic/QUICFrame.cc           | 208 ++++++++++++++---------
 iocore/net/quic/QUICFrame.h            |  20 ++-
 iocore/net/quic/QUICStream.cc          |   4 +-
 iocore/net/quic/QUICStreamManager.cc   |   5 +-
 iocore/net/quic/test/test_QUICFrame.cc | 302 ++++++++++++++++++---------------
 7 files changed, 309 insertions(+), 234 deletions(-)

diff --git a/iocore/net/quic/QUICApplication.cc b/iocore/net/quic/QUICApplication.cc
index 83559e6..ef26055 100644
--- a/iocore/net/quic/QUICApplication.cc
+++ b/iocore/net/quic/QUICApplication.cc
@@ -154,7 +154,7 @@ QUICApplication::reenable(QUICStream *stream)
     stream_io->read_reenable();
     stream_io->write_reenable();
   } else {
-    Debug(tag, "Unknown Stream, id: %d", stream->id());
+    Debug(tag, "Unknown Stream, id: %" PRIx64, stream->id());
   }
 
   return;
diff --git a/iocore/net/quic/QUICEchoApp.cc b/iocore/net/quic/QUICEchoApp.cc
index 5fcc4c6..6451dc7 100644
--- a/iocore/net/quic/QUICEchoApp.cc
+++ b/iocore/net/quic/QUICEchoApp.cc
@@ -41,7 +41,7 @@ QUICEchoApp::main_event_handler(int event, Event *data)
   QUICStream *stream      = reinterpret_cast<QUICStream *>(data->cookie);
   QUICStreamIO *stream_io = this->_find_stream_io(stream->id());
   if (stream_io == nullptr) {
-    Debug(tag, "Unknown Stream, id: %d", stream->id());
+    Debug(tag, "Unknown Stream, id: %" PRIx64, stream->id());
     return -1;
   }
 
diff --git a/iocore/net/quic/QUICFrame.cc b/iocore/net/quic/QUICFrame.cc
index 8b2f8ca..db04cb6 100644
--- a/iocore/net/quic/QUICFrame.cc
+++ b/iocore/net/quic/QUICFrame.cc
@@ -90,11 +90,7 @@ QUICStreamFrame::type() const
 size_t
 QUICStreamFrame::size() const
 {
-  if (this->_buf) {
-    return this->_get_data_offset() + this->data_length();
-  } else {
-    return 1 + 4 + 8 + 2 + this->data_length();
-  }
+  return this->_get_data_field_offset() + this->data_length();
 }
 
 void
@@ -106,53 +102,41 @@ QUICStreamFrame::store(uint8_t *buf, size_t *len) const
 void
 QUICStreamFrame::store(uint8_t *buf, size_t *len, bool include_length_field) const
 {
-  size_t n;
-  // Build Frame Type: "11FSSOOD"
+  // Build Frame Type: "0b0010OLF"
   buf[0] = static_cast<uint8_t>(QUICFrameType::STREAM);
   *len   = 1;
 
-  // "F" of "11FSSOOD"
-  if (this->has_fin_flag()) {
-    buf[0] += (0x01 << 5);
-  }
+  // Stream ID (i)
+  size_t stream_id_field_len;
 
-  // "SS" of "11FSSOOD"
-  uint8_t stream_id_width = 0;
-  if (this->_stream_id > 0xFFFFFF) {
-    stream_id_width = 3;
-  } else if (this->_stream_id > 0xFFFF) {
-    stream_id_width = 2;
-  } else if (this->_stream_id > 0xFF) {
-    stream_id_width = 1;
-  } else {
-    stream_id_width = 0;
-  }
-  buf[0] += (stream_id_width << 3);
-  QUICTypeUtil::write_QUICStreamId(this->stream_id(), stream_id_width + 1, buf + *len, &n);
-  *len += n;
-
-  // "OO" of "11FSSOOD"
-  uint8_t offset_width = 0;
-  if (this->offset() > 0xFFFFFFFF) {
-    offset_width = 3;
-  } else if (this->offset() > 0xFFFF) {
-    offset_width = 2;
-  } else if (this->offset() > 0x00) {
-    offset_width = 1;
-  } else {
-    offset_width = 0;
+  // FIXME: check length of buf
+  QUICVariableInt::encode(buf + *len, 8, stream_id_field_len, this->_stream_id);
+  *len += stream_id_field_len;
+
+  // [Offset (i)] "O" of "0b0010OLF"
+  if (this->has_offset_field()) {
+    size_t offset_field_len;
+    // FIXME: check length of buf
+    QUICVariableInt::encode(buf + *len, 8, offset_field_len, this->_offset);
+    *len += offset_field_len;
+    buf[0] += 0x04;
   }
-  buf[0] += (offset_width << 1);
-  QUICTypeUtil::write_QUICOffset(this->offset(), offset_width ? 1 << offset_width : 0, buf + *len, &n);
-  *len += n;
 
-  // "D" of "11FSSOOD"
+  // [Length (i)] "L of "0b0010OLF"
   if (include_length_field) {
+    size_t length_field_len;
+    // FIXME: check length of buf
+    QUICVariableInt::encode(buf + *len, 8, length_field_len, this->_data_len);
+    *len += length_field_len;
+    buf[0] += 0x02;
+  }
+
+  // "F" of "0b0010OLF"
+  if (this->has_fin_flag()) {
     buf[0] += 0x01;
-    QUICTypeUtil::write_uint_as_nbytes(this->data_length(), 2, buf + *len, &n);
-    *len += n;
   }
 
+  // Stream Data (*)
   memcpy(buf + *len, this->data(), this->data_length());
   *len += this->data_length();
 }
@@ -161,7 +145,11 @@ QUICStreamId
 QUICStreamFrame::stream_id() const
 {
   if (this->_buf) {
-    return QUICTypeUtil::read_QUICStreamId(this->_buf + this->_get_stream_id_offset(), this->_get_stream_id_len());
+    uint64_t stream_id;
+    size_t encoded_len;
+    QUICVariableInt::decode(stream_id, encoded_len, this->_buf + this->_get_stream_id_field_offset(),
+                            this->_len - this->_get_stream_id_field_offset());
+    return static_cast<QUICStreamId>(stream_id);
   } else {
     return this->_stream_id;
   }
@@ -171,106 +159,160 @@ QUICOffset
 QUICStreamFrame::offset() const
 {
   if (this->_buf) {
-    return QUICTypeUtil::read_QUICOffset(this->_buf + this->_get_offset_offset(), this->_get_offset_len());
+    if (this->has_offset_field()) {
+      uint64_t offset;
+      size_t encoded_len;
+      QUICVariableInt::decode(offset, encoded_len, this->_buf + this->_get_stream_id_field_offset(),
+                              this->_len - this->_get_stream_id_field_offset());
+      return static_cast<QUICOffset>(offset);
+    } else {
+      return 0;
+    }
   } else {
     return this->_offset;
   }
 }
 
+uint64_t
+QUICStreamFrame::data_length() const
+{
+  if (this->_buf) {
+    if (this->has_length_field()) {
+      uint64_t data_len;
+      size_t encoded_len;
+      QUICVariableInt::decode(data_len, encoded_len, this->_buf + this->_get_length_field_offset(),
+                              this->_len - this->_get_length_field_offset());
+      return data_len;
+    } else {
+      return this->_len - this->_get_data_field_offset();
+    }
+  } else {
+    return this->_data_len;
+  }
+}
+
 const uint8_t *
 QUICStreamFrame::data() const
 {
   if (this->_buf) {
-    return this->_buf + this->_get_data_offset();
+    return this->_buf + this->_get_data_field_offset();
   } else {
     return this->_data.get();
   }
 }
 
-size_t
-QUICStreamFrame::data_length() const
+/**
+ * "O" of "0b00010OLF"
+ */
+bool
+QUICStreamFrame::has_offset_field() const
 {
   if (this->_buf) {
-    if (this->has_data_length_field()) {
-      return QUICTypeUtil::read_nbytes_as_uint(this->_buf + this->_get_offset_offset() + this->_get_offset_len(), 2);
-    } else {
-      return this->_len - this->_get_data_offset();
-    }
+    return (this->_buf[0] & 0x40) != 0;
   } else {
-    return this->_data_len;
+    return this->_offset != 0;
   }
 }
 
 /**
- * "D" of "11FSSOOD"
+ * "L" of "0b00010OLF"
  */
 bool
-QUICStreamFrame::has_data_length_field() const
+QUICStreamFrame::has_length_field() const
 {
-  return (this->_buf[0] & 0x01) != 0;
+  if (this->_buf) {
+    return (this->_buf[0] & 0x02) != 0;
+  } else {
+    // This depends on `include_length_field` arg of QUICStreamFrame::store.
+    // Returning true for just in case.
+    return true;
+  }
 }
 
 /**
- * "F" of "11FSSOOD"
+ * "F" of "0b00010OLF"
  */
 bool
 QUICStreamFrame::has_fin_flag() const
 {
   if (this->_buf) {
-    return (this->_buf[0] & 0x20) != 0;
+    return (this->_buf[0] & 0x01) != 0;
   } else {
     return this->_fin;
   }
 }
 
 size_t
-QUICStreamFrame::_get_stream_id_offset() const
+QUICStreamFrame::_get_stream_id_field_offset() const
 {
   return 1;
 }
 
 size_t
-QUICStreamFrame::_get_offset_offset() const
+QUICStreamFrame::_get_offset_field_offset() const
+{
+  size_t offset_field_offset = this->_get_stream_id_field_offset();
+  offset_field_offset += this->_get_stream_id_field_len();
+
+  return offset_field_offset;
+}
+
+size_t
+QUICStreamFrame::_get_length_field_offset() const
+{
+  size_t length_field_offset = this->_get_stream_id_field_offset();
+  length_field_offset += this->_get_stream_id_field_len();
+  length_field_offset += this->_get_offset_field_len();
+
+  return length_field_offset;
+}
+
+size_t
+QUICStreamFrame::_get_data_field_offset() const
 {
-  return this->_get_stream_id_offset() + this->_get_stream_id_len();
+  size_t data_field_offset = this->_get_stream_id_field_offset();
+  data_field_offset += this->_get_stream_id_field_len();
+  data_field_offset += this->_get_offset_field_len();
+  data_field_offset += this->_get_length_field_len();
+
+  return data_field_offset;
 }
 
 size_t
-QUICStreamFrame::_get_data_offset() const
+QUICStreamFrame::_get_stream_id_field_len() const
 {
   if (this->_buf) {
-    if (this->has_data_length_field()) {
-      return this->_get_offset_offset() + this->_get_offset_len() + 2;
-    } else {
-      return this->_get_offset_offset() + this->_get_offset_len();
-    }
+    return QUICVariableInt::size(this->_buf + this->_get_stream_id_field_offset());
   } else {
-    return 0;
+    return QUICVariableInt::size(this->_stream_id);
   }
 }
 
-/**
- * "SS" of "11FSSOOD"
- * The value 00, 01, 02, and 03 indicate lengths of 8, 16, 24, and 32 bits long respectively.
- */
 size_t
-QUICStreamFrame::_get_stream_id_len() const
+QUICStreamFrame::_get_offset_field_len() const
 {
-  return ((this->_buf[0] & 0x18) >> 3) + 1;
+  if (this->_buf) {
+    if (this->has_offset_field()) {
+      return QUICVariableInt::size(this->_buf + this->_get_offset_field_offset());
+    } else {
+      return 0;
+    }
+  } else {
+    return QUICVariableInt::size(this->_offset);
+  }
 }
 
-/**
- * "OO" of "11FSSOOD"
- * The values 00, 01, 02, and 03 indicate lengths of 0, 16, 32, and 64 bits long respectively.
- */
 size_t
-QUICStreamFrame::_get_offset_len() const
+QUICStreamFrame::_get_length_field_len() const
 {
-  int OO_bits = (this->_buf[0] & 0x06) >> 1;
-  if (OO_bits == 0) {
-    return 0;
+  if (this->_buf) {
+    if (this->has_length_field()) {
+      return QUICVariableInt::size(this->_buf + this->_get_length_field_offset());
+    } else {
+      return 0;
+    }
   } else {
-    return 0x01 << OO_bits;
+    return QUICVariableInt::size(this->_data_len);
   }
 }
 
diff --git a/iocore/net/quic/QUICFrame.h b/iocore/net/quic/QUICFrame.h
index 59fd66d..a4d3b07 100644
--- a/iocore/net/quic/QUICFrame.h
+++ b/iocore/net/quic/QUICFrame.h
@@ -36,7 +36,7 @@ class QUICFrame
 public:
   QUICFrame(const uint8_t *buf, size_t len) : _buf(buf), _len(len){};
   virtual QUICFrameType type() const;
-  virtual size_t size() const = 0;
+  virtual size_t size() const                         = 0;
   virtual void store(uint8_t *buf, size_t *len) const = 0;
   virtual void reset(const uint8_t *buf, size_t len);
   static QUICFrameType type(const uint8_t *buf);
@@ -66,8 +66,9 @@ public:
   QUICStreamId stream_id() const;
   QUICOffset offset() const;
   const uint8_t *data() const;
-  size_t data_length() const;
-  bool has_data_length_field() const;
+  uint64_t data_length() const;
+  bool has_offset_field() const;
+  bool has_length_field() const;
   bool has_fin_flag() const;
 
   LINK(QUICStreamFrame, link);
@@ -78,11 +79,14 @@ private:
   QUICStreamId _stream_id = 0;
   QUICOffset _offset      = 0;
   bool _fin               = false;
-  size_t _get_data_offset() const;
-  size_t _get_stream_id_offset() const;
-  size_t _get_offset_offset() const;
-  size_t _get_stream_id_len() const;
-  size_t _get_offset_len() const;
+  size_t _get_stream_id_field_offset() const;
+  size_t _get_offset_field_offset() const;
+  size_t _get_length_field_offset() const;
+  size_t _get_data_field_offset() const;
+
+  size_t _get_stream_id_field_len() const;
+  size_t _get_offset_field_len() const;
+  size_t _get_length_field_len() const;
 };
 
 //
diff --git a/iocore/net/quic/QUICStream.cc b/iocore/net/quic/QUICStream.cc
index 1ca315e..4dafbf1 100644
--- a/iocore/net/quic/QUICStream.cc
+++ b/iocore/net/quic/QUICStream.cc
@@ -29,10 +29,10 @@
 #include "QUICConfig.h"
 
 #define QUICStreamDebug(fmt, ...)                                                                                       \
-  Debug("quic_stream", "[%" PRIx64 "] [%" PRIx32 "] [%s] " fmt, static_cast<uint64_t>(this->_connection_id), this->_id, \
+  Debug("quic_stream", "[%" PRIx64 "] [%" PRIx64 "] [%s] " fmt, static_cast<uint64_t>(this->_connection_id), this->_id, \
         QUICDebugNames::stream_state(this->_state), ##__VA_ARGS__)
 #define QUICStreamFCDebug(fmt, ...)                                                                                        \
-  Debug("quic_flow_ctrl", "[%" PRIx64 "] [%" PRIx32 "] [%s] " fmt, static_cast<uint64_t>(this->_connection_id), this->_id, \
+  Debug("quic_flow_ctrl", "[%" PRIx64 "] [%" PRIx64 "] [%s] " fmt, static_cast<uint64_t>(this->_connection_id), this->_id, \
         QUICDebugNames::stream_state(this->_state), ##__VA_ARGS__)
 
 QUICStream::~QUICStream()
diff --git a/iocore/net/quic/QUICStreamManager.cc b/iocore/net/quic/QUICStreamManager.cc
index f3b3d94..5223bb4 100644
--- a/iocore/net/quic/QUICStreamManager.cc
+++ b/iocore/net/quic/QUICStreamManager.cc
@@ -40,7 +40,10 @@ std::vector<QUICFrameType>
 QUICStreamManager::interests()
 {
   return {
-    QUICFrameType::STREAM, QUICFrameType::RST_STREAM, QUICFrameType::MAX_STREAM_DATA, QUICFrameType::MAX_STREAM_ID,
+    QUICFrameType::STREAM,
+    QUICFrameType::RST_STREAM,
+    QUICFrameType::MAX_STREAM_DATA,
+    QUICFrameType::MAX_STREAM_ID,
   };
 }
 
diff --git a/iocore/net/quic/test/test_QUICFrame.cc b/iocore/net/quic/test/test_QUICFrame.cc
index fc09cd4..5aed7ba 100644
--- a/iocore/net/quic/test/test_QUICFrame.cc
+++ b/iocore/net/quic/test/test_QUICFrame.cc
@@ -54,30 +54,10 @@ TEST_CASE("QUICFrame Type", "[quic]")
   CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\xff")) == QUICFrameType::UNKNOWN);
 }
 
-TEST_CASE("Construct QUICFrame", "[quic]")
-{
-  uint8_t raw[]          = "foo";
-  ats_unique_buf payload = ats_unique_malloc(sizeof(raw));
-  memcpy(payload.get(), raw, sizeof(raw));
-
-  uint8_t buf[65536];
-  size_t len;
-
-  QUICStreamFrame frame1(std::move(payload), sizeof(raw), 0xffcc9966, 0xffddbb9977553311);
-  frame1.store(buf, &len);
-  CHECK(frame1.type() == QUICFrameType::STREAM);
-  CHECK(frame1.size() == 19);
-  CHECK(frame1.stream_id() == 0xffcc9966);
-  CHECK(frame1.offset() == 0xffddbb9977553311);
-  CHECK(frame1.data_length() == 4);
-  CHECK(memcmp(frame1.data(), "foo\0", 4) == 0);
-  CHECK(frame1.has_fin_flag() == false);
-}
-
 TEST_CASE("Load STREAM Frame 1", "[quic]")
 {
   uint8_t buf1[] = {
-    0xC0,                   // 11FSSOOD
+    0x10,                   // 0b00010OLF (OLF=000)
     0x01,                   // Stream ID
     0x01, 0x02, 0x03, 0x04, // Stream Data
   };
@@ -95,14 +75,14 @@ TEST_CASE("Load STREAM Frame 1", "[quic]")
 TEST_CASE("Load STREAM Frame 2", "[quic]")
 {
   uint8_t buf1[] = {
-    0xC1,                         // 11FSSOOD
+    0x12,                         // 0b00010OLF (OLF=010)
     0x01,                         // Stream ID
-    0x00, 0x05,                   // Data Length
+    0x05,                         // Data Length
     0x01, 0x02, 0x03, 0x04, 0x05, // Stream Data
   };
   std::shared_ptr<const QUICFrame> frame1 = QUICFrameFactory::create(buf1, sizeof(buf1));
   CHECK(frame1->type() == QUICFrameType::STREAM);
-  CHECK(frame1->size() == 9);
+  CHECK(frame1->size() == 8);
   std::shared_ptr<const QUICStreamFrame> streamFrame1 = std::dynamic_pointer_cast<const QUICStreamFrame>(frame1);
   CHECK(streamFrame1->stream_id() == 0x01);
   CHECK(streamFrame1->offset() == 0x00);
@@ -113,127 +93,173 @@ TEST_CASE("Load STREAM Frame 2", "[quic]")
 
 TEST_CASE("Store STREAM Frame", "[quic]")
 {
-  uint8_t buf[65535];
-  size_t len;
+  SECTION("8bit stream id, 0bit offset")
+  {
+    uint8_t buf[32] = {0};
+    size_t len;
+    uint8_t expected1[] = {
+      0x12,                         // 0b00010OLF (OLF=010)
+      0x01,                         // Stream ID
+      0x05,                         // Data Length
+      0x01, 0x02, 0x03, 0x04, 0x05, // Stream Data
+    };
 
-  // 8bit stream id, 0bit offset
-  uint8_t expected1[] = {
-    0xC1,                         // 11FSSOOD
-    0x01,                         // Stream ID
-    0x00, 0x05,                   // Data Length
-    0x01, 0x02, 0x03, 0x04, 0x05, // Stream Data
-  };
+    uint8_t raw1[]          = "\x01\x02\x03\x04\x05";
+    ats_unique_buf payload1 = ats_unique_malloc(5);
+    memcpy(payload1.get(), raw1, 5);
 
-  uint8_t raw1[]          = "\x01\x02\x03\x04\x05";
-  ats_unique_buf payload1 = ats_unique_malloc(5);
-  memcpy(payload1.get(), raw1, 5);
+    QUICStreamFrame streamFrame1(std::move(payload1), 5, 0x01, 0x00);
+    streamFrame1.store(buf, &len);
+    CHECK(len == 8);
+    CHECK(memcmp(buf, expected1, len) == 0);
+  }
 
-  QUICStreamFrame streamFrame1(std::move(payload1), 5, 0x01, 0x00);
-  streamFrame1.store(buf, &len);
-  CHECK(len == 9);
-  CHECK(memcmp(buf, expected1, len) == 0);
+  SECTION("8bit stream id, 16bit offset")
+  {
+    uint8_t buf[32] = {0};
+    size_t len;
+    uint8_t expected2[] = {
+      0x16,                         // 0b00010OLF (OLF=110)
+      0x01,                         // Stream ID
+      0x01,                         // Offset
+      0x05,                         // Data Length
+      0x01, 0x02, 0x03, 0x04, 0x05, // Stream Data
+    };
+    uint8_t raw2[]          = "\x01\x02\x03\x04\x05";
+    ats_unique_buf payload2 = ats_unique_malloc(5);
+    memcpy(payload2.get(), raw2, 5);
+
+    QUICStreamFrame streamFrame2(std::move(payload2), 5, 0x01, 0x01);
+    streamFrame2.store(buf, &len);
+    CHECK(len == 9);
+    CHECK(memcmp(buf, expected2, len) == 0);
+  }
 
-  // 8bit stream id, 16bit offset
-  uint8_t expected2[] = {
-    0xC3,                         // 11FSSOOD
-    0x01,                         // Stream ID
-    0x00, 0x01,                   // Offset
-    0x00, 0x05,                   // Data Length
-    0x01, 0x02, 0x03, 0x04, 0x05, // Stream Data
-  };
-  uint8_t raw2[]          = "\x01\x02\x03\x04\x05";
-  ats_unique_buf payload2 = ats_unique_malloc(5);
-  memcpy(payload2.get(), raw2, 5);
+  SECTION("8bit stream id, 32bit offset")
+  {
+    uint8_t buf[32] = {0};
+    size_t len;
+    uint8_t expected3[] = {
+      0x16,                         // 0b00010OLF (OLF=110)
+      0x01,                         // Stream ID
+      0x80, 0x01, 0x00, 0x00,       // Offset
+      0x05,                         // Data Length
+      0x01, 0x02, 0x03, 0x04, 0x05, // Stream Data
+    };
+    uint8_t raw3[]          = "\x01\x02\x03\x04\x05";
+    ats_unique_buf payload3 = ats_unique_malloc(5);
+    memcpy(payload3.get(), raw3, 5);
+
+    QUICStreamFrame streamFrame3(std::move(payload3), 5, 0x01, 0x010000);
+    streamFrame3.store(buf, &len);
+    CHECK(len == 12);
+    CHECK(memcmp(buf, expected3, len) == 0);
+  }
 
-  QUICStreamFrame streamFrame2(std::move(payload2), 5, 0x01, 0x01);
-  streamFrame2.store(buf, &len);
-  CHECK(len == 11);
-  CHECK(memcmp(buf, expected2, len) == 0);
+  SECTION("8bit stream id, 64bit offset")
+  {
+    uint8_t buf[32] = {0};
+    size_t len;
+    uint8_t expected4[] = {
+      0x16,                                           // 0b00010OLF (OLF=110)
+      0x01,                                           // Stream ID
+      0xc0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // Offset
+      0x05,                                           // Data Length
+      0x01, 0x02, 0x03, 0x04, 0x05,                   // Stream Data
+    };
+    uint8_t raw4[]          = "\x01\x02\x03\x04\x05";
+    ats_unique_buf payload4 = ats_unique_malloc(5);
+    memcpy(payload4.get(), raw4, 5);
+
+    QUICStreamFrame streamFrame4(std::move(payload4), 5, 0x01, 0x0100000000);
+    streamFrame4.store(buf, &len);
+    CHECK(len == 16);
+    CHECK(memcmp(buf, expected4, len) == 0);
+  }
 
-  // 8bit stream id, 32bit offset
-  uint8_t expected3[] = {
-    0xC5,                         // 11FSSOOD
-    0x01,                         // Stream ID
-    0x00, 0x01, 0x00, 0x00,       // Offset
-    0x00, 0x05,                   // Data Length
-    0x01, 0x02, 0x03, 0x04, 0x05, // Stream Data
-  };
-  uint8_t raw3[]          = "\x01\x02\x03\x04\x05";
-  ats_unique_buf payload3 = ats_unique_malloc(5);
-  memcpy(payload3.get(), raw3, 5);
+  SECTION("16bit stream id, 64bit offset")
+  {
+    uint8_t buf[32] = {0};
+    size_t len;
+    uint8_t expected5[] = {
+      0x16,                                           // 0b00010OLF (OLF=110)
+      0x41, 0x00,                                     // Stream ID
+      0xc0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // Offset
+      0x05,                                           // Data Length
+      0x01, 0x02, 0x03, 0x04, 0x05,                   // Stream Data
+    };
+    uint8_t raw5[]          = "\x01\x02\x03\x04\x05";
+    ats_unique_buf payload5 = ats_unique_malloc(5);
+    memcpy(payload5.get(), raw5, 5);
+
+    QUICStreamFrame streamFrame5(std::move(payload5), 5, 0x0100, 0x0100000000);
+    streamFrame5.store(buf, &len);
+    CHECK(len == 17);
+    CHECK(memcmp(buf, expected5, len) == 0);
+  }
 
-  QUICStreamFrame streamFrame3(std::move(payload3), 5, 0x01, 0x010000);
-  streamFrame3.store(buf, &len);
-  CHECK(len == 13);
-  CHECK(memcmp(buf, expected3, len) == 0);
-
-  // 8bit stream id, 64bit offset
-  uint8_t expected4[] = {
-    0xC7,                                           // 11FSSOOD
-    0x01,                                           // Stream ID
-    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // Offset
-    0x00, 0x05,                                     // Data Length
-    0x01, 0x02, 0x03, 0x04, 0x05,                   // Stream Data
-  };
-  uint8_t raw4[]          = "\x01\x02\x03\x04\x05";
-  ats_unique_buf payload4 = ats_unique_malloc(5);
-  memcpy(payload4.get(), raw4, 5);
-
-  QUICStreamFrame streamFrame4(std::move(payload4), 5, 0x01, 0x0100000000);
-  streamFrame4.store(buf, &len);
-  CHECK(len == 17);
-  CHECK(memcmp(buf, expected4, len) == 0);
-
-  // 16bit stream id, 64bit offset
-  uint8_t expected5[] = {
-    0xCF,                                           // 11FSSOOD
-    0x01, 0x00,                                     // Stream ID
-    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // Offset
-    0x00, 0x05,                                     // Data Length
-    0x01, 0x02, 0x03, 0x04, 0x05,                   // Stream Data
-  };
-  uint8_t raw5[]          = "\x01\x02\x03\x04\x05";
-  ats_unique_buf payload5 = ats_unique_malloc(5);
-  memcpy(payload5.get(), raw5, 5);
-
-  QUICStreamFrame streamFrame5(std::move(payload5), 5, 0x0100, 0x0100000000);
-  streamFrame5.store(buf, &len);
-  CHECK(len == 18);
-  CHECK(memcmp(buf, expected5, len) == 0);
-
-  // 24bit stream id, 64bit offset
-  uint8_t expected6[] = {
-    0xD7,                                           // 11FSSOOD
-    0x01, 0x00, 0x00,                               // Stream ID
-    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // Offset
-    0x00, 0x05,                                     // Data Length
-    0x01, 0x02, 0x03, 0x04, 0x05,                   // Stream Data
-  };
-  uint8_t raw6[]          = "\x01\x02\x03\x04\x05";
-  ats_unique_buf payload6 = ats_unique_malloc(5);
-  memcpy(payload6.get(), raw6, 5);
-
-  QUICStreamFrame streamFrame6(std::move(payload6), 5, 0x010000, 0x0100000000);
-  streamFrame6.store(buf, &len);
-  CHECK(len == 19);
-  CHECK(memcmp(buf, expected6, len) == 0);
-
-  // 32bit stream id, 64bit offset
-  uint8_t expected7[] = {
-    0xDF,                                           // 11FSSOOD
-    0x01, 0x00, 0x00, 0x00,                         // Stream ID
-    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // Offset
-    0x00, 0x05,                                     // Data Length
-    0x01, 0x02, 0x03, 0x04, 0x05,                   // Stream Data
-  };
-  uint8_t raw7[]          = "\x01\x02\x03\x04\x05";
-  ats_unique_buf payload7 = ats_unique_malloc(5);
-  memcpy(payload7.get(), raw7, 5);
-
-  QUICStreamFrame streamFrame7(std::move(payload7), 5, 0x01000000, 0x0100000000);
-  streamFrame7.store(buf, &len);
-  CHECK(len == 20);
-  CHECK(memcmp(buf, expected7, len) == 0);
+  SECTION("24bit stream id, 64bit offset")
+  {
+    uint8_t buf[32] = {0};
+    size_t len;
+    uint8_t expected6[] = {
+      0x16,                                           // 0b00010OLF (OLF=110)
+      0x80, 0x01, 0x00, 0x00,                         // Stream ID
+      0xc0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // Offset
+      0x05,                                           // Data Length
+      0x01, 0x02, 0x03, 0x04, 0x05,                   // Stream Data
+    };
+    uint8_t raw6[]          = "\x01\x02\x03\x04\x05";
+    ats_unique_buf payload6 = ats_unique_malloc(5);
+    memcpy(payload6.get(), raw6, 5);
+
+    QUICStreamFrame streamFrame6(std::move(payload6), 5, 0x010000, 0x0100000000);
+    streamFrame6.store(buf, &len);
+    CHECK(len == 19);
+    CHECK(memcmp(buf, expected6, len) == 0);
+  }
+
+  SECTION("32bit stream id, 64bit offset")
+  {
+    uint8_t buf[32] = {0};
+    size_t len;
+    uint8_t expected7[] = {
+      0x16,                                           // 0b00010OLF (OLF=110)
+      0x81, 0x00, 0x00, 0x00,                         // Stream ID
+      0xc0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // Offset
+      0x05,                                           // Data Length
+      0x01, 0x02, 0x03, 0x04, 0x05,                   // Stream Data
+    };
+    uint8_t raw7[]          = "\x01\x02\x03\x04\x05";
+    ats_unique_buf payload7 = ats_unique_malloc(5);
+    memcpy(payload7.get(), raw7, 5);
+
+    QUICStreamFrame streamFrame7(std::move(payload7), 5, 0x01000000, 0x0100000000);
+    streamFrame7.store(buf, &len);
+    CHECK(len == 19);
+    CHECK(memcmp(buf, expected7, len) == 0);
+  }
+
+  SECTION("32bit stream id, 64bit offset, FIN bit")
+  {
+    uint8_t buf[32] = {0};
+    size_t len;
+    uint8_t expected[] = {
+      0x17,                                           // 0b00010OLF (OLF=111)
+      0x81, 0x00, 0x00, 0x00,                         // Stream ID
+      0xc0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // Offset
+      0x05,                                           // Data Length
+      0x01, 0x02, 0x03, 0x04, 0x05,                   // Stream Data
+    };
+    uint8_t raw[]          = "\x01\x02\x03\x04\x05";
+    ats_unique_buf payload = ats_unique_malloc(5);
+    memcpy(payload.get(), raw, 5);
+
+    QUICStreamFrame streamFrame(std::move(payload), 5, 0x01000000, 0x0100000000, true);
+    streamFrame.store(buf, &len);
+    CHECK(len == 19);
+    CHECK(memcmp(buf, expected, len) == 0);
+  }
 }
 
 TEST_CASE("Load Ack Frame 1", "[quic]")

-- 
To stop receiving notification emails like this one, please contact
"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>.