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 87526c0 [draft-13] Add NEW_TOKEN frame
87526c0 is described below
commit 87526c0d9889f7660a2a416078f7b902607bd568
Author: Masaori Koshiba <[email protected]>
AuthorDate: Wed Aug 1 10:19:03 2018 +0900
[draft-13] Add NEW_TOKEN frame
---
iocore/net/quic/QUICFrame.cc | 108 +++++++++++++++++++++++++++++++++
iocore/net/quic/QUICFrame.h | 47 +++++++++++++-
iocore/net/quic/QUICTypes.h | 1 +
iocore/net/quic/test/test_QUICFrame.cc | 42 +++++++++++++
4 files changed, 197 insertions(+), 1 deletion(-)
diff --git a/iocore/net/quic/QUICFrame.cc b/iocore/net/quic/QUICFrame.cc
index 25ef619..f0c47bf 100644
--- a/iocore/net/quic/QUICFrame.cc
+++ b/iocore/net/quic/QUICFrame.cc
@@ -44,6 +44,7 @@ ClassAllocator<QUICNewConnectionIdFrame>
quicNewConnectionIdFrameAllocator("quic
ClassAllocator<QUICStopSendingFrame>
quicStopSendingFrameAllocator("quicStopSendingFrameAllocator");
ClassAllocator<QUICPathChallengeFrame>
quicPathChallengeFrameAllocator("quicPathChallengeFrameAllocator");
ClassAllocator<QUICPathResponseFrame>
quicPathResponseFrameAllocator("quicPathResponseFrameAllocator");
+ClassAllocator<QUICNewTokenFrame>
quicNewTokenFrameAllocator("quicNewTokenFrameAllocator");
ClassAllocator<QUICRetransmissionFrame>
quicRetransmissionFrameAllocator("quicRetransmissionFrameAllocator");
QUICFrameType
@@ -2212,6 +2213,101 @@ QUICPathResponseFrame::_data_offset() const
}
//
+// QUICNewTokenFrame
+//
+QUICFrameUPtr
+QUICNewTokenFrame::clone() const
+{
+ return QUICFrameFactory::create_new_token_frame(this->token(),
this->token_length());
+}
+
+QUICFrameType
+QUICNewTokenFrame::type() const
+{
+ return QUICFrameType::NEW_TOKEN;
+}
+
+size_t
+QUICNewTokenFrame::size() const
+{
+ return this->_get_token_field_offset() + this->token_length();
+}
+
+size_t
+QUICNewTokenFrame::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);
+ } else {
+ uint8_t *p = buf;
+
+ // Type (i)
+ *p = static_cast<uint8_t>(QUICFrameType::NEW_TOKEN);
+ ++p;
+
+ // Token Length (i)
+ size_t n;
+ QUICIntUtil::write_QUICVariableInt(this->_token_length, p, &n);
+ p += n;
+
+ // Token (*)
+ memcpy(p, this->token(), this->token_length());
+ p += this->token_length();
+
+ *len = p - buf;
+ }
+
+ return *len;
+}
+
+uint64_t
+QUICNewTokenFrame::token_length() const
+{
+ if (this->_buf) {
+ return QUICIntUtil::read_QUICVariableInt(this->_buf +
this->_get_token_length_field_offset());
+ } else {
+ return this->_token_length;
+ }
+}
+
+const uint8_t *
+QUICNewTokenFrame::token() const
+{
+ if (this->_buf) {
+ return this->_buf + this->_get_token_field_offset();
+ } else {
+ return this->_token.get();
+ }
+}
+
+size_t
+QUICNewTokenFrame::_get_token_length_field_offset() const
+{
+ return sizeof(QUICFrameType);
+}
+
+size_t
+QUICNewTokenFrame::_get_token_length_field_length() const
+{
+ if (this->_buf) {
+ return QUICVariableInt::size(this->_buf + sizeof(QUICFrameType));
+ } else {
+ return QUICVariableInt::size(this->_token_length);
+ }
+}
+
+size_t
+QUICNewTokenFrame::_get_token_field_offset() const
+{
+ return sizeof(QUICFrameType) + this->_get_token_length_field_length();
+}
+
+//
// QUICRetransmissionFrame
//
QUICRetransmissionFrame::QUICRetransmissionFrame(QUICFrameUPtr original_frame,
const QUICPacket &original_packet)
@@ -2361,6 +2457,10 @@ QUICFrameFactory::create(const uint8_t *buf, size_t len)
frame = quicPathResponseFrameAllocator.alloc();
new (frame) QUICPathResponseFrame(buf, len);
return QUICFrameUPtr(frame, &QUICFrameDeleter::delete_path_response_frame);
+ case QUICFrameType::NEW_TOKEN:
+ frame = quicNewTokenFrameAllocator.alloc();
+ new (frame) QUICNewTokenFrame(buf, len);
+ return QUICFrameUPtr(frame, &QUICFrameDeleter::delete_new_token_frame);
default:
// Unknown frame
Debug("quic_frame_factory", "Unknown frame type %x", buf[0]);
@@ -2581,6 +2681,14 @@
QUICFrameFactory::create_new_connection_id_frame(uint32_t sequence, QUICConnecti
return std::unique_ptr<QUICNewConnectionIdFrame,
QUICFrameDeleterFunc>(frame, &QUICFrameDeleter::delete_new_connection_id_frame);
}
+std::unique_ptr<QUICNewTokenFrame, QUICFrameDeleterFunc>
+QUICFrameFactory::create_new_token_frame(const uint8_t *token, uint64_t
token_len)
+{
+ QUICNewTokenFrame *frame = quicNewTokenFrameAllocator.alloc();
+ new (frame) QUICNewTokenFrame(token, token_len);
+ return std::unique_ptr<QUICNewTokenFrame, QUICFrameDeleterFunc>(frame,
&QUICFrameDeleter::delete_new_token_frame);
+}
+
std::unique_ptr<QUICRetransmissionFrame, QUICFrameDeleterFunc>
QUICFrameFactory::create_retransmission_frame(QUICFrameUPtr original_frame,
const QUICPacket &original_packet)
{
diff --git a/iocore/net/quic/QUICFrame.h b/iocore/net/quic/QUICFrame.h
index 05f65cb..1d5598f 100644
--- a/iocore/net/quic/QUICFrame.h
+++ b/iocore/net/quic/QUICFrame.h
@@ -326,7 +326,9 @@ public:
private:
};
+//
// PADDING
+//
class QUICPaddingFrame : public QUICFrame
{
@@ -648,7 +650,37 @@ private:
};
//
-// Retransmission Frame
+// NEW_TOKEN
+//
+
+class QUICNewTokenFrame : public QUICFrame
+{
+public:
+ QUICNewTokenFrame() : QUICFrame() {}
+ QUICNewTokenFrame(const uint8_t *buf, size_t len, bool protection = true) :
QUICFrame(buf, len, protection) {}
+ QUICNewTokenFrame(ats_unique_buf token, size_t token_length, bool protection
= true)
+ : QUICFrame(protection), _token_length(token_length),
_token(std::move(token))
+ {
+ }
+ QUICFrameUPtr clone() const override;
+ virtual QUICFrameType type() const override;
+ virtual size_t size() const override;
+ virtual size_t store(uint8_t *buf, size_t *len, size_t limit) const override;
+
+ uint64_t token_length() const;
+ const uint8_t *token() const;
+
+private:
+ size_t _get_token_length_field_offset() const;
+ size_t _get_token_length_field_length() const;
+ size_t _get_token_field_offset() const;
+
+ uint64_t _token_length = 0;
+ ats_unique_buf _token = {nullptr, [](void *p) { ats_free(p); }};
+};
+
+//
+// Retransmission Frame - Not on the spec
//
class QUICRetransmissionFrame : public QUICFrame
@@ -688,6 +720,7 @@ extern ClassAllocator<QUICNewConnectionIdFrame>
quicNewConnectionIdFrameAllocato
extern ClassAllocator<QUICStopSendingFrame> quicStopSendingFrameAllocator;
extern ClassAllocator<QUICPathChallengeFrame> quicPathChallengeFrameAllocator;
extern ClassAllocator<QUICPathResponseFrame> quicPathResponseFrameAllocator;
+extern ClassAllocator<QUICNewTokenFrame> quicNewTokenFrameAllocator;
extern ClassAllocator<QUICRetransmissionFrame>
quicRetransmissionFrameAllocator;
class QUICFrameDeleter
@@ -827,6 +860,13 @@ public:
}
static void
+ delete_new_token_frame(QUICFrame *frame)
+ {
+ frame->~QUICFrame();
+ quicNewTokenFrameAllocator.free(static_cast<QUICNewTokenFrame *>(frame));
+ }
+
+ static void
delete_retransmission_frame(QUICFrame *frame)
{
frame->~QUICFrame();
@@ -968,6 +1008,11 @@ public:
uint32_t sequence, QUICConnectionId connectoin_id, QUICStatelessResetToken
stateless_reset_token);
/*
+ * Creates a NEW_TOKEN frame
+ */
+ static std::unique_ptr<QUICNewTokenFrame, QUICFrameDeleterFunc>
create_new_token_frame(const uint8_t *token, uint64_t token_len);
+
+ /*
* Creates a retransmission frame, which is very special.
* This retransmission frame will be used only for retransmission and it's
not a standard frame type.
*/
diff --git a/iocore/net/quic/QUICTypes.h b/iocore/net/quic/QUICTypes.h
index 8b4df08..b58b007 100644
--- a/iocore/net/quic/QUICTypes.h
+++ b/iocore/net/quic/QUICTypes.h
@@ -109,6 +109,7 @@ enum class QUICFrameType : uint8_t {
PATH_RESPONSE,
STREAM = 0x10, // 0x10 - 0x17
CRYPTO = 0x18,
+ NEW_TOKEN,
UNKNOWN,
};
diff --git a/iocore/net/quic/test/test_QUICFrame.cc
b/iocore/net/quic/test/test_QUICFrame.cc
index 6a32a46..ad67a6f 100644
--- a/iocore/net/quic/test/test_QUICFrame.cc
+++ b/iocore/net/quic/test/test_QUICFrame.cc
@@ -49,6 +49,7 @@ TEST_CASE("QUICFrame Type", "[quic]")
CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x10")) ==
QUICFrameType::STREAM);
CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x17")) ==
QUICFrameType::STREAM);
CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x18")) ==
QUICFrameType::CRYPTO);
+ CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x19")) ==
QUICFrameType::NEW_TOKEN);
// Undefined ragne
CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x21")) ==
QUICFrameType::UNKNOWN);
CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\xff")) ==
QUICFrameType::UNKNOWN);
@@ -1133,6 +1134,47 @@ TEST_CASE("Store PATH_RESPONSE Frame", "[quic]")
CHECK(memcmp(buf, expected, len) == 0);
}
+TEST_CASE("NEW_TOKEN Frame", "[quic]")
+{
+ uint8_t raw_new_token_frame[] = {
+ 0x19, // Type
+ 0x08, // Token Length (i)
+ 0xbe, 0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe, 0xef, // Token (*)
+ };
+ size_t raw_new_token_frame_len = sizeof(raw_new_token_frame);
+
+ uint8_t raw_token[] = {0xbe, 0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe, 0xef};
+ size_t raw_token_len = sizeof(raw_token);
+
+ SECTION("load")
+ {
+ std::shared_ptr<const QUICFrame> frame =
QUICFrameFactory::create(raw_new_token_frame, raw_new_token_frame_len);
+ CHECK(frame->type() == QUICFrameType::NEW_TOKEN);
+ CHECK(frame->size() == raw_new_token_frame_len);
+
+ std::shared_ptr<const QUICNewTokenFrame> new_token_frame =
std::dynamic_pointer_cast<const QUICNewTokenFrame>(frame);
+ CHECK(new_token_frame != nullptr);
+ CHECK(new_token_frame->token_length() == raw_token_len);
+ CHECK(memcmp(new_token_frame->token(), raw_token, raw_token_len) == 0);
+ }
+
+ SECTION("store")
+ {
+ uint8_t buf[32];
+ size_t len;
+
+ ats_unique_buf token = ats_unique_malloc(raw_token_len);
+ memcpy(token.get(), raw_token, raw_token_len);
+
+ QUICNewTokenFrame frame(std::move(token), raw_token_len);
+ CHECK(frame.size() == raw_new_token_frame_len);
+
+ frame.store(buf, &len, 16);
+ CHECK(len == raw_new_token_frame_len);
+ CHECK(memcmp(buf, raw_new_token_frame, len) == 0);
+ }
+}
+
TEST_CASE("QUICFrameFactory Create Unknown Frame", "[quic]")
{
uint8_t buf1[] = {