Project import generated by Copybara.
PiperOrigin-RevId: 224614037
Change-Id: I14e53449d4aeccb328f86828c76b5f09dea0d4b8
diff --git a/http2/http2_structures.h b/http2/http2_structures.h
new file mode 100644
index 0000000..01c011e
--- /dev/null
+++ b/http2/http2_structures.h
@@ -0,0 +1,325 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_HTTP2_HTTP2_STRUCTURES_H_
+#define QUICHE_HTTP2_HTTP2_STRUCTURES_H_
+
+// Defines structs for various fixed sized structures in HTTP/2.
+//
+// Those structs with multiple fields have constructors that take arguments in
+// the same order as their encoding (which may be different from their order
+// in the struct). For single field structs, use aggregate initialization if
+// desired, e.g.:
+//
+// Http2RstStreamFields var{Http2ErrorCode::ENHANCE_YOUR_CALM};
+// or:
+// SomeFunc(Http2RstStreamFields{Http2ErrorCode::ENHANCE_YOUR_CALM});
+//
+// Each struct includes a static method EncodedSize which returns the number
+// of bytes of the encoding.
+//
+// With the exception of Http2FrameHeader, all the types are named
+// Http2<X>Fields, where X is the title-case form of the frame which always
+// includes the fields; the "always" is to cover the case of the PRIORITY frame;
+// its fields optionally appear in the HEADERS frame, but the struct is called
+// Http2PriorityFields.
+
+#include <stddef.h>
+
+#include <cstdint>
+#include <ostream>
+
+#include "base/logging.h"
+#include "net/third_party/quiche/src/http2/http2_constants.h"
+#include "net/third_party/quiche/src/http2/platform/api/http2_export.h"
+#include "net/third_party/quiche/src/http2/platform/api/http2_string.h"
+
+namespace http2 {
+
+struct HTTP2_EXPORT_PRIVATE Http2FrameHeader {
+ Http2FrameHeader() {}
+ Http2FrameHeader(uint32_t payload_length,
+ Http2FrameType type,
+ uint8_t flags,
+ uint32_t stream_id)
+ : payload_length(payload_length),
+ stream_id(stream_id),
+ type(type),
+ flags(static_cast<Http2FrameFlag>(flags)) {
+ DCHECK_LT(payload_length, static_cast<uint32_t>(1 << 24))
+ << "Payload Length is only a 24 bit field\n"
+ << ToString();
+ }
+
+ static constexpr size_t EncodedSize() { return 9; }
+
+ // Keep the current value of those flags that are in
+ // valid_flags, and clear all the others.
+ void RetainFlags(uint8_t valid_flags) {
+ flags = static_cast<Http2FrameFlag>(flags & valid_flags);
+ }
+
+ // Returns true if any of the flags in flag_mask are set,
+ // otherwise false.
+ bool HasAnyFlags(uint8_t flag_mask) const { return 0 != (flags & flag_mask); }
+
+ // Is the END_STREAM flag set?
+ bool IsEndStream() const {
+ DCHECK(type == Http2FrameType::DATA || type == Http2FrameType::HEADERS)
+ << ToString();
+ return (flags & Http2FrameFlag::END_STREAM) != 0;
+ }
+
+ // Is the ACK flag set?
+ bool IsAck() const {
+ DCHECK(type == Http2FrameType::SETTINGS || type == Http2FrameType::PING)
+ << ToString();
+ return (flags & Http2FrameFlag::ACK) != 0;
+ }
+
+ // Is the END_HEADERS flag set?
+ bool IsEndHeaders() const {
+ DCHECK(type == Http2FrameType::HEADERS ||
+ type == Http2FrameType::PUSH_PROMISE ||
+ type == Http2FrameType::CONTINUATION)
+ << ToString();
+ return (flags & Http2FrameFlag::END_HEADERS) != 0;
+ }
+
+ // Is the PADDED flag set?
+ bool IsPadded() const {
+ DCHECK(type == Http2FrameType::DATA || type == Http2FrameType::HEADERS ||
+ type == Http2FrameType::PUSH_PROMISE)
+ << ToString();
+ return (flags & Http2FrameFlag::PADDED) != 0;
+ }
+
+ // Is the PRIORITY flag set?
+ bool HasPriority() const {
+ DCHECK_EQ(type, Http2FrameType::HEADERS) << ToString();
+ return (flags & Http2FrameFlag::PRIORITY) != 0;
+ }
+
+ // Does the encoding of this header start with "HTTP/", indicating that it
+ // might be from a non-HTTP/2 server.
+ bool IsProbableHttpResponse() const;
+
+ // Produce strings useful for debugging/logging messages.
+ Http2String ToString() const;
+ Http2String FlagsToString() const;
+
+ // 24 bit length of the payload after the header, including any padding.
+ // First field in encoding.
+ uint32_t payload_length; // 24 bits
+
+ // 31 bit stream id, with high bit (32nd bit) reserved (must be zero),
+ // and is cleared during decoding.
+ // Fourth field in encoding.
+ uint32_t stream_id;
+
+ // Type of the frame.
+ // Second field in encoding.
+ Http2FrameType type;
+
+ // Flag bits, with interpretations that depend upon the frame type.
+ // Flag bits not used by the frame type are cleared.
+ // Third field in encoding.
+ Http2FrameFlag flags;
+};
+
+HTTP2_EXPORT_PRIVATE bool operator==(const Http2FrameHeader& a,
+ const Http2FrameHeader& b);
+HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2FrameHeader& a,
+ const Http2FrameHeader& b) {
+ return !(a == b);
+}
+HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2FrameHeader& v);
+
+// Http2PriorityFields:
+
+struct HTTP2_EXPORT_PRIVATE Http2PriorityFields {
+ Http2PriorityFields() {}
+ Http2PriorityFields(uint32_t stream_dependency,
+ uint32_t weight,
+ bool is_exclusive)
+ : stream_dependency(stream_dependency),
+ weight(weight),
+ is_exclusive(is_exclusive) {
+ // Can't have the high-bit set in the stream id because we need to use
+ // that for the EXCLUSIVE flag bit.
+ DCHECK_EQ(stream_dependency, stream_dependency & StreamIdMask())
+ << "Stream Dependency is only a 31-bit field.\n"
+ << ToString();
+ DCHECK_LE(1u, weight) << "Weight is too small.";
+ DCHECK_LE(weight, 256u) << "Weight is too large.";
+ }
+ static constexpr size_t EncodedSize() { return 5; }
+
+ // Produce strings useful for debugging/logging messages.
+ Http2String ToString() const;
+
+ // A 31-bit stream identifier for the stream that this stream depends on.
+ uint32_t stream_dependency;
+
+ // Weight (1 to 256) is encoded as a byte in the range 0 to 255, so we
+ // add one when decoding, and store it in a field larger than a byte.
+ uint32_t weight;
+
+ // A single-bit flag indicating that the stream dependency is exclusive;
+ // extracted from high bit of stream dependency field during decoding.
+ bool is_exclusive;
+};
+
+HTTP2_EXPORT_PRIVATE bool operator==(const Http2PriorityFields& a,
+ const Http2PriorityFields& b);
+HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2PriorityFields& a,
+ const Http2PriorityFields& b) {
+ return !(a == b);
+}
+HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2PriorityFields& v);
+
+// Http2RstStreamFields:
+
+struct Http2RstStreamFields {
+ static constexpr size_t EncodedSize() { return 4; }
+ bool IsSupportedErrorCode() const {
+ return IsSupportedHttp2ErrorCode(error_code);
+ }
+
+ Http2ErrorCode error_code;
+};
+
+HTTP2_EXPORT_PRIVATE bool operator==(const Http2RstStreamFields& a,
+ const Http2RstStreamFields& b);
+HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2RstStreamFields& a,
+ const Http2RstStreamFields& b) {
+ return !(a == b);
+}
+HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2RstStreamFields& v);
+
+// Http2SettingFields:
+
+struct Http2SettingFields {
+ Http2SettingFields() {}
+ Http2SettingFields(Http2SettingsParameter parameter, uint32_t value)
+ : parameter(parameter), value(value) {}
+ static constexpr size_t EncodedSize() { return 6; }
+ bool IsSupportedParameter() const {
+ return IsSupportedHttp2SettingsParameter(parameter);
+ }
+
+ Http2SettingsParameter parameter;
+ uint32_t value;
+};
+
+HTTP2_EXPORT_PRIVATE bool operator==(const Http2SettingFields& a,
+ const Http2SettingFields& b);
+HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2SettingFields& a,
+ const Http2SettingFields& b) {
+ return !(a == b);
+}
+HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2SettingFields& v);
+
+// Http2PushPromiseFields:
+
+struct Http2PushPromiseFields {
+ static constexpr size_t EncodedSize() { return 4; }
+
+ uint32_t promised_stream_id;
+};
+
+HTTP2_EXPORT_PRIVATE bool operator==(const Http2PushPromiseFields& a,
+ const Http2PushPromiseFields& b);
+HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2PushPromiseFields& a,
+ const Http2PushPromiseFields& b) {
+ return !(a == b);
+}
+HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2PushPromiseFields& v);
+
+// Http2PingFields:
+
+struct Http2PingFields {
+ static constexpr size_t EncodedSize() { return 8; }
+
+ uint8_t opaque_bytes[8];
+};
+
+HTTP2_EXPORT_PRIVATE bool operator==(const Http2PingFields& a,
+ const Http2PingFields& b);
+HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2PingFields& a,
+ const Http2PingFields& b) {
+ return !(a == b);
+}
+HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2PingFields& v);
+
+// Http2GoAwayFields:
+
+struct Http2GoAwayFields {
+ Http2GoAwayFields() {}
+ Http2GoAwayFields(uint32_t last_stream_id, Http2ErrorCode error_code)
+ : last_stream_id(last_stream_id), error_code(error_code) {}
+ static constexpr size_t EncodedSize() { return 8; }
+ bool IsSupportedErrorCode() const {
+ return IsSupportedHttp2ErrorCode(error_code);
+ }
+
+ uint32_t last_stream_id;
+ Http2ErrorCode error_code;
+};
+
+HTTP2_EXPORT_PRIVATE bool operator==(const Http2GoAwayFields& a,
+ const Http2GoAwayFields& b);
+HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2GoAwayFields& a,
+ const Http2GoAwayFields& b) {
+ return !(a == b);
+}
+HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2GoAwayFields& v);
+
+// Http2WindowUpdateFields:
+
+struct Http2WindowUpdateFields {
+ static constexpr size_t EncodedSize() { return 4; }
+
+ // 31-bit, unsigned increase in the window size (only positive values are
+ // allowed). The high-bit is reserved for the future.
+ uint32_t window_size_increment;
+};
+
+HTTP2_EXPORT_PRIVATE bool operator==(const Http2WindowUpdateFields& a,
+ const Http2WindowUpdateFields& b);
+HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2WindowUpdateFields& a,
+ const Http2WindowUpdateFields& b) {
+ return !(a == b);
+}
+HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2WindowUpdateFields& v);
+
+// Http2AltSvcFields:
+
+struct Http2AltSvcFields {
+ static constexpr size_t EncodedSize() { return 2; }
+
+ // This is the one fixed size portion of the ALTSVC payload.
+ uint16_t origin_length;
+};
+
+HTTP2_EXPORT_PRIVATE bool operator==(const Http2AltSvcFields& a,
+ const Http2AltSvcFields& b);
+HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2AltSvcFields& a,
+ const Http2AltSvcFields& b) {
+ return !(a == b);
+}
+HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
+ const Http2AltSvcFields& v);
+
+} // namespace http2
+
+#endif // QUICHE_HTTP2_HTTP2_STRUCTURES_H_