summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc')
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc231
1 files changed, 231 insertions, 0 deletions
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc
new file mode 100644
index 00000000000..2222fed4b6b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc
@@ -0,0 +1,231 @@
+#include "http2/adapter/oghttp2_session.h"
+
+#include "absl/strings/escaping.h"
+
+namespace http2 {
+namespace adapter {
+
+void OgHttp2Session::PassthroughHeadersHandler::OnHeaderBlockStart() {
+ visitor_.OnBeginHeadersForStream(stream_id_);
+}
+
+void OgHttp2Session::PassthroughHeadersHandler::OnHeader(
+ absl::string_view key,
+ absl::string_view value) {
+ visitor_.OnHeaderForStream(stream_id_, key, value);
+}
+
+void OgHttp2Session::PassthroughHeadersHandler::OnHeaderBlockEnd(
+ size_t /* uncompressed_header_bytes */,
+ size_t /* compressed_header_bytes */) {
+ visitor_.OnEndHeadersForStream(stream_id_);
+}
+
+OgHttp2Session::OgHttp2Session(Http2VisitorInterface& visitor, Options options)
+ : visitor_(visitor), headers_handler_(visitor), options_(options) {
+ decoder_.set_visitor(this);
+ if (options_.perspective == Perspective::kServer) {
+ remaining_preface_ = {spdy::kHttp2ConnectionHeaderPrefix,
+ spdy::kHttp2ConnectionHeaderPrefixSize};
+ }
+}
+
+OgHttp2Session::~OgHttp2Session() {}
+
+ssize_t OgHttp2Session::ProcessBytes(absl::string_view bytes) {
+ ssize_t preface_consumed = 0;
+ if (!remaining_preface_.empty()) {
+ QUICHE_VLOG(2) << "Preface bytes remaining: " << remaining_preface_.size();
+ // decoder_ does not understand the client connection preface.
+ size_t min_size = std::min(remaining_preface_.size(), bytes.size());
+ if (!absl::StartsWith(remaining_preface_, bytes.substr(0, min_size))) {
+ // Preface doesn't match!
+ QUICHE_DLOG(INFO) << "Preface doesn't match! Expected: ["
+ << absl::CEscape(remaining_preface_) << "], actual: ["
+ << absl::CEscape(bytes) << "]";
+ visitor_.OnConnectionError();
+ return -1;
+ }
+ remaining_preface_.remove_prefix(min_size);
+ bytes.remove_prefix(min_size);
+ if (!remaining_preface_.empty()) {
+ QUICHE_VLOG(2) << "Preface bytes remaining: "
+ << remaining_preface_.size();
+ return min_size;
+ }
+ preface_consumed = min_size;
+ }
+ ssize_t result = decoder_.ProcessInput(bytes.data(), bytes.size());
+ return result < 0 ? result : result + preface_consumed;
+}
+
+int OgHttp2Session::Consume(Http2StreamId stream_id, size_t num_bytes) {
+ auto it = stream_map_.find(stream_id);
+ if (it == stream_map_.end()) {
+ // TODO(b/181586191): LOG_ERROR rather than QUICHE_BUG.
+ QUICHE_BUG(stream_consume_notfound)
+ << "Stream " << stream_id << " not found";
+ } else {
+ it->second.window_manager.MarkDataFlushed(num_bytes);
+ }
+ return 0; // Remove?
+}
+
+void OgHttp2Session::EnqueueFrame(std::unique_ptr<spdy::SpdyFrameIR> frame) {
+ frames_.push_back(std::move(frame));
+}
+
+std::string OgHttp2Session::GetBytesToWrite(absl::optional<size_t> max_bytes) {
+ const size_t serialized_max =
+ max_bytes ? max_bytes.value() : std::numeric_limits<size_t>::max();
+ std::string serialized = std::move(serialized_prefix_);
+ while (serialized.size() < serialized_max && !frames_.empty()) {
+ spdy::SpdySerializedFrame frame = framer_.SerializeFrame(*frames_.front());
+ absl::StrAppend(&serialized, absl::string_view(frame));
+ frames_.pop_front();
+ }
+ if (serialized.size() > serialized_max) {
+ serialized_prefix_ = serialized.substr(serialized_max);
+ serialized.resize(serialized_max);
+ }
+ return serialized;
+}
+
+void OgHttp2Session::OnError(http2::Http2DecoderAdapter::SpdyFramerError error,
+ std::string detailed_error) {
+ QUICHE_VLOG(1) << "Error: "
+ << http2::Http2DecoderAdapter::SpdyFramerErrorToString(error)
+ << " details: " << detailed_error;
+ visitor_.OnConnectionError();
+}
+
+void OgHttp2Session::OnCommonHeader(spdy::SpdyStreamId stream_id,
+ size_t length,
+ uint8_t type,
+ uint8_t flags) {
+ visitor_.OnFrameHeader(stream_id, length, type, flags);
+}
+
+void OgHttp2Session::OnDataFrameHeader(spdy::SpdyStreamId stream_id,
+ size_t length,
+ bool fin) {
+ visitor_.OnBeginDataForStream(stream_id, length);
+}
+
+void OgHttp2Session::OnStreamFrameData(spdy::SpdyStreamId stream_id,
+ const char* data,
+ size_t len) {
+ visitor_.OnDataForStream(stream_id, absl::string_view(data, len));
+}
+
+void OgHttp2Session::OnStreamEnd(spdy::SpdyStreamId stream_id) {
+ visitor_.OnEndStream(stream_id);
+}
+
+void OgHttp2Session::OnStreamPadLength(spdy::SpdyStreamId /*stream_id*/,
+ size_t /*value*/) {
+ // TODO(181586191): handle padding
+}
+
+void OgHttp2Session::OnStreamPadding(spdy::SpdyStreamId stream_id, size_t len) {
+ // TODO(181586191): handle padding
+}
+
+spdy::SpdyHeadersHandlerInterface* OgHttp2Session::OnHeaderFrameStart(
+ spdy::SpdyStreamId stream_id) {
+ headers_handler_.set_stream_id(stream_id);
+ return &headers_handler_;
+}
+
+void OgHttp2Session::OnHeaderFrameEnd(spdy::SpdyStreamId stream_id) {
+ headers_handler_.set_stream_id(0);
+}
+
+void OgHttp2Session::OnRstStream(spdy::SpdyStreamId stream_id,
+ spdy::SpdyErrorCode error_code) {
+ visitor_.OnRstStream(stream_id, TranslateErrorCode(error_code));
+ visitor_.OnCloseStream(stream_id, TranslateErrorCode(error_code));
+}
+
+void OgHttp2Session::OnSettings() {
+ visitor_.OnSettingsStart();
+}
+
+void OgHttp2Session::OnSetting(spdy::SpdySettingsId id, uint32_t value) {
+ visitor_.OnSetting({id, value});
+}
+
+void OgHttp2Session::OnSettingsEnd() {
+ visitor_.OnSettingsEnd();
+}
+
+void OgHttp2Session::OnSettingsAck() {
+ visitor_.OnSettingsAck();
+}
+
+void OgHttp2Session::OnPing(spdy::SpdyPingId unique_id, bool is_ack) {
+ visitor_.OnPing(unique_id, is_ack);
+}
+
+void OgHttp2Session::OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
+ spdy::SpdyErrorCode error_code) {
+ received_goaway_ = true;
+ visitor_.OnGoAway(last_accepted_stream_id, TranslateErrorCode(error_code),
+ "");
+}
+
+bool OgHttp2Session::OnGoAwayFrameData(const char* goaway_data, size_t len) {
+ // Opaque data is currently ignored.
+ return true;
+}
+
+void OgHttp2Session::OnHeaders(spdy::SpdyStreamId stream_id,
+ bool has_priority,
+ int weight,
+ spdy::SpdyStreamId parent_stream_id,
+ bool exclusive,
+ bool fin,
+ bool end) {}
+
+void OgHttp2Session::OnWindowUpdate(spdy::SpdyStreamId stream_id,
+ int delta_window_size) {
+ if (stream_id == 0) {
+ peer_window_ += delta_window_size;
+ } else {
+ auto it = stream_map_.find(stream_id);
+ if (it == stream_map_.end()) {
+ QUICHE_VLOG(1) << "Stream " << stream_id << " not found!";
+ } else {
+ it->second.send_window += delta_window_size;
+ }
+ }
+ visitor_.OnWindowUpdate(stream_id, delta_window_size);
+}
+
+void OgHttp2Session::OnPushPromise(spdy::SpdyStreamId stream_id,
+ spdy::SpdyStreamId promised_stream_id,
+ bool end) {}
+
+void OgHttp2Session::OnContinuation(spdy::SpdyStreamId stream_id, bool end) {}
+
+void OgHttp2Session::OnAltSvc(spdy::SpdyStreamId /*stream_id*/,
+ absl::string_view /*origin*/,
+ const spdy::SpdyAltSvcWireFormat::
+ AlternativeServiceVector& /*altsvc_vector*/) {
+}
+
+void OgHttp2Session::OnPriority(spdy::SpdyStreamId stream_id,
+ spdy::SpdyStreamId parent_stream_id,
+ int weight,
+ bool exclusive) {}
+
+void OgHttp2Session::OnPriorityUpdate(spdy::SpdyStreamId prioritized_stream_id,
+ absl::string_view priority_field_value) {}
+
+bool OgHttp2Session::OnUnknownFrame(spdy::SpdyStreamId stream_id,
+ uint8_t frame_type) {
+ return true;
+}
+
+} // namespace adapter
+} // namespace http2