-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HTTP1: Add DumpState support for HTTP1. #14812
Changes from all commits
125129d
5bbe8ed
090ce6c
0df63f0
97af1ce
813be1b
ca7d535
81c9ee9
020ed25
d3a50a5
5d3838b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,9 @@ | |
#include "envoy/network/connection.h" | ||
|
||
#include "common/common/cleanup.h" | ||
#include "common/common/dump_state_utils.h" | ||
#include "common/common/enum_to_int.h" | ||
#include "common/common/scope_tracker.h" | ||
#include "common/common/statusor.h" | ||
#include "common/common/utility.h" | ||
#include "common/grpc/common.h" | ||
|
@@ -67,7 +69,6 @@ HeaderKeyFormatterPtr formatter(const Http::Http1Settings& settings) { | |
|
||
return nullptr; | ||
} | ||
|
||
} // namespace | ||
|
||
const std::string StreamEncoderImpl::CRLF = "\r\n"; | ||
|
@@ -569,6 +570,8 @@ Http::Status ClientConnectionImpl::dispatch(Buffer::Instance& data) { | |
} | ||
|
||
Http::Status ConnectionImpl::innerDispatch(Buffer::Instance& data) { | ||
// Add self to the Dispatcher's tracked object stack. | ||
ScopeTrackerScopeState scope(this, connection_.dispatcher()); | ||
ENVOY_CONN_LOG(trace, "parsing {} bytes", connection_, data.length()); | ||
// Make sure that dispatching_ is set to false after dispatching, even when | ||
// http_parser exits early with an error code. | ||
|
@@ -863,6 +866,73 @@ void ConnectionImpl::onResetStreamBase(StreamResetReason reason) { | |
onResetStream(reason); | ||
} | ||
|
||
void ConnectionImpl::dumpState(std::ostream& os, int indent_level) const { | ||
const char* spaces = spacesForLevel(indent_level); | ||
os << spaces << "Http1::ConnectionImpl " << this << DUMP_MEMBER(dispatching_) | ||
<< DUMP_MEMBER(dispatching_slice_already_drained_) << DUMP_MEMBER(reset_stream_called_) | ||
<< DUMP_MEMBER(handling_upgrade_) << DUMP_MEMBER(deferred_end_stream_headers_) | ||
<< DUMP_MEMBER(strict_1xx_and_204_headers_) << DUMP_MEMBER(processing_trailers_) | ||
<< DUMP_MEMBER(buffered_body_.length()); | ||
|
||
// Dump header parsing state, and any progress on headers. | ||
os << DUMP_MEMBER(header_parsing_state_); | ||
os << DUMP_MEMBER_AS(current_header_field_, current_header_field_.getStringView()); | ||
os << DUMP_MEMBER_AS(current_header_value_, current_header_value_.getStringView()); | ||
|
||
// Dump Child | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that the dump for current_dispatching_buffer_ should be done via DUMP_DETAILS. Consider putting it after the dump of header maps in subclasses. Reasoning: buffer contents can be long and may contain newlines There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense; It's now after the dump of header maps. By "via We could explicitly add a dumpState method to the buffer if that's what you meant, but given we're just dumping the first slice. |
||
os << '\n'; | ||
dumpAdditionalState(os, indent_level); | ||
|
||
// Dump the first slice of the dispatching buffer if not drained escaping | ||
// certain characters. We do this last as the slice could be rather large. | ||
if (current_dispatching_buffer_ == nullptr || dispatching_slice_already_drained_) { | ||
// Buffer is either null or already drained (in the body). | ||
// Use the macro for consistent formatting. | ||
os << DUMP_NULLABLE_MEMBER(current_dispatching_buffer_, "drained"); | ||
return; | ||
} else { | ||
absl::string_view front_slice = [](Buffer::RawSlice slice) { | ||
return absl::string_view(static_cast<const char*>(slice.mem_), slice.len_); | ||
}(current_dispatching_buffer_->frontSlice()); | ||
|
||
// Dump buffer data escaping \r, \n, \t, ", ', and \. | ||
// This is not the most performant implementation, but we're crashing and | ||
// cannot allocate memory. | ||
os << spaces << "current_dispatching_buffer_ front_slice length: " << front_slice.length() | ||
<< " contents: \""; | ||
StringUtil::escapeToOstream(os, front_slice); | ||
os << "\"\n"; | ||
} | ||
} | ||
|
||
void ServerConnectionImpl::dumpAdditionalState(std::ostream& os, int indent_level) const { | ||
const char* spaces = spacesForLevel(indent_level); | ||
os << DUMP_MEMBER_AS(active_request_.request_url_, | ||
active_request_.has_value() && | ||
!active_request_.value().request_url_.getStringView().empty() | ||
? active_request_.value().request_url_.getStringView() | ||
: "null"); | ||
os << '\n'; | ||
|
||
// Dump header map, it may be null if it was moved to the request, and | ||
// request_url. | ||
if (absl::holds_alternative<RequestHeaderMapPtr>(headers_or_trailers_)) { | ||
DUMP_DETAILS(absl::get<RequestHeaderMapPtr>(headers_or_trailers_)); | ||
} else { | ||
DUMP_DETAILS(absl::get<RequestTrailerMapPtr>(headers_or_trailers_)); | ||
} | ||
antoniovicente marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
void ClientConnectionImpl::dumpAdditionalState(std::ostream& os, int indent_level) const { | ||
antoniovicente marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const char* spaces = spacesForLevel(indent_level); | ||
// Dump header map, it may be null if it was moved to the request. | ||
if (absl::holds_alternative<ResponseHeaderMapPtr>(headers_or_trailers_)) { | ||
DUMP_DETAILS(absl::get<ResponseHeaderMapPtr>(headers_or_trailers_)); | ||
} else { | ||
DUMP_DETAILS(absl::get<ResponseTrailerMapPtr>(headers_or_trailers_)); | ||
} | ||
} | ||
|
||
ServerConnectionImpl::ServerConnectionImpl( | ||
Network::Connection& connection, CodecStats& stats, ServerConnectionCallbacks& callbacks, | ||
const Http1Settings& settings, uint32_t max_request_headers_kb, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these are the most important to escape, but I can see us also escaping c < ' ' and c >= 127. We can take that on in a followup if we decide it is useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do in a followup if needed. Added a todo here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's also escaping code in
source/common/common/logger.cc
inDelegatingLogSink::escapeLogLine()
which callsabsl::CEscape
. Can you use that instead?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope,
absl::CEscape
allocs memory via the string it'll create and return. This avoids memory allocs.