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/18 05:21:53 UTC

[trafficserver] branch quic-latest updated: draft-08: Support new PING/PONG 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


The following commit(s) were added to refs/heads/quic-latest by this push:
     new 72056a6  draft-08: Support new PING/PONG frame format
72056a6 is described below

commit 72056a67d53bf232ae56391f6ca75d9c8d080c8c
Author: Masaori Koshiba <ma...@apache.org>
AuthorDate: Mon Dec 18 14:21:39 2017 +0900

    draft-08: Support new PING/PONG frame format
---
 iocore/net/quic/QUICDebugNames.cc      |   2 +
 iocore/net/quic/QUICFrame.cc           |  96 ++++++++++++++++++++++++++-
 iocore/net/quic/QUICFrame.h            |  45 +++++++++++++
 iocore/net/quic/test/test_QUICFrame.cc | 114 +++++++++++++++++++++++++++++----
 4 files changed, 242 insertions(+), 15 deletions(-)

diff --git a/iocore/net/quic/QUICDebugNames.cc b/iocore/net/quic/QUICDebugNames.cc
index e08a910..a96bf39 100644
--- a/iocore/net/quic/QUICDebugNames.cc
+++ b/iocore/net/quic/QUICDebugNames.cc
@@ -78,6 +78,8 @@ QUICDebugNames::frame_type(QUICFrameType type)
     return "ACK";
   case QUICFrameType::STREAM:
     return "STREAM";
+  case QUICFrameType::PONG:
+    return "PONG";
   case QUICFrameType::UNKNOWN:
   default:
     return "UNKNOWN";
diff --git a/iocore/net/quic/QUICFrame.cc b/iocore/net/quic/QUICFrame.cc
index 6160b26..93d894c 100644
--- a/iocore/net/quic/QUICFrame.cc
+++ b/iocore/net/quic/QUICFrame.cc
@@ -39,6 +39,7 @@ ClassAllocator<QUICStreamBlockedFrame> quicStreamBlockedFrameAllocator("quicStre
 ClassAllocator<QUICStreamIdBlockedFrame> quicStreamIdBlockedFrameAllocator("quicStreamIdBlockedFrameAllocator");
 ClassAllocator<QUICNewConnectionIdFrame> quicNewConnectionIdFrameAllocator("quicNewConnectionIdFrameAllocator");
 ClassAllocator<QUICStopSendingFrame> quicStopSendingFrameAllocator("quicStopSendingFrameAllocator");
+ClassAllocator<QUICPongFrame> quicPongFrameAllocator("quicPongFrameAllocator");
 ClassAllocator<QUICRetransmissionFrame> quicRetransmissionFrameAllocator("quicRetransmissionFrameAllocator");
 
 QUICFrameType
@@ -795,21 +796,50 @@ QUICPingFrame::type() const
 size_t
 QUICPingFrame::size() const
 {
-  return 1;
+  return this->_data_offset() + this->data_length();
 }
 
 void
 QUICPingFrame::store(uint8_t *buf, size_t *len) const
 {
+  *len = this->size();
+
   if (this->_buf) {
-    *len = this->size();
     memcpy(buf, this->_buf, *len);
   } else {
     buf[0] = static_cast<uint8_t>(QUICFrameType::PING);
-    *len   = 1;
+    buf[1] = this->data_length();
+
+    memcpy(buf + this->_data_offset(), this->data(), this->data_length());
+  }
+}
+
+const uint8_t *
+QUICPingFrame::data() const
+{
+  if (this->_buf) {
+    return this->_buf + this->_data_offset();
+  } else {
+    return this->_data.get();
   }
 }
 
+uint8_t
+QUICPingFrame::data_length() const
+{
+  if (this->_buf) {
+    return QUICTypeUtil::read_nbytes_as_uint(this->_buf + sizeof(QUICFrameType), 1);
+  } else {
+    return this->_data_len;
+  }
+}
+
+const size_t
+QUICPingFrame::_data_offset() const
+{
+  return sizeof(QUICFrameType) + sizeof(this->_data_len);
+}
+
 //
 // PADDING frame
 //
@@ -1592,6 +1622,62 @@ QUICStopSendingFrame::_get_error_code_field_offset() const
 }
 
 //
+// PONG frame
+//
+QUICFrameType
+QUICPongFrame::type() const
+{
+  return QUICFrameType::PONG;
+}
+
+size_t
+QUICPongFrame::size() const
+{
+  return this->_data_offset() + this->data_length();
+}
+
+void
+QUICPongFrame::store(uint8_t *buf, size_t *len) const
+{
+  *len = this->size();
+
+  if (this->_buf) {
+    memcpy(buf, this->_buf, *len);
+  } else {
+    buf[0] = static_cast<uint8_t>(QUICFrameType::PONG);
+    buf[1] = this->data_length();
+
+    memcpy(buf + this->_data_offset(), this->data(), this->data_length());
+  }
+}
+
+const uint8_t *
+QUICPongFrame::data() const
+{
+  if (this->_buf) {
+    return this->_buf + this->_data_offset();
+  } else {
+    return this->_data.get();
+  }
+}
+
+uint8_t
+QUICPongFrame::data_length() const
+{
+  if (this->_buf) {
+    return QUICTypeUtil::read_nbytes_as_uint(this->_buf + sizeof(QUICFrameType), 1);
+  } else {
+    return this->_data_len;
+  }
+}
+
+const size_t
+QUICPongFrame::_data_offset() const
+{
+  return sizeof(QUICFrameType) + sizeof(this->_data_len);
+}
+
+//
 // QUICRetransmissionFrame
 //
 QUICRetransmissionFrame::QUICRetransmissionFrame(QUICFrameUPtr original_frame, const QUICPacket &original_packet)
@@ -1705,6 +1791,10 @@ QUICFrameFactory::create(const uint8_t *buf, size_t len)
     frame = quicStopSendingFrameAllocator.alloc();
     new (frame) QUICStopSendingFrame(buf, len);
     return QUICFrameUPtr(frame, &QUICFrameDeleter::delete_stop_sending_frame);
+  case QUICFrameType::PONG:
+    frame = quicPongFrameAllocator.alloc();
+    new (frame) QUICPongFrame(buf, len);
+    return QUICFrameUPtr(frame, &QUICFrameDeleter::delete_pong_frame);
   default:
     // Unknown frame
     Debug("quic_frame_factory", "Unknown frame type %x", buf[0]);
diff --git a/iocore/net/quic/QUICFrame.h b/iocore/net/quic/QUICFrame.h
index 74e03a8..df5bf75 100644
--- a/iocore/net/quic/QUICFrame.h
+++ b/iocore/net/quic/QUICFrame.h
@@ -59,9 +59,11 @@ public:
   QUICStreamFrame() : QUICFrame() {}
   QUICStreamFrame(const uint8_t *buf, size_t len) : QUICFrame(buf, len) {}
   QUICStreamFrame(ats_unique_buf buf, size_t len, QUICStreamId streamid, QUICOffset offset, bool last = false);
+
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
   virtual void store(uint8_t *buf, size_t *len) const override;
+
   void store(uint8_t *buf, size_t *len, bool include_length_field) const;
   QUICStreamId stream_id() const;
   QUICOffset offset() const;
@@ -229,9 +231,20 @@ class QUICPingFrame : public QUICFrame
 public:
   QUICPingFrame() : QUICFrame() {}
   QUICPingFrame(const uint8_t *buf, size_t len) : QUICFrame(buf, len) {}
+  QUICPingFrame(ats_unique_buf data, size_t data_len) : _data(std::move(data)), _data_len(data_len) {}
+
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
   virtual void store(uint8_t *buf, size_t *len) const override;
+
+  const uint8_t *data() const;
+  uint8_t data_length() const;
+
+private:
+  const size_t _data_offset() const;
+
+  ats_unique_buf _data = {nullptr, [](void *p) { ats_free(p); }};
+  uint8_t _data_len    = 0;
 };
 
 // PADDING
@@ -499,6 +512,31 @@ using QUICFrameUPtr        = std::unique_ptr<QUICFrame, QUICFrameDeleterFunc>;
 using QUICStreamFrameUPtr  = std::unique_ptr<QUICStreamFrame, QUICFrameDeleterFunc>;
 
 //
+// PONG
+//
+
+class QUICPongFrame : public QUICFrame
+{
+public:
+  QUICPongFrame() : QUICFrame() {}
+  QUICPongFrame(const uint8_t *buf, size_t len) : QUICFrame(buf, len) {}
+  QUICPongFrame(ats_unique_buf data, size_t data_len) : _data(std::move(data)), _data_len(data_len) {}
+
+  virtual QUICFrameType type() const override;
+  virtual size_t size() const override;
+  virtual void store(uint8_t *buf, size_t *len) const override;
+
+  const uint8_t *data() const;
+  uint8_t data_length() const;
+
+private:
+  const size_t _data_offset() const;
+
+  ats_unique_buf _data = {nullptr, [](void *p) { ats_free(p); }};
+  uint8_t _data_len    = 0;
+};
+
+//
 // Retransmission Frame
 //
 
@@ -533,6 +571,7 @@ extern ClassAllocator<QUICStreamBlockedFrame> quicStreamBlockedFrameAllocator;
 extern ClassAllocator<QUICStreamIdBlockedFrame> quicStreamIdBlockedFrameAllocator;
 extern ClassAllocator<QUICNewConnectionIdFrame> quicNewConnectionIdFrameAllocator;
 extern ClassAllocator<QUICStopSendingFrame> quicStopSendingFrameAllocator;
+extern ClassAllocator<QUICPongFrame> quicPongFrameAllocator;
 extern ClassAllocator<QUICRetransmissionFrame> quicRetransmissionFrameAllocator;
 
 class QUICFrameDeleter
@@ -637,6 +676,12 @@ public:
   }
 
   static void
+  delete_pong_frame(QUICFrame *frame)
+  {
+    quicPongFrameAllocator.free(static_cast<QUICPongFrame *>(frame));
+  }
+
+  static void
   delete_retransmission_frame(QUICFrame *frame)
   {
     quicRetransmissionFrameAllocator.free(static_cast<QUICRetransmissionFrame *>(frame));
diff --git a/iocore/net/quic/test/test_QUICFrame.cc b/iocore/net/quic/test/test_QUICFrame.cc
index b3aee21..e23dd6a 100644
--- a/iocore/net/quic/test/test_QUICFrame.cc
+++ b/iocore/net/quic/test/test_QUICFrame.cc
@@ -495,27 +495,42 @@ TEST_CASE("Store RST_STREAM Frame", "[quic]")
 
 TEST_CASE("Load Ping Frame", "[quic]")
 {
-  uint8_t buf1[] = {
-    0x07, // Type
+  uint8_t buf[] = {
+    0x07,                                           // Type
+    0x08,                                           // Length
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
   };
-  std::shared_ptr<const QUICFrame> frame1 = QUICFrameFactory::create(buf1, sizeof(buf1));
-  CHECK(frame1->type() == QUICFrameType::PING);
-  CHECK(frame1->size() == 1);
-  std::shared_ptr<const QUICPingFrame> ping_frame = std::dynamic_pointer_cast<const QUICPingFrame>(frame1);
+  std::shared_ptr<const QUICFrame> frame = QUICFrameFactory::create(buf, sizeof(buf));
+  CHECK(frame->type() == QUICFrameType::PING);
+  CHECK(frame->size() == 10);
+
+  std::shared_ptr<const QUICPingFrame> ping_frame = std::dynamic_pointer_cast<const QUICPingFrame>(frame);
   CHECK(ping_frame != nullptr);
+  CHECK(ping_frame->data_length() == 8);
+  CHECK(memcmp(ping_frame->data(), "\x01\x23\x45\x67\x89\xab\xcd\xef", 8) == 0);
 }
 
 TEST_CASE("Store Ping Frame", "[quic]")
 {
-  uint8_t buf[65535];
+  uint8_t buf[16];
   size_t len;
 
   uint8_t expected[] = {
-    0x07, // Type
+    0x07,                                           // Type
+    0x08,                                           // Length
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
   };
-  QUICPingFrame ping_frame;
-  ping_frame.store(buf, &len);
-  CHECK(len == 1);
+
+  uint8_t raw[]       = "\x01\x23\x45\x67\x89\xab\xcd\xef";
+  size_t raw_len      = sizeof(raw) - 1;
+  ats_unique_buf data = ats_unique_malloc(raw_len);
+  memcpy(data.get(), raw, raw_len);
+
+  QUICPingFrame frame(std::move(data), 8);
+  CHECK(frame.size() == 10);
+
+  frame.store(buf, &len);
+  CHECK(len == 10);
   CHECK(memcmp(buf, expected, len) == 0);
 }
 
@@ -974,6 +989,47 @@ TEST_CASE("Store STOP_SENDING Frame", "[quic]")
   CHECK(memcmp(buf, expected, len) == 0);
 }
 
+TEST_CASE("Load Pong Frame", "[quic]")
+{
+  uint8_t buf[] = {
+    0x0d,                                           // Type
+    0x08,                                           // Length
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
+  };
+  std::shared_ptr<const QUICFrame> frame = QUICFrameFactory::create(buf, sizeof(buf));
+  CHECK(frame->type() == QUICFrameType::PONG);
+  CHECK(frame->size() == 10);
+
+  std::shared_ptr<const QUICPongFrame> pong_frame = std::dynamic_pointer_cast<const QUICPongFrame>(frame);
+  CHECK(pong_frame != nullptr);
+  CHECK(pong_frame->data_length() == 8);
+  CHECK(memcmp(pong_frame->data(), "\x01\x23\x45\x67\x89\xab\xcd\xef", 8) == 0);
+}
+
+TEST_CASE("Store Pong Frame", "[quic]")
+{
+  uint8_t buf[16];
+  size_t len;
+
+  uint8_t expected[] = {
+    0x0d,                                           // Type
+    0x08,                                           // Length
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
+  };
+
+  uint8_t raw[]       = "\x01\x23\x45\x67\x89\xab\xcd\xef";
+  size_t raw_len      = sizeof(raw) - 1;
+  ats_unique_buf data = ats_unique_malloc(raw_len);
+  memcpy(data.get(), raw, raw_len);
+
+  QUICPongFrame frame(std::move(data), 8);
+  CHECK(frame.size() == 10);
+
+  frame.store(buf, &len);
+  CHECK(len == 10);
+  CHECK(memcmp(buf, expected, len) == 0);
+}
+
 TEST_CASE("QUICFrameFactory Create Unknown Frame", "[quic]")
 {
   uint8_t buf1[] = {
@@ -1054,6 +1110,7 @@ TEST_CASE("QUICFrameFactory Create RST_STREAM with a QUICStreamError", "[quic]")
   CHECK(rst_stream_frame1->final_offset() == 0);
 }
 
+// Test for retransmittable frames
 TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 {
   QUICPacketFactory factory;
@@ -1198,7 +1255,21 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
 
   SECTION("PING frame")
   {
-    // TODO
+    uint8_t frame_buf[] = {
+      0x07,                                           // Type
+      0x08,                                           // Length
+      0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
+    };
+
+    QUICFrameUPtr frame = QUICFrameFactory::create(frame_buf, sizeof(frame_buf));
+    frame               = QUICFrameFactory::create_retransmission_frame(std::move(frame), *packet);
+
+    uint8_t buf[32] = {0};
+    size_t len;
+    frame->store(buf, &len);
+
+    CHECK(len == 10);
+    CHECK(memcmp(buf, frame_buf, len) == 0);
   }
 
   SECTION("BLOCKED frame")
@@ -1295,4 +1366,23 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
     CHECK(len == 7);
     CHECK(memcmp(buf, frame_buf, len) == 0);
   }
+
+  SECTION("PONG frame")
+  {
+    uint8_t frame_buf[] = {
+      0x0d,                                           // Type
+      0x08,                                           // Length
+      0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
+    };
+
+    QUICFrameUPtr frame = QUICFrameFactory::create(frame_buf, sizeof(frame_buf));
+    frame               = QUICFrameFactory::create_retransmission_frame(std::move(frame), *packet);
+
+    uint8_t buf[32] = {0};
+    size_t len;
+    frame->store(buf, &len);
+
+    CHECK(len == 10);
+    CHECK(memcmp(buf, frame_buf, len) == 0);
+  }
 }

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