Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8c99d4f
Implemented H2 stream level buffer accounting.
KBaichoo Apr 13, 2021
44a5e05
Simplified stream API, H2 codec impl. Reverted setWatermark as change
KBaichoo Apr 30, 2021
6956e95
Added test for Set and Wait for Expected Account Balance.
KBaichoo Apr 30, 2021
dbc66ad
Fixing broken tests.
KBaichoo May 3, 2021
65e8206
Merge remote-tracking branch 'upstream/main' into accounting-connect-…
KBaichoo May 3, 2021
8abaa72
Fixed broken extension test.
KBaichoo May 3, 2021
f7ca7dd
Moved location of method.
KBaichoo May 4, 2021
922a222
Merged upstream.
KBaichoo May 6, 2021
0295ac9
Use Release Assert in test code with side effects (i.e. erase).
KBaichoo May 6, 2021
1644e66
Minor Fixes.
KBaichoo May 7, 2021
091dc3e
Added disabled by default test only runtime guard.
KBaichoo May 10, 2021
2d5fba4
Merge remote-tracking branch 'upstream/main' into accounting-connect-…
KBaichoo May 10, 2021
3e5f947
Clangtidy.
KBaichoo May 11, 2021
324dbf9
Merged main.
KBaichoo May 13, 2021
ee69562
Merge remote-tracking branch 'upstream/main' into accounting-connect-…
KBaichoo May 14, 2021
d8f2db7
Merge remote-tracking branch 'upstream/main' into accounting-connect-…
KBaichoo May 17, 2021
2e65c5d
Cleanup tests.
KBaichoo May 19, 2021
f204c8a
Merge remote-tracking branch 'upstream/main' into accounting-connect-…
KBaichoo May 19, 2021
c06b5d5
Additional test infra changes.
KBaichoo May 20, 2021
7b32a8d
Nit fix.
KBaichoo May 21, 2021
60ca164
Merge remote-tracking branch 'upstream/main' into accounting-connect-…
KBaichoo May 21, 2021
03e7a13
Coverage revert.
KBaichoo May 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions include/envoy/http/codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,19 @@ class Stream {
* small window updates as satisfying the idle timeout as this is a potential DoS vector.
*/
virtual void setFlushTimeout(std::chrono::milliseconds timeout) PURE;

/**
* @return the account associated with this stream.
*/
virtual Buffer::BufferMemoryAccountSharedPtr getAccount() const PURE;

/**
* Sets the account for this stream, propagating it to all of its buffers.
* This should only be called on client streams since server streams create
* their own account.
Comment thread
KBaichoo marked this conversation as resolved.
Outdated
* @param the account to assign this stream.
*/
virtual void setAccount(Buffer::BufferMemoryAccountSharedPtr account) PURE;
};

/**
Expand Down
6 changes: 6 additions & 0 deletions include/envoy/http/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <string>

#include "envoy/access_log/access_log.h"
#include "envoy/buffer/buffer.h"
#include "envoy/common/scope_tracker.h"
#include "envoy/event/dispatcher.h"
#include "envoy/grpc/status.h"
Expand Down Expand Up @@ -544,6 +545,11 @@ class StreamDecoderFilterCallbacks : public virtual StreamFilterCallbacks {
*/
virtual uint32_t decoderBufferLimit() PURE;

/**
* @return the account, if any, used by this stream.
*/
virtual Buffer::BufferMemoryAccountSharedPtr account() const PURE;

/**
* Takes a stream, and acts as if the headers are newly arrived.
* On success, this will result in a creating a new filter chain and likely
Expand Down
6 changes: 6 additions & 0 deletions include/envoy/router/router.h
Original file line number Diff line number Diff line change
Expand Up @@ -1327,6 +1327,12 @@ class GenericUpstream {
* @param reason supplies the reset reason.
*/
virtual void resetStream() PURE;

/**
* Sets the upstream to use the following account.
* @param the account to assign the generic upstream.
*/
virtual void setAccount(Buffer::BufferMemoryAccountSharedPtr account) PURE;
};

using GenericConnPoolPtr = std::unique_ptr<GenericConnPool>;
Expand Down
2 changes: 2 additions & 0 deletions source/common/buffer/buffer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ void OwnedImpl::bindAccount(BufferMemoryAccountSharedPtr account) {
account_ = std::move(account);
}

BufferMemoryAccountSharedPtr OwnedImpl::getAccountForTest() { return account_; }

void OwnedImpl::add(const void* data, uint64_t size) { addImpl(data, size); }

void OwnedImpl::addBufferFragment(BufferFragment& fragment) {
Expand Down
5 changes: 5 additions & 0 deletions source/common/buffer/buffer_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,11 @@ class OwnedImpl : public LibEventInstance {
*/
virtual void appendSliceForTest(absl::string_view data);

/**
* @return the BufferMemoryAccount bound to this buffer, if any.
*/
BufferMemoryAccountSharedPtr getAccountForTest();

// Does not implement watermarking.
// TODO(antoniovicente) Implement watermarks by merging the OwnedImpl and WatermarkBuffer
// implementations. Also, make high-watermark config a constructor argument.
Expand Down
5 changes: 2 additions & 3 deletions source/common/buffer/watermark_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ void WatermarkBuffer::appendSliceForTest(absl::string_view data) {
appendSliceForTest(data.data(), data.size());
}

void WatermarkBuffer::setWatermarks(uint32_t low_watermark, uint32_t high_watermark) {
ASSERT(low_watermark < high_watermark || (high_watermark == 0 && low_watermark == 0));
void WatermarkBuffer::setWatermarks(uint32_t high_watermark) {
uint32_t overflow_watermark_multiplier =
Runtime::getInteger("envoy.buffer.overflow_multiplier", 0);
if (overflow_watermark_multiplier > 0 &&
Expand All @@ -101,7 +100,7 @@ void WatermarkBuffer::setWatermarks(uint32_t low_watermark, uint32_t high_waterm
"high_watermark is overflowing. Disabling overflow watermark.");
overflow_watermark_multiplier = 0;
}
low_watermark_ = low_watermark;
low_watermark_ = high_watermark / 2;
high_watermark_ = high_watermark;
overflow_watermark_ = overflow_watermark_multiplier * high_watermark;
checkHighAndOverflowWatermarks();
Expand Down
5 changes: 2 additions & 3 deletions source/common/buffer/watermark_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,15 @@ class WatermarkBuffer : public OwnedImpl {
void appendSliceForTest(const void* data, uint64_t size) override;
void appendSliceForTest(absl::string_view data) override;

void setWatermarks(uint32_t watermark) override { setWatermarks(watermark / 2, watermark); }
void setWatermarks(uint32_t low_watermark, uint32_t high_watermark);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test/common/buffer/watermark_buffer_test.cc seems to be failing to build because the 2 argument version of setWatermarks is missing, please look into it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

void setWatermarks(uint32_t watermark) override;
uint32_t highWatermark() const override { return high_watermark_; }
// Returns true if the high watermark callbacks have been called more recently
// than the low watermark callbacks.
bool highWatermarkTriggered() const override { return above_high_watermark_called_; }

protected:
virtual void checkHighAndOverflowWatermarks();
void checkLowWatermark();
virtual void checkLowWatermark();

private:
void commit(uint64_t length, absl::Span<RawSlice> slices,
Expand Down
2 changes: 2 additions & 0 deletions source/common/http/async_client_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@ class AsyncStreamImpl : public AsyncClient::Stream,
Upstream::ClusterInfoConstSharedPtr clusterInfo() override { return parent_.cluster_; }
void clearRouteCache() override {}
uint64_t streamId() const override { return stream_id_; }
// TODO(kbaichoo): Implement this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that some users of async client are filters like the RBAC filter. We should plumb accounts to those eventually. Other users may involve config plane operations which are not associated with clients. Still it may be worth associating with an account owned by the config system, as a way to track memory usage by config plane components.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you change the TODO to something like: Plumb account from owning request filter.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the comment.

Buffer::BufferMemoryAccountSharedPtr account() const override { return nullptr; }
Tracing::Span& activeSpan() override { return active_span_; }
const Tracing::Config& tracingConfig() override { return tracing_config_; }
void continueDecoding() override { NOT_IMPLEMENTED_GCOVR_EXCL_LINE; }
Expand Down
10 changes: 6 additions & 4 deletions source/common/http/conn_manager_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ RequestDecoder& ConnectionManagerImpl::newStream(ResponseEncoder& response_encod
}

ENVOY_CONN_LOG(debug, "new stream", read_callbacks_->connection());
ActiveStreamPtr new_stream(new ActiveStream(*this, response_encoder.getStream().bufferLimit()));
ActiveStreamPtr new_stream(new ActiveStream(*this, response_encoder.getStream().bufferLimit(),
response_encoder.getStream().getAccount()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also say that the connection manager is the owner of the account and feed the account directly from the connection manager instead of asking the stream. I think we can remove getAccount() from the stream API if we do this change.

See related comment in http2/codec_impl.h setAccount

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See response to comment in http2/codec_impl.h

new_stream->state_.is_internally_created_ = is_internally_created;
new_stream->response_encoder_ = &response_encoder;
new_stream->response_encoder_->getStream().addCallbacks(*new_stream);
Expand Down Expand Up @@ -571,13 +572,14 @@ void ConnectionManagerImpl::RdsRouteConfigUpdateRequester::requestSrdsUpdate(
}

ConnectionManagerImpl::ActiveStream::ActiveStream(ConnectionManagerImpl& connection_manager,
uint32_t buffer_limit)
uint32_t buffer_limit,
Buffer::BufferMemoryAccountSharedPtr account)
: connection_manager_(connection_manager),
stream_id_(connection_manager.random_generator_.random()),
filter_manager_(*this, connection_manager_.read_callbacks_->connection().dispatcher(),
connection_manager_.read_callbacks_->connection(), stream_id_,
connection_manager_.config_.proxy100Continue(), buffer_limit,
connection_manager_.config_.filterFactory(),
std::move(account), connection_manager_.config_.proxy100Continue(),
buffer_limit, connection_manager_.config_.filterFactory(),
connection_manager_.config_.localReply(),
connection_manager_.codec_->protocol(), connection_manager_.timeSource(),
connection_manager_.read_callbacks_->connection().streamInfo().filterState(),
Expand Down
3 changes: 2 additions & 1 deletion source/common/http/conn_manager_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ class ConnectionManagerImpl : Logger::Loggable<Logger::Id::http>,
public Tracing::Config,
public ScopeTrackedObject,
public FilterManagerCallbacks {
ActiveStream(ConnectionManagerImpl& connection_manager, uint32_t buffer_limit);
ActiveStream(ConnectionManagerImpl& connection_manager, uint32_t buffer_limit,
Buffer::BufferMemoryAccountSharedPtr account);
void completeRequest();

const Network::Connection* connection();
Expand Down
4 changes: 4 additions & 0 deletions source/common/http/filter_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1558,5 +1558,9 @@ void ActiveStreamFilterBase::resetStream() { parent_.filter_manager_callbacks_.r

uint64_t ActiveStreamFilterBase::streamId() const { return parent_.streamId(); }

Buffer::BufferMemoryAccountSharedPtr ActiveStreamDecoderFilter::account() const {
return parent_.account();
}

} // namespace Http
} // namespace Envoy
13 changes: 9 additions & 4 deletions source/common/http/filter_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <memory>

#include "envoy/buffer/buffer.h"
#include "envoy/common/optref.h"
#include "envoy/extensions/filters/common/matcher/action/v3/skip_action.pb.h"
#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h"
Expand Down Expand Up @@ -275,6 +276,7 @@ struct ActiveStreamDecoderFilter : public ActiveStreamFilterBase,
void addUpstreamSocketOptions(const Network::Socket::OptionsSharedPtr& options) override;

Network::Socket::OptionsSharedPtr getUpstreamSocketOptions() const override;
Buffer::BufferMemoryAccountSharedPtr account() const override;

// Each decoder filter instance checks if the request passed to the filter is gRPC
// so that we can issue gRPC local responses to gRPC requests. Filter's decodeHeaders()
Expand Down Expand Up @@ -638,15 +640,16 @@ class FilterManager : public ScopeTrackedObject,
Logger::Loggable<Logger::Id::http> {
public:
FilterManager(FilterManagerCallbacks& filter_manager_callbacks, Event::Dispatcher& dispatcher,
const Network::Connection& connection, uint64_t stream_id, bool proxy_100_continue,
const Network::Connection& connection, uint64_t stream_id,
Buffer::BufferMemoryAccountSharedPtr account, bool proxy_100_continue,
uint32_t buffer_limit, FilterChainFactory& filter_chain_factory,
const LocalReply::LocalReply& local_reply, Http::Protocol protocol,
TimeSource& time_source, StreamInfo::FilterStateSharedPtr parent_filter_state,
StreamInfo::FilterState::LifeSpan filter_state_life_span)
: filter_manager_callbacks_(filter_manager_callbacks), dispatcher_(dispatcher),
connection_(connection), stream_id_(stream_id), proxy_100_continue_(proxy_100_continue),
buffer_limit_(buffer_limit), filter_chain_factory_(filter_chain_factory),
local_reply_(local_reply),
connection_(connection), stream_id_(stream_id), account_(std::move(account)),
proxy_100_continue_(proxy_100_continue), buffer_limit_(buffer_limit),
filter_chain_factory_(filter_chain_factory), local_reply_(local_reply),
stream_info_(protocol, time_source, connection.addressProviderSharedPtr(),
parent_filter_state, filter_state_life_span) {}
~FilterManager() override {
Expand Down Expand Up @@ -911,6 +914,7 @@ class FilterManager : public ScopeTrackedObject,
const Network::Connection* connection() const { return &connection_; }

uint64_t streamId() const { return stream_id_; }
Buffer::BufferMemoryAccountSharedPtr account() const { return account_; }

Buffer::InstancePtr& bufferedRequestData() { return buffered_request_data_; }

Expand Down Expand Up @@ -982,6 +986,7 @@ class FilterManager : public ScopeTrackedObject,
Event::Dispatcher& dispatcher_;
const Network::Connection& connection_;
const uint64_t stream_id_;
Buffer::BufferMemoryAccountSharedPtr account_;
const bool proxy_100_continue_;

std::list<ActiveStreamDecoderFilterPtr> decoder_filters_;
Expand Down
8 changes: 8 additions & 0 deletions source/common/http/http1/codec_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ class StreamEncoderImpl : public virtual StreamEncoder,
// connection, invoking any watermarks as necessary. There is no internal buffering that would
// require a flush timeout not already covered by other timeouts.
}
Buffer::BufferMemoryAccountSharedPtr getAccount() const override {
// TODO(kbaichoo): implement account tracking for H1.
return nullptr;
}

void setAccount(Buffer::BufferMemoryAccountSharedPtr) override {
// TODO(kbaichoo): implement account tracking for H1.
}

void setIsResponseToHeadRequest(bool value) { is_response_to_head_request_ = value; }
void setIsResponseToConnectRequest(bool value) { is_response_to_connect_request_ = value; }
Expand Down
52 changes: 36 additions & 16 deletions source/common/http/http2/codec_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,23 @@ template <typename T> static T* removeConst(const void* object) {
}

ConnectionImpl::StreamImpl::StreamImpl(ConnectionImpl& parent, uint32_t buffer_limit)
: parent_(parent), local_end_stream_sent_(false), remote_end_stream_(false),
data_deferred_(false), received_noninformational_headers_(false),
: parent_(parent),
pending_recv_data_(parent_.connection_.dispatcher().getWatermarkFactory().create(
[this]() -> void { this->pendingRecvBufferLowWatermark(); },
[this]() -> void { this->pendingRecvBufferHighWatermark(); },
[]() -> void { /* TODO(adisuissa): Handle overflow watermark */ })),
pending_send_data_(parent_.connection_.dispatcher().getWatermarkFactory().create(
[this]() -> void { this->pendingSendBufferLowWatermark(); },
[this]() -> void { this->pendingSendBufferHighWatermark(); },
[]() -> void { /* TODO(adisuissa): Handle overflow watermark */ })),
local_end_stream_sent_(false), remote_end_stream_(false), data_deferred_(false),
received_noninformational_headers_(false),
pending_receive_buffer_high_watermark_called_(false),
pending_send_buffer_high_watermark_called_(false), reset_due_to_messaging_error_(false) {
parent_.stats_.streams_active_.inc();
if (buffer_limit > 0) {
setWriteBufferWatermarks(buffer_limit / 2, buffer_limit);
pending_recv_data_->setWatermarks(buffer_limit);
pending_send_data_->setWatermarks(buffer_limit);
}
}

Expand All @@ -145,7 +155,7 @@ ConnectionImpl::StreamImpl::~StreamImpl() { ASSERT(stream_idle_timer_ == nullptr
void ConnectionImpl::StreamImpl::destroy() {
disarmStreamIdleTimer();
parent_.stats_.streams_active_.dec();
parent_.stats_.pending_send_bytes_.sub(pending_send_data_.length());
parent_.stats_.pending_send_bytes_.sub(pending_send_data_->length());
}

static void insertHeader(std::vector<nghttp2_nv>& headers, const HeaderEntry& header) {
Expand Down Expand Up @@ -253,7 +263,7 @@ void ConnectionImpl::ServerStreamImpl::encodeHeaders(const ResponseHeaderMap& he
void ConnectionImpl::StreamImpl::encodeTrailersBase(const HeaderMap& trailers) {
ASSERT(!local_end_stream_);
local_end_stream_ = true;
if (pending_send_data_.length() > 0) {
if (pending_send_data_->length() > 0) {
// In this case we want trailers to come after we release all pending body data that is
// waiting on window updates. We need to save the trailers so that we can emit them later.
// However, for empty trailers, we don't need to to save the trailers.
Expand Down Expand Up @@ -390,7 +400,9 @@ void ConnectionImpl::StreamImpl::submitTrailers(const HeaderMap& trailers) {

// Instead of submitting empty trailers, we send empty data instead.
Buffer::OwnedImpl empty_buffer;
encodeDataHelper(empty_buffer, /*end_stream=*/true, skip_encoding_empty_trailers);
encodeDataHelper(empty_buffer,
/*end_stream=*/
true, skip_encoding_empty_trailers);
return;
}

Expand All @@ -409,13 +421,13 @@ void ConnectionImpl::StreamImpl::submitMetadata(uint8_t flags) {
}

ssize_t ConnectionImpl::StreamImpl::onDataSourceRead(uint64_t length, uint32_t* data_flags) {
if (pending_send_data_.length() == 0 && !local_end_stream_) {
if (pending_send_data_->length() == 0 && !local_end_stream_) {
ASSERT(!data_deferred_);
data_deferred_ = true;
return NGHTTP2_ERR_DEFERRED;
} else {
*data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
if (local_end_stream_ && pending_send_data_.length() <= length) {
if (local_end_stream_ && pending_send_data_->length() <= length) {
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
if (pending_trailers_to_encode_) {
// We need to tell the library to not set end stream so that we can emit the trailers.
Expand All @@ -425,7 +437,7 @@ ssize_t ConnectionImpl::StreamImpl::onDataSourceRead(uint64_t length, uint32_t*
}
}

return std::min(length, pending_send_data_.length());
return std::min(length, pending_send_data_->length());
}
}

Expand All @@ -446,7 +458,7 @@ void ConnectionImpl::StreamImpl::onDataSourceSend(const uint8_t* framehd, size_t
}

parent_.stats_.pending_send_bytes_.sub(length);
output.move(pending_send_data_, length);
output.move(*pending_send_data_, length);
parent_.connection_.write(output, false);
}

Expand Down Expand Up @@ -491,7 +503,9 @@ void ConnectionImpl::StreamImpl::onPendingFlushTimer() {

void ConnectionImpl::StreamImpl::encodeData(Buffer::Instance& data, bool end_stream) {
ASSERT(!local_end_stream_);
encodeDataHelper(data, end_stream, /*skip_encoding_empty_trailers=*/false);
encodeDataHelper(data, end_stream,
/*skip_encoding_empty_trailers=*/
false);
}

void ConnectionImpl::StreamImpl::encodeDataHelper(Buffer::Instance& data, bool end_stream,
Expand All @@ -502,7 +516,7 @@ void ConnectionImpl::StreamImpl::encodeDataHelper(Buffer::Instance& data, bool e

local_end_stream_ = end_stream;
parent_.stats_.pending_send_bytes_.add(data.length());
pending_send_data_.move(data);
pending_send_data_->move(data);
if (data_deferred_) {
int rc = nghttp2_session_resume_data(parent_.session_, stream_id_);
ASSERT(rc == 0);
Expand All @@ -514,7 +528,7 @@ void ConnectionImpl::StreamImpl::encodeDataHelper(Buffer::Instance& data, bool e
// Intended to check through coverage that this error case is tested
return;
}
if (local_end_stream_ && pending_send_data_.length() > 0) {
if (local_end_stream_ && pending_send_data_->length() > 0) {
createPendingFlushTimer();
}
}
Expand Down Expand Up @@ -707,7 +721,7 @@ int ConnectionImpl::onData(int32_t stream_id, const uint8_t* data, size_t len) {
StreamImpl* stream = getStream(stream_id);
// If this results in buffering too much data, the watermark buffer will call
// pendingRecvBufferHighWatermark, resulting in ++read_disable_count_
stream->pending_recv_data_.add(data, len);
stream->pending_recv_data_->add(data, len);
// Update the window to the peer unless some consumer of this stream's data has hit a flow control
// limit and disabled reads on this stream
if (!stream->buffersOverrun()) {
Expand Down Expand Up @@ -862,10 +876,10 @@ Status ConnectionImpl::onFrameReceived(const nghttp2_frame* frame) {
// It's possible that we are waiting to send a deferred reset, so only raise data if local
// is not complete.
if (!stream->deferred_reset_) {
stream->decoder().decodeData(stream->pending_recv_data_, stream->remote_end_stream_);
stream->decoder().decodeData(*stream->pending_recv_data_, stream->remote_end_stream_);
}

stream->pending_recv_data_.drain(stream->pending_recv_data_.length());
stream->pending_recv_data_->drain(stream->pending_recv_data_->length());
break;
}
case NGHTTP2_RST_STREAM: {
Expand Down Expand Up @@ -1530,6 +1544,12 @@ void ConnectionImpl::ServerStreamImpl::dumpState(std::ostream& os, int indent_le
}
}

void ConnectionImpl::ClientStreamImpl::setAccount(Buffer::BufferMemoryAccountSharedPtr account) {
buffer_memory_account_ = account;
pending_recv_data_->bindAccount(buffer_memory_account_);
pending_send_data_->bindAccount(buffer_memory_account_);
}

ClientConnectionImpl::ClientConnectionImpl(
Network::Connection& connection, Http::ConnectionCallbacks& callbacks, CodecStats& stats,
Random::RandomGenerator& random_generator,
Expand Down
Loading