Fixes frame length calculations to use the actual serialized length. PiperOrigin-RevId: 409202403
diff --git a/http2/adapter/oghttp2_session.cc b/http2/adapter/oghttp2_session.cc index 21dd589..379a40b 100644 --- a/http2/adapter/oghttp2_session.cc +++ b/http2/adapter/oghttp2_session.cc
@@ -36,60 +36,50 @@ void VisitData(const spdy::SpdyDataIR& data) override { frame_type_ = static_cast<uint8_t>(data.frame_type()); stream_id_ = data.stream_id(); - length_ = - data.data_len() + (data.padded() ? 1 : 0) + data.padding_payload_len(); flags_ = (data.fin() ? 0x1 : 0) | (data.padded() ? 0x8 : 0); } void VisitHeaders(const spdy::SpdyHeadersIR& headers) override { frame_type_ = static_cast<uint8_t>(headers.frame_type()); stream_id_ = headers.stream_id(); - length_ = headers.size() - spdy::kFrameHeaderSize; flags_ = 0x4 | (headers.fin() ? 0x1 : 0) | (headers.padded() ? 0x8 : 0) | (headers.has_priority() ? 0x20 : 0); } void VisitPriority(const spdy::SpdyPriorityIR& priority) override { frame_type_ = static_cast<uint8_t>(priority.frame_type()); frame_type_ = 2; - length_ = 5; stream_id_ = priority.stream_id(); } void VisitRstStream(const spdy::SpdyRstStreamIR& rst_stream) override { frame_type_ = static_cast<uint8_t>(rst_stream.frame_type()); frame_type_ = 3; - length_ = 4; stream_id_ = rst_stream.stream_id(); error_code_ = rst_stream.error_code(); } void VisitSettings(const spdy::SpdySettingsIR& settings) override { frame_type_ = static_cast<uint8_t>(settings.frame_type()); frame_type_ = 4; - length_ = 6 * settings.values().size(); flags_ = (settings.is_ack() ? 0x1 : 0); } void VisitPushPromise(const spdy::SpdyPushPromiseIR& push_promise) override { frame_type_ = static_cast<uint8_t>(push_promise.frame_type()); frame_type_ = 5; - length_ = push_promise.size() - spdy::kFrameHeaderSize; stream_id_ = push_promise.stream_id(); flags_ = (push_promise.padded() ? 0x8 : 0); } void VisitPing(const spdy::SpdyPingIR& ping) override { frame_type_ = static_cast<uint8_t>(ping.frame_type()); frame_type_ = 6; - length_ = 8; flags_ = (ping.is_ack() ? 0x1 : 0); } void VisitGoAway(const spdy::SpdyGoAwayIR& goaway) override { frame_type_ = static_cast<uint8_t>(goaway.frame_type()); frame_type_ = 7; - length_ = goaway.size() - spdy::kFrameHeaderSize; error_code_ = goaway.error_code(); } void VisitWindowUpdate( const spdy::SpdyWindowUpdateIR& window_update) override { frame_type_ = static_cast<uint8_t>(window_update.frame_type()); frame_type_ = 8; - length_ = 4; stream_id_ = window_update.stream_id(); } void VisitContinuation( @@ -97,13 +87,11 @@ frame_type_ = static_cast<uint8_t>(continuation.frame_type()); stream_id_ = continuation.stream_id(); flags_ = continuation.end_headers() ? 0x4 : 0; - length_ = continuation.size() - spdy::kFrameHeaderSize; } void VisitUnknown(const spdy::SpdyUnknownIR& unknown) override { frame_type_ = static_cast<uint8_t>(unknown.frame_type()); stream_id_ = unknown.stream_id(); flags_ = unknown.flags(); - length_ = unknown.size() - spdy::kFrameHeaderSize; } void VisitAltSvc(const spdy::SpdyAltSvcIR& /*altsvc*/) override {} void VisitPriorityUpdate( @@ -111,14 +99,12 @@ void VisitAcceptCh(const spdy::SpdyAcceptChIR& /*accept_ch*/) override {} uint32_t stream_id() { return stream_id_; } - uint32_t length() { return length_; } uint32_t error_code() { return error_code_; } uint8_t frame_type() { return frame_type_; } uint8_t flags() { return flags_; } private: uint32_t stream_id_ = 0; - uint32_t length_ = 0; uint32_t error_code_ = 0; uint8_t frame_type_ = 0; uint8_t flags_ = 0; @@ -457,10 +443,13 @@ const auto& frame_ptr = frames_.front(); FrameAttributeCollector c; frame_ptr->Visit(&c); - visitor_.OnBeforeFrameSent(c.frame_type(), c.stream_id(), c.length(), - c.flags()); - frame_ptr->Visit(&send_logger_); + // Frames can't accurately report their own length; the actual serialized + // length must be used instead. spdy::SpdySerializedFrame frame = framer_.SerializeFrame(*frame_ptr); + const size_t frame_payload_length = frame.size() - spdy::kFrameHeaderSize; + frame_ptr->Visit(&send_logger_); + visitor_.OnBeforeFrameSent(c.frame_type(), c.stream_id(), + frame_payload_length, c.flags()); const int64_t result = visitor_.OnReadyToSend(absl::string_view(frame)); if (result < 0) { LatchErrorAndNotify(Http2ErrorCode::INTERNAL_ERROR, @@ -470,8 +459,8 @@ // Write blocked. return false; } else { - visitor_.OnFrameSent(c.frame_type(), c.stream_id(), c.length(), c.flags(), - c.error_code()); + visitor_.OnFrameSent(c.frame_type(), c.stream_id(), frame_payload_length, + c.flags(), c.error_code()); if (static_cast<FrameType>(c.frame_type()) == FrameType::RST_STREAM) { // If this endpoint is resetting the stream, the stream should be // closed. This endpoint is already aware of the outbound RST_STREAM and @@ -482,7 +471,7 @@ frames_.pop_front(); if (static_cast<size_t>(result) < frame.size()) { // The frame was partially written, so the rest must be buffered. - serialized_prefix_.assign(frame.data() + result, frame.size() - result); + serialized_prefix_.append(frame.data() + result, frame.size() - result); return false; } }