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 2018/05/21 01:33:38 UTC

[trafficserver] branch quic-latest updated: [QUIC] Limits the size when store frame into buffer

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 2391a97  [QUIC] Limits the size when store frame into buffer
2391a97 is described below

commit 2391a97e2ffa7f815d71e0e614cb4fd9ee1c8201
Author: scw00 <sc...@apache.org>
AuthorDate: Wed May 16 08:12:32 2018 +0800

    [QUIC] Limits the size when store frame into buffer
---
 iocore/net/QUICNetVConnection.cc       |  20 ++-
 iocore/net/quic/QUICFrame.cc           | 248 +++++++++++++++++++++++++++------
 iocore/net/quic/QUICFrame.h            |  51 ++++---
 iocore/net/quic/test/test_QUICFrame.cc | 115 +++++++++------
 4 files changed, 323 insertions(+), 111 deletions(-)

diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc
index 6d52b54..525f129 100644
--- a/iocore/net/QUICNetVConnection.cc
+++ b/iocore/net/QUICNetVConnection.cc
@@ -1121,12 +1121,26 @@ QUICNetVConnection::_store_frame(ats_unique_buf &buf, size_t &len, bool &retrans
 
   // TODO: check debug build
   char msg[1024];
-  frame->debug_msg(msg, sizeof(msg));
   QUICConDebug("[TX] %s", msg);
 
-  frame->store(buf.get() + len, &l);
-  len += l;
+  ink_assert(max_size > len);
+  size_t n = frame->store(buf.get() + len, &l, max_size - len);
+  if (n > 0) {
+    frame->debug_msg(msg, sizeof(msg));
+    len += l;
+    return;
+  }
+
+  // split frame
+  auto new_frame = QUICFrameFactory::split_frame(frame.get(), max_size - len);
+  frame->debug_msg(msg, sizeof(msg));
+  ink_assert(frame->store(buf.get() + len, &l, max_size - len) > 0);
+  ink_assert(new_frame != nullptr);
 
+  this->_transmit_packet(this->_build_packet(std::move(buf), len, retransmittable, current_packet_type));
+  len = 0;
+  buf = ats_unique_malloc(max_size);
+  this->_store_frame(buf, len, retransmittable, current_packet_type, std::move(new_frame));
   return;
 }
 
diff --git a/iocore/net/quic/QUICFrame.cc b/iocore/net/quic/QUICFrame.cc
index 559d07a..1cc1000 100644
--- a/iocore/net/quic/QUICFrame.cc
+++ b/iocore/net/quic/QUICFrame.cc
@@ -97,6 +97,44 @@ QUICStreamFrame::QUICStreamFrame(ats_unique_buf data, size_t data_len, QUICStrea
   this->_fin       = last;
 }
 
+QUICStreamFrame *
+QUICStreamFrame::split(size_t size)
+{
+  if (size <= this->_get_data_field_offset()) {
+    return nullptr;
+  }
+  bool fin = this->has_fin_flag();
+
+  ink_assert(size < this->size());
+
+  size_t data_len = size - this->_get_data_field_offset();
+  size_t buf2_len = this->data_length() - data_len;
+
+  ats_unique_buf buf  = ats_unique_malloc(data_len);
+  ats_unique_buf buf2 = ats_unique_malloc(buf2_len);
+  memcpy(buf.get(), this->data(), data_len);
+  memcpy(buf2.get(), this->data() + data_len, buf2_len);
+
+  if (this->has_offset_field()) {
+    this->_offset = this->offset();
+  }
+
+  if (this->has_length_field()) {
+    this->_data_len = data_len;
+  }
+
+  this->_fin       = false;
+  this->_data      = std::move(buf);
+  this->_stream_id = this->stream_id();
+
+  this->reset(nullptr, 0);
+
+  QUICStreamFrame *frame = quicStreamFrameAllocator.alloc();
+  new (frame)
+    QUICStreamFrame(std::move(buf2), buf2_len, this->stream_id(), this->offset() + this->data_length(), fin, this->is_protected());
+  return frame;
+}
+
 QUICFrameType
 QUICStreamFrame::type() const
 {
@@ -109,10 +147,10 @@ QUICStreamFrame::size() const
   return this->_get_data_field_offset() + this->data_length();
 }
 
-void
-QUICStreamFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICStreamFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
-  this->store(buf, len, true);
+  return this->store(buf, len, limit, true);
 }
 
 int
@@ -122,9 +160,13 @@ QUICStreamFrame::debug_msg(char *msg, size_t msg_len) const
                   this->stream_id(), this->offset(), this->data_length(), this->has_fin_flag());
 }
 
-void
-QUICStreamFrame::store(uint8_t *buf, size_t *len, bool include_length_field) const
+size_t
+QUICStreamFrame::store(uint8_t *buf, size_t *len, size_t limit, bool include_length_field) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   // Build Frame Type: "0b0010OLF"
   buf[0] = static_cast<uint8_t>(QUICFrameType::STREAM);
   *len   = 1;
@@ -157,6 +199,8 @@ QUICStreamFrame::store(uint8_t *buf, size_t *len, bool include_length_field) con
   // Stream Data (*)
   memcpy(buf + *len, this->data(), this->data_length());
   *len += this->data_length();
+
+  return *len;
 }
 
 QUICStreamId
@@ -373,9 +417,13 @@ QUICAckFrame::size() const
   return this->_get_ack_block_section_offset() + this->_ack_block_section->size();
 }
 
-void
-QUICAckFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICAckFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   uint8_t *p = buf;
   size_t n;
   *p = static_cast<uint8_t>(QUICFrameType::ACK);
@@ -387,12 +435,15 @@ QUICAckFrame::store(uint8_t *buf, size_t *len) const
   p += n;
   QUICIntUtil::write_QUICVariableInt(this->ack_block_count(), p, &n);
   p += n;
-  this->_ack_block_section->store(p, &n);
+
+  ink_assert(limit >= static_cast<size_t>(p - buf));
+  limit -= (p - buf);
+  this->_ack_block_section->store(p, &n, limit);
   p += n;
 
   *len = p - buf;
 
-  return;
+  return *len;
 }
 
 int
@@ -631,9 +682,13 @@ QUICAckFrame::AckBlockSection::size() const
   return n;
 }
 
-void
-QUICAckFrame::AckBlockSection::store(uint8_t *buf, size_t *len) const
+size_t
+QUICAckFrame::AckBlockSection::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   size_t n;
   uint8_t *p = buf;
 
@@ -648,6 +703,8 @@ QUICAckFrame::AckBlockSection::store(uint8_t *buf, size_t *len) const
   }
 
   *len = p - buf;
+
+  return *len;
 }
 
 uint64_t
@@ -783,9 +840,13 @@ QUICRstStreamFrame::size() const
   return 1 + this->_get_stream_id_field_length() + sizeof(QUICAppErrorCode) + this->_get_final_offset_field_length();
 }
 
-void
-QUICRstStreamFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICRstStreamFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -803,6 +864,8 @@ QUICRstStreamFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+
+  return *len;
 }
 
 QUICStreamId
@@ -888,9 +951,13 @@ QUICPingFrame::size() const
   return 1;
 }
 
-void
-QUICPingFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICPingFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   *len = this->size();
 
   if (this->_buf) {
@@ -898,6 +965,8 @@ QUICPingFrame::store(uint8_t *buf, size_t *len) const
   } else {
     buf[0] = static_cast<uint8_t>(QUICFrameType::PING);
   }
+
+  return *len;
 }
 
 //
@@ -915,11 +984,16 @@ QUICPaddingFrame::size() const
   return 1;
 }
 
-void
-QUICPaddingFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICPaddingFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   buf[0] = static_cast<uint8_t>(QUICFrameType::PADDING);
   *len   = 1;
+  return *len;
 }
 
 //
@@ -947,9 +1021,13 @@ QUICConnectionCloseFrame::size() const
          this->reason_phrase_length();
 }
 
-void
-QUICConnectionCloseFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICConnectionCloseFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -969,6 +1047,8 @@ QUICConnectionCloseFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+
+  return *len;
 }
 
 QUICTransErrorCode
@@ -1048,9 +1128,13 @@ QUICApplicationCloseFrame::size() const
          this->reason_phrase_length();
 }
 
-void
-QUICApplicationCloseFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICApplicationCloseFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -1070,6 +1154,8 @@ QUICApplicationCloseFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+
+  return *len;
 }
 
 QUICAppErrorCode
@@ -1144,9 +1230,13 @@ QUICMaxDataFrame::size() const
   return sizeof(QUICFrameType) + this->_get_max_data_field_length();
 }
 
-void
-QUICMaxDataFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICMaxDataFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -1160,6 +1250,8 @@ QUICMaxDataFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+
+  return *len;
 }
 
 uint64_t
@@ -1204,9 +1296,12 @@ QUICMaxStreamDataFrame::size() const
   return sizeof(QUICFrameType) + this->_get_stream_id_field_length() + this->_get_max_stream_data_field_length();
 }
 
-void
-QUICMaxStreamDataFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICMaxStreamDataFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -1222,6 +1317,7 @@ QUICMaxStreamDataFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+  return *len;
 }
 
 QUICStreamId
@@ -1296,9 +1392,13 @@ QUICMaxStreamIdFrame::size() const
   return sizeof(QUICFrameType) + this->_get_max_stream_id_field_length();
 }
 
-void
-QUICMaxStreamIdFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICMaxStreamIdFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -1312,6 +1412,7 @@ QUICMaxStreamIdFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+  return *len;
 }
 
 QUICStreamId
@@ -1349,9 +1450,13 @@ QUICBlockedFrame::size() const
   return sizeof(QUICFrameType) + this->_get_offset_field_length();
 }
 
-void
-QUICBlockedFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICBlockedFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -1366,6 +1471,8 @@ QUICBlockedFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+
+  return *len;
 }
 
 QUICOffset
@@ -1403,9 +1510,13 @@ QUICStreamBlockedFrame::size() const
   return sizeof(QUICFrameType) + this->_get_stream_id_field_length() + this->_get_offset_field_length();
 }
 
-void
-QUICStreamBlockedFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICStreamBlockedFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -1421,6 +1532,8 @@ QUICStreamBlockedFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+
+  return *len;
 }
 
 QUICStreamId
@@ -1484,9 +1597,13 @@ QUICStreamIdBlockedFrame::size() const
   return sizeof(QUICFrameType) + this->_get_stream_id_field_length();
 }
 
-void
-QUICStreamIdBlockedFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICStreamIdBlockedFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -1501,6 +1618,8 @@ QUICStreamIdBlockedFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+
+  return *len;
 }
 
 QUICStreamId
@@ -1539,9 +1658,13 @@ QUICNewConnectionIdFrame::size() const
   return sizeof(QUICFrameType) + this->_get_sequence_field_length() + 1 + this->_get_connection_id_length() + 16;
 }
 
-void
-QUICNewConnectionIdFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICNewConnectionIdFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -1561,6 +1684,8 @@ QUICNewConnectionIdFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+
+  return *len;
 }
 
 uint64_t
@@ -1641,9 +1766,13 @@ QUICStopSendingFrame::size() const
   return sizeof(QUICFrameType) + this->_get_stream_id_field_length() + sizeof(QUICAppErrorCode);
 }
 
-void
-QUICStopSendingFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICStopSendingFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   if (this->_buf) {
     *len = this->size();
     memcpy(buf, this->_buf, *len);
@@ -1659,6 +1788,8 @@ QUICStopSendingFrame::store(uint8_t *buf, size_t *len) const
 
     *len = p - buf;
   }
+
+  return *len;
 }
 
 QUICAppErrorCode
@@ -1712,9 +1843,13 @@ QUICPathChallengeFrame::size() const
   return this->_data_offset() + QUICPathChallengeFrame::DATA_LEN;
 }
 
-void
-QUICPathChallengeFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICPathChallengeFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   *len = this->size();
 
   if (this->_buf) {
@@ -1723,6 +1858,8 @@ QUICPathChallengeFrame::store(uint8_t *buf, size_t *len) const
     buf[0] = static_cast<uint8_t>(QUICFrameType::PATH_CHALLENGE);
     memcpy(buf + this->_data_offset(), this->data(), QUICPathChallengeFrame::DATA_LEN);
   }
+
+  return *len;
 }
 
 const uint8_t *
@@ -1756,9 +1893,13 @@ QUICPathResponseFrame::size() const
   return this->_data_offset() + 8;
 }
 
-void
-QUICPathResponseFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICPathResponseFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   *len = this->size();
 
   if (this->_buf) {
@@ -1767,6 +1908,8 @@ QUICPathResponseFrame::store(uint8_t *buf, size_t *len) const
     buf[0] = static_cast<uint8_t>(QUICFrameType::PATH_RESPONSE);
     memcpy(buf + this->_data_offset(), this->data(), QUICPathResponseFrame::DATA_LEN);
   }
+
+  return *len;
 }
 
 const uint8_t *
@@ -1795,7 +1938,7 @@ QUICRetransmissionFrame::QUICRetransmissionFrame(QUICFrameUPtr original_frame, c
   this->_size = original_frame->size();
   this->_data = ats_unique_malloc(this->_size);
   this->_buf  = this->_data.get();
-  original_frame->store(this->_data.get(), &dummy);
+  original_frame->store(this->_data.get(), &dummy, this->_size);
 }
 
 size_t
@@ -1804,11 +1947,16 @@ QUICRetransmissionFrame::size() const
   return this->_size;
 }
 
-void
-QUICRetransmissionFrame::store(uint8_t *buf, size_t *len) const
+size_t
+QUICRetransmissionFrame::store(uint8_t *buf, size_t *len, size_t limit) const
 {
+  if (limit < this->size()) {
+    return 0;
+  }
+
   memcpy(buf, this->_data.get(), this->_size);
   *len = this->_size;
+  return *len;
 }
 
 QUICPacketType
@@ -1947,6 +2095,18 @@ QUICFrameFactory::create_stream_frame(const uint8_t *data, size_t data_len, QUIC
   return QUICStreamFrameUPtr(frame, &QUICFrameDeleter::delete_stream_frame);
 }
 
+QUICFrameUPtr
+QUICFrameFactory::split_frame(QUICFrame *frame, size_t size)
+{
+  if (frame->type() != QUICFrameType::STREAM) {
+    return QUICFrameFactory::create_null_frame();
+  }
+
+  QUICStreamFrame *old_frame = static_cast<QUICStreamFrame *>(frame);
+  QUICStreamFrame *new_frame = old_frame->split(size);
+  return QUICFrameUPtr(new_frame, &QUICFrameDeleter::delete_stream_frame);
+}
+
 std::unique_ptr<QUICAckFrame, QUICFrameDeleterFunc>
 QUICFrameFactory::create_ack_frame(QUICPacketNumber largest_acknowledged, uint64_t ack_delay, uint64_t first_ack_block,
                                    bool protection)
diff --git a/iocore/net/quic/QUICFrame.h b/iocore/net/quic/QUICFrame.h
index b946251..94bbadb 100644
--- a/iocore/net/quic/QUICFrame.h
+++ b/iocore/net/quic/QUICFrame.h
@@ -40,8 +40,8 @@ public:
   static QUICFrameType type(const uint8_t *buf);
 
   virtual QUICFrameType type() const;
-  virtual size_t size() const                         = 0;
-  virtual void store(uint8_t *buf, size_t *len) const = 0;
+  virtual size_t size() const                                         = 0;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const = 0;
   virtual void reset(const uint8_t *buf, size_t len);
   virtual bool is_protected() const;
   virtual int debug_msg(char *msg, size_t msg_len) const;
@@ -66,12 +66,13 @@ public:
   QUICStreamFrame(ats_unique_buf buf, size_t len, QUICStreamId streamid, QUICOffset offset, bool last = false,
                   bool protection = true);
 
+  QUICStreamFrame *split(size_t size);
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
   virtual int debug_msg(char *msg, size_t msg_len) const override;
 
-  void store(uint8_t *buf, size_t *len, bool include_length_field) const;
+  size_t store(uint8_t *buf, size_t *len, size_t limit, bool include_length_field) const;
   QUICStreamId stream_id() const;
   QUICOffset offset() const;
   const uint8_t *data() const;
@@ -172,7 +173,7 @@ public:
     AckBlockSection(const uint8_t *buf, uint8_t ack_block_count) : _buf(buf), _ack_block_count(ack_block_count) {}
     uint8_t count() const;
     size_t size() const;
-    void store(uint8_t *buf, size_t *len) const;
+    size_t store(uint8_t *buf, size_t *len, size_t limit) const;
     uint64_t first_ack_block() const;
     void add_ack_block(const AckBlock block, bool protection = true);
     const_iterator begin() const;
@@ -197,7 +198,7 @@ public:
   virtual void reset(const uint8_t *buf, size_t len) override;
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
   virtual int debug_msg(char *msg, size_t msg_len) const override;
 
   bool is_protected() const override;
@@ -235,7 +236,7 @@ public:
 
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
 
   QUICStreamId stream_id() const;
   QUICAppErrorCode error_code() const;
@@ -265,7 +266,7 @@ public:
   QUICPingFrame(bool protection) : QUICFrame(protection) {}
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
 
 private:
 };
@@ -279,7 +280,7 @@ public:
   QUICPaddingFrame(const uint8_t *buf, size_t len, bool protection = true) : QUICFrame(buf, len, protection) {}
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
 };
 
 //
@@ -295,7 +296,7 @@ public:
                            bool protection = true);
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
   QUICTransErrorCode error_code() const;
   uint64_t reason_phrase_length() const;
   const char *reason_phrase() const;
@@ -323,7 +324,7 @@ public:
                             bool protection = true);
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
   QUICAppErrorCode error_code() const;
   uint64_t reason_phrase_length() const;
   const char *reason_phrase() const;
@@ -350,7 +351,7 @@ public:
   QUICMaxDataFrame(uint64_t maximum_data, bool protection = true);
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
   uint64_t maximum_data() const;
 
 private:
@@ -371,7 +372,7 @@ public:
   QUICMaxStreamDataFrame(QUICStreamId stream_id, uint64_t maximum_stream_data, bool protection = true);
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
   QUICStreamId stream_id() const;
   uint64_t maximum_stream_data() const;
 
@@ -397,7 +398,7 @@ public:
   QUICMaxStreamIdFrame(QUICStreamId maximum_stream_id, bool protection = true);
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
   QUICStreamId maximum_stream_id() const;
 
 private:
@@ -418,7 +419,7 @@ public:
 
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
 
   QUICOffset offset() const;
 
@@ -441,7 +442,7 @@ public:
 
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
 
   QUICStreamId stream_id() const;
   QUICOffset offset() const;
@@ -466,7 +467,7 @@ public:
   QUICStreamIdBlockedFrame(QUICStreamId s, bool protection = true) : QUICFrame(protection), _stream_id(s) {}
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
 
   QUICStreamId stream_id() const;
 
@@ -490,7 +491,7 @@ public:
 
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
 
   uint64_t sequence() const;
   QUICConnectionId connection_id() const;
@@ -519,7 +520,7 @@ public:
 
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
 
   QUICStreamId stream_id() const;
   QUICAppErrorCode error_code() const;
@@ -545,7 +546,7 @@ public:
   QUICPathChallengeFrame(ats_unique_buf data, bool protection = true) : QUICFrame(protection), _data(std::move(data)) {}
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
 
   const uint8_t *data() const;
 
@@ -568,7 +569,7 @@ public:
   QUICPathResponseFrame(ats_unique_buf data, bool protection = true) : QUICFrame(protection), _data(std::move(data)) {}
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
 
   const uint8_t *data() const;
 
@@ -592,7 +593,7 @@ public:
   QUICRetransmissionFrame() : QUICFrame() {}
   QUICRetransmissionFrame(QUICFrameUPtr original_frame, const QUICPacket &original_packet);
   virtual size_t size() const override;
-  virtual void store(uint8_t *buf, size_t *len) const override;
+  virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
   QUICPacketType packet_type() const;
 
 private:
@@ -765,6 +766,12 @@ class QUICFrameFactory
 {
 public:
   /*
+   * Split Stream frame into two frame
+   * Return the new frame
+   */
+  static QUICFrameUPtr split_frame(QUICFrame *frame, size_t size);
+
+  /*
    * This is for an empty QUICFrameUptr.
    * Empty frames are used for variable initialization and return value of frame creation failure
    */
diff --git a/iocore/net/quic/test/test_QUICFrame.cc b/iocore/net/quic/test/test_QUICFrame.cc
index b6d0086..03b8869 100644
--- a/iocore/net/quic/test/test_QUICFrame.cc
+++ b/iocore/net/quic/test/test_QUICFrame.cc
@@ -155,7 +155,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     QUICStreamFrame stream_frame(std::move(payload1), 5, 0x01, 0x00);
     CHECK(stream_frame.size() == 8);
 
-    stream_frame.store(buf, &len);
+    stream_frame.store(buf, &len, 32);
     CHECK(len == 8);
     CHECK(memcmp(buf, expected1, len) == 0);
   }
@@ -178,7 +178,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     QUICStreamFrame stream_frame(std::move(payload2), 5, 0x01, 0x01);
     CHECK(stream_frame.size() == 9);
 
-    stream_frame.store(buf, &len);
+    stream_frame.store(buf, &len, 32);
     CHECK(len == 9);
     CHECK(memcmp(buf, expected2, len) == 0);
   }
@@ -201,7 +201,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     QUICStreamFrame stream_frame(std::move(payload3), 5, 0x01, 0x010000);
     CHECK(stream_frame.size() == 12);
 
-    stream_frame.store(buf, &len);
+    stream_frame.store(buf, &len, 32);
     CHECK(len == 12);
     CHECK(memcmp(buf, expected3, len) == 0);
   }
@@ -224,7 +224,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     QUICStreamFrame stream_frame(std::move(payload4), 5, 0x01, 0x0100000000);
     CHECK(stream_frame.size() == 16);
 
-    stream_frame.store(buf, &len);
+    stream_frame.store(buf, &len, 32);
     CHECK(len == 16);
     CHECK(memcmp(buf, expected4, len) == 0);
   }
@@ -247,7 +247,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     QUICStreamFrame stream_frame(std::move(payload5), 5, 0x0100, 0x0100000000);
     CHECK(stream_frame.size() == 17);
 
-    stream_frame.store(buf, &len);
+    stream_frame.store(buf, &len, 32);
     CHECK(len == 17);
     CHECK(memcmp(buf, expected5, len) == 0);
   }
@@ -270,7 +270,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     QUICStreamFrame stream_frame(std::move(payload6), 5, 0x010000, 0x0100000000);
     CHECK(stream_frame.size() == 19);
 
-    stream_frame.store(buf, &len);
+    stream_frame.store(buf, &len, 32);
     CHECK(len == 19);
     CHECK(memcmp(buf, expected6, len) == 0);
   }
@@ -293,7 +293,7 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     QUICStreamFrame stream_frame(std::move(payload7), 5, 0x01000000, 0x0100000000);
     CHECK(stream_frame.size() == 19);
 
-    stream_frame.store(buf, &len);
+    stream_frame.store(buf, &len, 32);
     CHECK(len == 19);
     CHECK(memcmp(buf, expected7, len) == 0);
   }
@@ -316,10 +316,41 @@ TEST_CASE("Store STREAM Frame", "[quic]")
     QUICStreamFrame stream_frame(std::move(payload), 5, 0x01000000, 0x0100000000, true);
     CHECK(stream_frame.size() == 19);
 
-    stream_frame.store(buf, &len);
+    stream_frame.store(buf, &len, 32);
     CHECK(len == 19);
     CHECK(memcmp(buf, expected, len) == 0);
   }
+
+  SECTION("split stream frame")
+  {
+    size_t len;
+    uint8_t buf1[] = {
+      0x16,                                           // 0b00010OLF (OLF=110)
+      0x01,                                           // Stream ID
+      0xc0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // Offset
+      0x0a,                                           // Data Length
+      0x01, 0x02, 0x03, 0x04, 0x05,                   // Stream Data
+      0x11, 0x22, 0x33, 0x44, 0x55,
+    };
+
+    QUICFrameUPtr frame1 = QUICFrameFactory::create(buf1, sizeof(buf1));
+    CHECK(frame1->type() == QUICFrameType::STREAM);
+    CHECK(frame1->size() == 21);
+    QUICStreamFrame *stream_frame = dynamic_cast<QUICStreamFrame *>(frame1.get());
+    CHECK(stream_frame->offset() == 0x100000000);
+    CHECK(stream_frame->stream_id() == 0x01);
+    CHECK(stream_frame->data_length() == 10);
+    QUICStreamFrame *stream_frame2 = stream_frame->split(16);
+    CHECK(stream_frame->stream_id() == 0x01);
+    CHECK(stream_frame->data_length() == 5);
+    CHECK(memcmp(stream_frame->data(), "\x01\x02\x03\x04\x05", stream_frame->data_length()) == 0);
+    CHECK(stream_frame->offset() == 0x100000000);
+
+    CHECK(stream_frame2->data_length() == 5);
+    CHECK(memcmp(stream_frame2->data(), "\x11\x22\x33\x44\x55", stream_frame2->data_length()) == 0);
+    CHECK(stream_frame2->offset() == 0x100000000 + 5);
+    CHECK(stream_frame2->stream_id() == 0x01);
+  }
 }
 
 TEST_CASE("Load Ack Frame 1", "[quic]")
@@ -422,7 +453,7 @@ TEST_CASE("Store Ack Frame", "[quic]")
     QUICAckFrame ack_frame(0x12, 0x3456, 0);
     CHECK(ack_frame.size() == 6);
 
-    ack_frame.store(buf, &len);
+    ack_frame.store(buf, &len, 32);
     CHECK(len == 6);
     CHECK(memcmp(buf, expected, len) == 0);
   }
@@ -449,7 +480,7 @@ TEST_CASE("Store Ack Frame", "[quic]")
     section->add_ack_block({0x05060708, 0x090a0b0c0d0e0f10});
     CHECK(ack_frame.size() == 21);
 
-    ack_frame.store(buf, &len);
+    ack_frame.store(buf, &len, 32);
     CHECK(len == 21);
     CHECK(memcmp(buf, expected, len) == 0);
   }
@@ -487,7 +518,7 @@ TEST_CASE("Store RST_STREAM Frame", "[quic]")
   QUICRstStreamFrame rst_stream_frame(0x12345678, 0x0001, 0x1122334455667788);
   CHECK(rst_stream_frame.size() == 15);
 
-  rst_stream_frame.store(buf, &len);
+  rst_stream_frame.store(buf, &len, 65535);
   CHECK(len == 15);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -517,7 +548,7 @@ TEST_CASE("Store Ping Frame", "[quic]")
   QUICPingFrame frame(true);
   CHECK(frame.size() == 1);
 
-  frame.store(buf, &len);
+  frame.store(buf, &len, 16);
   CHECK(len == 1);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -543,7 +574,7 @@ TEST_CASE("Store Padding Frame", "[quic]")
     0x00, // Type
   };
   QUICPaddingFrame padding_frame;
-  padding_frame.store(buf, &len);
+  padding_frame.store(buf, &len, 65535);
   CHECK(len == 1);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -605,7 +636,7 @@ TEST_CASE("Store ConnectionClose Frame", "[quic]")
     QUICConnectionCloseFrame connection_close_frame(QUICTransErrorCode::PROTOCOL_VIOLATION, 5, "ABCDE");
     CHECK(connection_close_frame.size() == 9);
 
-    connection_close_frame.store(buf, &len);
+    connection_close_frame.store(buf, &len, 32);
     CHECK(len == 9);
     CHECK(memcmp(buf, expected1, len) == 0);
   }
@@ -621,7 +652,7 @@ TEST_CASE("Store ConnectionClose Frame", "[quic]")
       0x00,       // Reason Phrase Length
     };
     QUICConnectionCloseFrame connection_close_frame(QUICTransErrorCode::PROTOCOL_VIOLATION, 0, nullptr);
-    connection_close_frame.store(buf, &len);
+    connection_close_frame.store(buf, &len, 32);
     CHECK(len == 4);
     CHECK(memcmp(buf, expected2, len) == 0);
   }
@@ -684,7 +715,7 @@ TEST_CASE("Store ApplicationClose Frame", "[quic]")
     QUICApplicationCloseFrame app_close_frame(static_cast<QUICAppErrorCode>(0x01), 5, "ABCDE");
     CHECK(app_close_frame.size() == 9);
 
-    app_close_frame.store(buf, &len);
+    app_close_frame.store(buf, &len, 32);
     CHECK(len == 9);
     CHECK(memcmp(buf, expected1, len) == 0);
   }
@@ -701,7 +732,7 @@ TEST_CASE("Store ApplicationClose Frame", "[quic]")
     QUICApplicationCloseFrame app_close_frame(static_cast<QUICAppErrorCode>(0x01), 0, nullptr);
     CHECK(app_close_frame.size() == 4);
 
-    app_close_frame.store(buf, &len);
+    app_close_frame.store(buf, &len, 32);
     CHECK(len == 4);
     CHECK(memcmp(buf, expected2, len) == 0);
   }
@@ -733,7 +764,7 @@ TEST_CASE("Store MaxData Frame", "[quic]")
   QUICMaxDataFrame max_data_frame(0x1122334455667788);
   CHECK(max_data_frame.size() == 9);
 
-  max_data_frame.store(buf, &len);
+  max_data_frame.store(buf, &len, 65535);
   CHECK(len == 9);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -768,7 +799,7 @@ TEST_CASE("Store MaxStreamData Frame", "[quic]")
   QUICMaxStreamDataFrame max_stream_data_frame(0x01020304, 0x1122334455667788ULL);
   CHECK(max_stream_data_frame.size() == 13);
 
-  max_stream_data_frame.store(buf, &len);
+  max_stream_data_frame.store(buf, &len, 65535);
   CHECK(len == 13);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -799,7 +830,7 @@ TEST_CASE("Store MaxStreamId Frame", "[quic]")
   QUICMaxStreamIdFrame max_stream_id_frame(0x01020304);
   CHECK(max_stream_id_frame.size() == 5);
 
-  max_stream_id_frame.store(buf, &len);
+  max_stream_id_frame.store(buf, &len, 65535);
   CHECK(len == 5);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -830,7 +861,7 @@ TEST_CASE("Store Blocked Frame", "[quic]")
   QUICBlockedFrame blocked_stream_frame(0x07);
   CHECK(blocked_stream_frame.size() == 2);
 
-  blocked_stream_frame.store(buf, &len);
+  blocked_stream_frame.store(buf, &len, 65535);
   CHECK(len == 2);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -865,7 +896,7 @@ TEST_CASE("Store StreamBlocked Frame", "[quic]")
   QUICStreamBlockedFrame stream_blocked_frame(0x01020304, 0x07);
   CHECK(stream_blocked_frame.size() == 6);
 
-  stream_blocked_frame.store(buf, &len);
+  stream_blocked_frame.store(buf, &len, 65535);
   CHECK(len == 6);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -897,7 +928,7 @@ TEST_CASE("Store StreamIdBlocked Frame", "[quic]")
   QUICStreamIdBlockedFrame stream_id_blocked_frame(0x0102);
   CHECK(stream_id_blocked_frame.size() == 3);
 
-  stream_id_blocked_frame.store(buf, &len);
+  stream_id_blocked_frame.store(buf, &len, 65535);
   CHECK(len == 3);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -941,7 +972,7 @@ TEST_CASE("Store NewConnectionId Frame", "[quic]")
                                             {expected + 12});
   CHECK(new_con_id_frame.size() == 28);
 
-  new_con_id_frame.store(buf, &len);
+  new_con_id_frame.store(buf, &len, 32);
   CHECK(len == 28);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -976,7 +1007,7 @@ TEST_CASE("Store STOP_SENDING Frame", "[quic]")
   QUICStopSendingFrame stop_sending_frame(0x12345678, static_cast<QUICAppErrorCode>(0x01));
   CHECK(stop_sending_frame.size() == 7);
 
-  stop_sending_frame.store(buf, &len);
+  stop_sending_frame.store(buf, &len, 65535);
   CHECK(len == 7);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -1015,7 +1046,7 @@ TEST_CASE("Store PATH_CHALLENGE Frame", "[quic]")
   QUICPathChallengeFrame frame(std::move(data), QUICPathChallengeFrame::DATA_LEN);
   CHECK(frame.size() == 9);
 
-  frame.store(buf, &len);
+  frame.store(buf, &len, 16);
   CHECK(len == 9);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -1053,7 +1084,7 @@ TEST_CASE("Store PATH_RESPONSE Frame", "[quic]")
   QUICPathResponseFrame frame(std::move(data), QUICPathResponseFrame::DATA_LEN);
   CHECK(frame.size() == 9);
 
-  frame.store(buf, &len);
+  frame.store(buf, &len, 16);
   CHECK(len == 9);
   CHECK(memcmp(buf, expected, len) == 0);
 }
@@ -1160,7 +1191,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 8);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1180,7 +1211,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 15);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1200,7 +1231,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 9);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1220,7 +1251,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 9);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1238,7 +1269,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 9);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1257,7 +1288,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 13);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1275,7 +1306,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 5);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1292,7 +1323,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 1);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1310,7 +1341,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 2);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1329,7 +1360,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 6);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1347,7 +1378,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 3);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1369,7 +1400,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 28);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1388,7 +1419,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 7);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1406,7 +1437,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 9);
     CHECK(memcmp(buf, frame_buf, len) == 0);
@@ -1424,7 +1455,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
     uint8_t buf[32] = {0};
     size_t len;
-    frame->store(buf, &len);
+    frame->store(buf, &len, 32);
 
     CHECK(len == 9);
     CHECK(memcmp(buf, frame_buf, len) == 0);

-- 
To stop receiving notification emails like this one, please contact
masaori@apache.org.