diff options
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.cc | 231 |
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 |