1
#include "source/common/http/http1/codec_impl.h"
2

            
3
#include <cstdint>
4
#include <memory>
5
#include <string>
6

            
7
#include "envoy/buffer/buffer.h"
8
#include "envoy/common/optref.h"
9
#include "envoy/http/codec.h"
10
#include "envoy/http/header_map.h"
11
#include "envoy/network/connection.h"
12

            
13
#include "source/common/common/cleanup.h"
14
#include "source/common/common/dump_state_utils.h"
15
#include "source/common/common/enum_to_int.h"
16
#include "source/common/common/scope_tracker.h"
17
#include "source/common/common/statusor.h"
18
#include "source/common/common/utility.h"
19
#include "source/common/grpc/common.h"
20
#include "source/common/http/exception.h"
21
#include "source/common/http/header_utility.h"
22
#include "source/common/http/headers.h"
23
#include "source/common/http/http1/balsa_parser.h"
24
#include "source/common/http/http1/header_formatter.h"
25
#include "source/common/http/http1/legacy_parser_impl.h"
26
#include "source/common/http/utility.h"
27
#include "source/common/runtime/runtime_features.h"
28

            
29
#include "absl/container/fixed_array.h"
30
#include "absl/strings/ascii.h"
31

            
32
namespace Envoy {
33
namespace Http {
34
namespace Http1 {
35
namespace {
36

            
37
// Changes or additions to details should be reflected in
38
// docs/root/configuration/http/http_conn_man/response_code_details.rst
39
struct Http1ResponseCodeDetailValues {
40
  const absl::string_view TooManyHeaders = "http1.too_many_headers";
41
  const absl::string_view HeadersTooLarge = "http1.headers_too_large";
42
  const absl::string_view HttpCodecError = "http1.codec_error";
43
  const absl::string_view InvalidCharacters = "http1.invalid_characters";
44
  const absl::string_view ConnectionHeaderSanitization = "http1.connection_header_rejected";
45
  const absl::string_view InvalidUrl = "http1.invalid_url";
46
  const absl::string_view InvalidTransferEncoding = "http1.invalid_transfer_encoding";
47
  const absl::string_view BodyDisallowed = "http1.body_disallowed";
48
  const absl::string_view TransferEncodingNotAllowed = "http1.transfer_encoding_not_allowed";
49
  const absl::string_view ContentLengthNotAllowed = "http1.content_length_not_allowed";
50
  const absl::string_view InvalidUnderscore = "http1.unexpected_underscore";
51
  const absl::string_view ChunkedContentLength = "http1.content_length_and_chunked_not_allowed";
52
  const absl::string_view HttpsInPlaintext = "http1.https_url_on_plaintext_connection";
53
  const absl::string_view InvalidScheme = "http1.invalid_scheme";
54
};
55

            
56
struct Http1HeaderTypesValues {
57
  const absl::string_view Headers = "headers";
58
  const absl::string_view Trailers = "trailers";
59
};
60

            
61
// Pipelining is generally not well supported on the internet and has a series of dangerous
62
// overflow bugs. As such Envoy disabled it.
63
static constexpr uint32_t kMaxOutboundResponses = 2;
64

            
65
using Http1ResponseCodeDetails = ConstSingleton<Http1ResponseCodeDetailValues>;
66
using Http1HeaderTypes = ConstSingleton<Http1HeaderTypesValues>;
67

            
68
3
const StringUtil::CaseUnorderedSet& caseUnorderedSetContainingUpgrade() {
69
3
  CONSTRUCT_ON_FIRST_USE(StringUtil::CaseUnorderedSet,
70
3
                         Http::Headers::get().ConnectionValues.Upgrade);
71
3
}
72

            
73
3
const StringUtil::CaseUnorderedSet& caseUnorderedSetContainingUpgradeAndHttp2Settings() {
74
3
  CONSTRUCT_ON_FIRST_USE(StringUtil::CaseUnorderedSet,
75
3
                         Http::Headers::get().ConnectionValues.Upgrade,
76
3
                         Http::Headers::get().ConnectionValues.Http2Settings);
77
3
}
78

            
79
69333
HeaderKeyFormatterConstPtr encodeOnlyFormatterFromSettings(const Http::Http1Settings& settings) {
80
69333
  if (settings.header_key_format_ == Http1Settings::HeaderKeyFormat::ProperCase) {
81
4
    return std::make_unique<ProperCaseHeaderKeyFormatter>();
82
4
  }
83

            
84
69329
  return nullptr;
85
69333
}
86

            
87
84276
StatefulHeaderKeyFormatterPtr statefulFormatterFromSettings(const Http::Http1Settings& settings) {
88
84276
  if (settings.header_key_format_ == Http1Settings::HeaderKeyFormat::StatefulFormatter) {
89
6
    return settings.stateful_header_key_formatter_->create();
90
6
  }
91
84270
  return nullptr;
92
84276
}
93

            
94
constexpr size_t CRLF_SIZE = 2;
95

            
96
} // namespace
97

            
98
static constexpr absl::string_view CRLF = "\r\n";
99
// Last chunk as defined here https://tools.ietf.org/html/rfc7230#section-4.1
100
static constexpr absl::string_view LAST_CHUNK = "0\r\n";
101

            
102
static constexpr absl::string_view SPACE = " ";
103
static constexpr absl::string_view COLON_SPACE = ": ";
104

            
105
StreamEncoderImpl::StreamEncoderImpl(ConnectionImpl& connection,
106
                                     StreamInfo::BytesMeterSharedPtr&& bytes_meter)
107
85018
    : connection_(connection), disable_chunk_encoding_(false), chunk_encoding_(true),
108
85018
      connect_request_(false), is_tcp_tunneling_(false), is_response_to_head_request_(false),
109
85018
      is_response_to_connect_request_(false), bytes_meter_(std::move(bytes_meter)) {
110
85018
  if (!bytes_meter_) {
111
41966
    bytes_meter_ = std::make_shared<StreamInfo::BytesMeter>();
112
41966
  }
113
85018
  if (connection_.connection().aboveHighWatermark()) {
114
4
    runHighWatermarkCallbacks();
115
4
  }
116
85018
}
117

            
118
377859
void StreamEncoderImpl::encodeHeader(absl::string_view key, absl::string_view value) {
119
377859
  ASSERT(!key.empty());
120

            
121
377859
  const uint64_t header_size = connection_.buffer().addFragments({key, COLON_SPACE, value, CRLF});
122

            
123
  // There is no header field compression in HTTP/1.1, so the wire representation is the same as the
124
  // decompressed representation.
125
377859
  bytes_meter_->addHeaderBytesSent(header_size);
126
377859
  bytes_meter_->addDecompressedHeaderBytesSent(header_size);
127
377859
}
128

            
129
void StreamEncoderImpl::encodeFormattedHeader(absl::string_view key, absl::string_view value,
130
377859
                                              HeaderKeyFormatterOptConstRef formatter) {
131
377859
  if (formatter.has_value()) {
132
62
    encodeHeader(formatter->format(key), value);
133
377835
  } else {
134
377797
    encodeHeader(key, value);
135
377797
  }
136
377859
}
137

            
138
130
void ResponseEncoderImpl::encode1xxHeaders(const ResponseHeaderMap& headers) {
139
130
  ASSERT(HeaderUtility::isSpecial1xx(headers));
140
130
  encodeHeaders(headers, false);
141
  // Don't consider 100-continue responses as the actual response.
142
130
  started_response_ = false;
143
130
}
144

            
145
void StreamEncoderImpl::encodeHeadersBase(const RequestOrResponseHeaderMap& headers,
146
                                          absl::optional<uint64_t> status, bool end_stream,
147
84498
                                          bool bodiless_request) {
148
84498
  HeaderKeyFormatterOptConstRef formatter(headers.formatter());
149
84498
  if (!formatter.has_value()) {
150
84489
    formatter = connection_.formatter();
151
84489
  }
152

            
153
84498
  const Http::HeaderValues& header_values = Http::Headers::get();
154
84498
  bool saw_content_length = false;
155
84498
  headers.iterate(
156
459709
      [this, &header_values, formatter](const HeaderEntry& header) -> HeaderMap::Iterate {
157
459709
        absl::string_view key_to_use = header.key().getStringView();
158
459709
        uint32_t key_size_to_use = header.key().size();
159
        // Translate :authority -> host so that upper layers do not need to deal with this.
160
459709
        if (key_size_to_use > 1 && key_to_use[0] == ':' && key_to_use[1] == 'a') {
161
40928
          key_to_use = absl::string_view(header_values.HostLegacy.get());
162
40928
          key_size_to_use = header_values.HostLegacy.get().size();
163
40928
        }
164

            
165
        // Skip all headers starting with ':' that make it here.
166
459709
        if (key_to_use[0] == ':') {
167
167506
          return HeaderMap::Iterate::Continue;
168
167506
        }
169

            
170
292203
        encodeFormattedHeader(key_to_use, header.value().getStringView(), formatter);
171

            
172
292203
        return HeaderMap::Iterate::Continue;
173
459709
      });
174

            
175
84498
  if (headers.ContentLength()) {
176
4955
    saw_content_length = true;
177
4955
  }
178

            
179
84498
  ASSERT(!headers.TransferEncoding());
180

            
181
  // Assume we are chunk encoding unless we are passed a content length or this is a header only
182
  // response. Upper layers generally should strip transfer-encoding since it only applies to
183
  // HTTP/1.1. The codec will infer it based on the type of response.
184
  // for streaming (e.g. SSE stream sent to hystrix dashboard), we do not want
185
  // chunk transfer encoding but we don't have a content-length so disable_chunk_encoding_ is
186
  // consulted before enabling chunk encoding.
187
  //
188
  // Note that for HEAD requests Envoy does best-effort guessing when there is no
189
  // content-length. If a client makes a HEAD request for an upstream resource
190
  // with no bytes but the upstream response doesn't include "Content-length: 0",
191
  // Envoy will incorrectly assume a subsequent response to GET will be chunk encoded.
192
84498
  if (saw_content_length || disable_chunk_encoding_) {
193
5358
    chunk_encoding_ = false;
194
79420
  } else {
195
79140
    if (status && (*status < 200 || *status == 204)) {
196
      // For 1xx and 204 responses, do not send the chunked encoding header or enable chunked
197
      // encoding: https://tools.ietf.org/html/rfc7230#section-3.3.1
198
212
      chunk_encoding_ = false;
199
78957
    } else if (status && *status == 304) {
200
      // For 304 response, since it should never have a body, we should not need to chunk_encode at
201
      // all.
202
48
      chunk_encoding_ = false;
203
78880
    } else if (end_stream && !is_response_to_head_request_) {
204
      // If this is a headers-only stream, append an explicit "Content-Length: 0" unless it's a
205
      // response to a HEAD request.
206
      // For 204s and 1xx where content length is disallowed, don't append the content length but
207
      // also don't chunk encode.
208
      // Also do not add content length for requests which should not have a
209
      // body, per https://tools.ietf.org/html/rfc7230#section-3.3.2
210
58022
      if (!status || (*status >= 200 && *status != 204)) {
211
58022
        if (!bodiless_request) {
212
23360
          encodeFormattedHeader(header_values.ContentLength.get(), "0", formatter);
213
23360
        }
214
58022
      }
215
58022
      chunk_encoding_ = false;
216
65479
    } else if (connection_.protocol() == Protocol::Http10) {
217
10
      chunk_encoding_ = false;
218
20848
    } else {
219
      // For responses to connect requests, do not send the chunked encoding header:
220
      // https://tools.ietf.org/html/rfc7231#section-4.3.6.
221
20848
      if (!is_response_to_connect_request_) {
222
20622
        encodeFormattedHeader(header_values.TransferEncoding.get(),
223
20622
                              header_values.TransferEncodingValues.Chunked, formatter);
224
20622
      }
225
      // We do not apply chunk encoding for HTTP upgrades, including CONNECT style upgrades.
226
      // If there is a body in a response on the upgrade path, the chunks will be
227
      // passed through via maybeDirectDispatch so we need to avoid appending
228
      // extra chunk boundaries.
229
      //
230
      // When sending a response to a HEAD request Envoy may send an informational
231
      // "Transfer-Encoding: chunked" header, but should not send a chunk encoded body.
232
20848
      chunk_encoding_ = !Utility::isUpgrade(headers) && !is_response_to_head_request_ &&
233
20848
                        !is_response_to_connect_request_;
234
20848
    }
235
79140
  }
236

            
237
84498
  connection_.buffer().add(CRLF);
238

            
239
84498
  if (end_stream) {
240
60116
    endEncode();
241
68087
  } else {
242
24382
    flushOutput();
243
24382
  }
244
84498
}
245

            
246
140832
void StreamEncoderImpl::encodeData(Buffer::Instance& data, bool end_stream) {
247
  // end_stream may be indicated with a zero length data buffer. If that is the case, so not
248
  // actually write the zero length buffer out.
249
140832
  if (data.length() > 0) {
250
131309
    if (chunk_encoding_) {
251
74215
      std::string chunk_header = absl::StrCat(absl::Hex(data.length()), CRLF);
252
74215
      connection_.buffer().add(std::move(chunk_header));
253
74215
    }
254

            
255
131309
    connection_.buffer().move(data);
256

            
257
131309
    if (chunk_encoding_) {
258
74215
      connection_.buffer().add(CRLF);
259
74215
    }
260
131309
  }
261

            
262
140832
  if (end_stream) {
263
17540
    endEncode();
264
129577
  } else {
265
123292
    flushOutput();
266
123292
  }
267
140832
}
268

            
269
230413
void StreamEncoderImpl::flushOutput(bool end_encode) {
270
230413
  auto encoded_bytes = connection_.flushOutput(end_encode);
271
230413
  bytes_meter_->addWireBytesSent(encoded_bytes);
272
230413
}
273

            
274
5083
void StreamEncoderImpl::encodeTrailersBase(const HeaderMap& trailers) {
275
5083
  if (!connection_.enableTrailers()) {
276
120
    return endEncode();
277
120
  }
278
  // Trailers only matter if it is a chunk transfer encoding
279
  // https://tools.ietf.org/html/rfc7230#section-4.4
280
4963
  if (chunk_encoding_) {
281
    // Finalize the body
282
4801
    connection_.buffer().add(LAST_CHUNK);
283

            
284
    // TODO(mattklein123): Wire up the formatter if someone actually asks for this (very unlikely).
285
46064
    trailers.iterate([this](const HeaderEntry& header) -> HeaderMap::Iterate {
286
41674
      encodeFormattedHeader(header.key().getStringView(), header.value().getStringView(),
287
41674
                            HeaderKeyFormatterOptConstRef());
288
41674
      return HeaderMap::Iterate::Continue;
289
41674
    });
290

            
291
4801
    connection_.buffer().add(CRLF);
292
4801
  }
293

            
294
4963
  flushOutput();
295
4963
  notifyEncodeComplete();
296
4963
}
297

            
298
323
void StreamEncoderImpl::encodeMetadata(const MetadataMapVector&) {
299
323
  connection_.stats().metadata_not_supported_error_.inc();
300
323
}
301

            
302
77776
void StreamEncoderImpl::endEncode() {
303
77776
  if (chunk_encoding_) {
304
14765
    connection_.buffer().addFragments({LAST_CHUNK, CRLF});
305
14765
  }
306

            
307
77776
  flushOutput(true);
308
77776
  notifyEncodeComplete();
309
  // With CONNECT or TCP tunneling, half-closing the connection is used to signal end stream so
310
  // don't delay that signal.
311
77776
  if (connect_request_ || is_tcp_tunneling_) {
312
160
    connection_.connection().close(
313
160
        Network::ConnectionCloseType::FlushWrite,
314
160
        StreamInfo::LocalCloseReasons::get().CloseForConnectRequestOrTcpTunneling);
315
160
  }
316
77776
}
317

            
318
82738
void StreamEncoderImpl::notifyEncodeComplete() {
319
82738
  if (codec_callbacks_) {
320
16143
    codec_callbacks_->onCodecEncodeComplete();
321
16143
  }
322
82738
  connection_.onEncodeComplete();
323
82738
}
324

            
325
37097
void ServerConnectionImpl::maybeAddSentinelBufferFragment(Buffer::Instance& output_buffer) {
326
  // It's messy and complicated to try to tag the final write of an HTTP response for response
327
  // tracking for flood protection. Instead, write an empty buffer fragment after the response,
328
  // to allow for tracking.
329
  // When the response is written out, the fragment will be deleted and the counter will be updated
330
  // by ServerConnectionImpl::releaseOutboundResponse()
331
37097
  auto fragment =
332
37097
      Buffer::OwnedBufferFragmentImpl::create(absl::string_view("", 0), response_buffer_releasor_);
333
37097
  output_buffer.addBufferFragment(*fragment.release());
334
37097
  ASSERT(outbound_responses_ < kMaxOutboundResponses);
335
37097
  outbound_responses_++;
336
37097
}
337

            
338
43054
Status ServerConnectionImpl::doFloodProtectionChecks() const {
339
43054
  ASSERT(dispatching_);
340
  // Before processing another request, make sure that we are below the response flood protection
341
  // threshold.
342
43054
  if (outbound_responses_ >= kMaxOutboundResponses) {
343
3
    ENVOY_CONN_LOG(trace, "error accepting request: too many pending responses queued",
344
3
                   connection_);
345
3
    stats_.response_flood_.inc();
346
3
    return bufferFloodError("Too many responses queued.");
347
3
  }
348
43051
  return okStatus();
349
43054
}
350

            
351
230413
uint64_t ConnectionImpl::flushOutput(bool end_encode) {
352
230413
  if (end_encode) {
353
    // If this is an HTTP response in ServerConnectionImpl, track outbound responses for flood
354
    // protection
355
77776
    maybeAddSentinelBufferFragment(*output_buffer_);
356
77776
  }
357
230413
  const uint64_t bytes_encoded = output_buffer_->length();
358
230413
  connection().write(*output_buffer_, false);
359
230413
  ASSERT(0UL == output_buffer_->length());
360
230413
  return bytes_encoded;
361
230413
}
362

            
363
CodecEventCallbacks*
364
32779
StreamEncoderImpl::registerCodecEventCallbacks(CodecEventCallbacks* codec_callbacks) {
365
32779
  std::swap(codec_callbacks, codec_callbacks_);
366
32779
  return codec_callbacks;
367
32779
}
368

            
369
3290
void StreamEncoderImpl::resetStream(StreamResetReason reason) {
370
3290
  connection_.onResetStreamBase(reason);
371
3290
}
372

            
373
1863
void ResponseEncoderImpl::resetStream(StreamResetReason reason) {
374
  // Clear the downstream on the account since we're resetting the downstream.
375
1863
  if (buffer_memory_account_) {
376
2
    buffer_memory_account_->clearDownstream();
377
2
  }
378

            
379
  // For H1, we use idleTimeouts to cancel streams unless there was an
380
  // explicit protocol error prior to sending a response to the downstream
381
  // in which case we send a local reply.
382
  // TODO(kbaichoo): If we want snappier resets of H1 streams we can
383
  //  1) Send local reply if no response data sent yet
384
  //  2) Invoke the idle timeout sooner to close underlying connection
385
1863
  StreamEncoderImpl::resetStream(reason);
386
1863
}
387

            
388
24456
void StreamEncoderImpl::readDisable(bool disable) {
389
24456
  if (disable) {
390
12228
    ++read_disable_calls_;
391
12228
  } else {
392
12228
    ASSERT(read_disable_calls_ != 0);
393
12228
    if (read_disable_calls_ != 0) {
394
12228
      --read_disable_calls_;
395
12228
    }
396
12228
  }
397
24456
  connection_.readDisable(disable);
398
24456
}
399

            
400
16462
uint32_t StreamEncoderImpl::bufferLimit() const { return connection_.bufferLimit(); }
401

            
402
25447
const Network::ConnectionInfoProvider& StreamEncoderImpl::connectionInfoProvider() {
403
25447
  return connection_.connection().connectionInfoProvider();
404
25447
}
405

            
406
static constexpr absl::string_view RESPONSE_PREFIX = "HTTP/1.1 ";
407
static constexpr absl::string_view HTTP_10_RESPONSE_PREFIX = "HTTP/1.0 ";
408

            
409
42564
void ResponseEncoderImpl::encodeHeaders(const ResponseHeaderMap& headers, bool end_stream) {
410
42564
  started_response_ = true;
411

            
412
  // The contract is that client codecs must ensure that :status is present and valid.
413
42564
  ASSERT(headers.Status() != nullptr);
414
42564
  uint64_t numeric_status = Utility::getResponseStatus(headers);
415

            
416
42564
  absl::string_view response_prefix;
417
42564
  if (connection_.protocol() == Protocol::Http10 && connection_.supportsHttp10()) {
418
9
    response_prefix = HTTP_10_RESPONSE_PREFIX;
419
42555
  } else {
420
42555
    response_prefix = RESPONSE_PREFIX;
421
42555
  }
422

            
423
42564
  StatefulHeaderKeyFormatterOptConstRef formatter(headers.formatter());
424

            
425
42564
  absl::string_view reason_phrase;
426
42564
  if (formatter.has_value() && !formatter->getReasonPhrase().empty()) {
427
4
    reason_phrase = formatter->getReasonPhrase();
428
42560
  } else {
429
42560
    const char* status_string = CodeUtility::toString(static_cast<Code>(numeric_status));
430
42560
    uint32_t status_string_len = strlen(status_string);
431
42560
    reason_phrase = {status_string, status_string_len};
432
42560
  }
433

            
434
42564
  connection_.buffer().addFragments(
435
42564
      {response_prefix, absl::StrCat(numeric_status), SPACE, reason_phrase, CRLF});
436

            
437
42564
  if (numeric_status >= 300) {
438
    // Don't do special CONNECT logic if the CONNECT was rejected.
439
5791
    is_response_to_connect_request_ = false;
440
5791
  }
441

            
442
42564
  encodeHeadersBase(headers, absl::make_optional<uint64_t>(numeric_status), end_stream, false);
443
42564
}
444

            
445
static constexpr absl::string_view REQUEST_POSTFIX = " HTTP/1.1\r\n";
446

            
447
41956
Status RequestEncoderImpl::encodeHeaders(const RequestHeaderMap& headers, bool end_stream) {
448
41956
#ifndef ENVOY_ENABLE_UHV
449
  // Headers are now validated by UHV before encoding by the codec. Two checks below are not needed
450
  // when UHV is enabled.
451
  //
452
  // Required headers must be present. This can only happen by some erroneous processing after the
453
  // downstream codecs decode.
454
41956
  RETURN_IF_ERROR(HeaderUtility::checkRequiredRequestHeaders(headers));
455
  // Verify that a filter hasn't added an invalid header key or value.
456
41942
  RETURN_IF_ERROR(HeaderUtility::checkValidRequestHeaders(headers));
457
41936
#endif
458

            
459
41936
  const HeaderEntry* method = headers.Method();
460
41936
  const HeaderEntry* path = headers.Path();
461
41936
  const HeaderEntry* host = headers.Host();
462
41936
  bool is_connect = HeaderUtility::isConnect(headers);
463
41936
  const Http::HeaderValues& header_values = Http::Headers::get();
464

            
465
41936
  if (method->value() == header_values.MethodValues.Head) {
466
158
    head_request_ = true;
467
41778
  } else if (method->value() == header_values.MethodValues.Connect) {
468
329
    disableChunkEncoding();
469
329
    connection_.connection().enableHalfClose(true);
470
329
    connect_request_ = true;
471
329
  }
472
41936
  if (Utility::isUpgrade(headers)) {
473
125
    upgrade_request_ = true;
474
    // If the flag is flipped from true to false all outstanding upgrade requests that are waiting
475
    // for upstream connections will become invalid, as Envoy will add chunk encoding to the
476
    // protocol stream. This will likely cause the server to disconnect, since it will be unable to
477
    // parse the protocol.
478
125
    disableChunkEncoding();
479
125
  }
480

            
481
41936
  if (connection_.sendFullyQualifiedUrl() && !is_connect) {
482
5
    const HeaderEntry* scheme = headers.Scheme();
483
5
    if (!scheme) {
484
1
      return absl::InvalidArgumentError(
485
1
          absl::StrCat("missing required header: ", Envoy::Http::Headers::get().Scheme.get()));
486
1
    }
487
4
    if (!host) {
488
1
      return absl::InvalidArgumentError(
489
1
          absl::StrCat("missing required header: ", Envoy::Http::Headers::get().Host.get()));
490
1
    }
491
3
    ASSERT(path);
492
3
    ASSERT(host);
493

            
494
3
    std::string url = absl::StrCat(scheme->value().getStringView(), "://",
495
3
                                   host->value().getStringView(), path->value().getStringView());
496
3
    ENVOY_CONN_LOG(trace, "Sending fully qualified URL: {}", connection_.connection(), url);
497
3
    connection_.buffer().addFragments(
498
3
        {method->value().getStringView(), SPACE, url, REQUEST_POSTFIX});
499
41931
  } else {
500
41931
    absl::string_view host_or_path_view;
501
41931
    if (is_connect) {
502
329
      host_or_path_view = host->value().getStringView();
503
41893
    } else {
504
41602
      host_or_path_view = path->value().getStringView();
505
41602
    }
506

            
507
41931
    connection_.buffer().addFragments(
508
41931
        {method->value().getStringView(), SPACE, host_or_path_view, REQUEST_POSTFIX});
509
41931
  }
510

            
511
41934
  encodeHeadersBase(headers, absl::nullopt, end_stream,
512
41934
                    HeaderUtility::requestShouldHaveNoBody(headers));
513
41934
  return okStatus();
514
41936
}
515

            
516
919319
CallbackResult ConnectionImpl::setAndCheckCallbackStatus(Status&& status) {
517
919319
  ASSERT(codec_status_.ok());
518
919319
  codec_status_ = std::move(status);
519
919319
  return codec_status_.ok() ? CallbackResult::Success : CallbackResult::Error;
520
919319
}
521

            
522
CallbackResult
523
164465
ConnectionImpl::setAndCheckCallbackStatusOr(Envoy::StatusOr<CallbackResult>&& statusor) {
524
164465
  ASSERT(codec_status_.ok());
525
164465
  if (statusor.ok()) {
526
164409
    return statusor.value();
527
164409
  } else {
528
56
    codec_status_ = std::move(statusor.status());
529
56
    return CallbackResult::Error;
530
56
  }
531
164465
}
532

            
533
ConnectionImpl::ConnectionImpl(Network::Connection& connection, CodecStats& stats,
534
                               const Http1Settings& settings, MessageType type,
535
                               uint32_t max_headers_kb, const uint32_t max_headers_count)
536
69333
    : connection_(connection), stats_(stats), codec_settings_(settings),
537
69333
      encode_only_header_key_formatter_(encodeOnlyFormatterFromSettings(settings)),
538
69333
      processing_trailers_(false), handling_upgrade_(false), reset_stream_called_(false),
539
69333
      deferred_end_stream_headers_(false), dispatching_(false), max_headers_kb_(max_headers_kb),
540
69333
      max_headers_count_(max_headers_count) {
541
69333
  parser_ = std::make_unique<BalsaParser>(type, this, max_headers_kb_ * 1024, enableTrailers(),
542
69333
                                          codec_settings_.allow_custom_methods_);
543
69333
}
544

            
545
377496
Status ConnectionImpl::completeCurrentHeader() {
546
377496
  ASSERT(dispatching_);
547
377496
  ENVOY_CONN_LOG(trace, "completed header: key={} value={}", connection_,
548
377496
                 current_header_field_.getStringView(), current_header_value_.getStringView());
549
377496
  auto& headers_or_trailers = headersOrTrailers();
550

            
551
  // Account for ":" and "\r\n" bytes between the header key value pair.
552
377496
  getBytesMeter().addHeaderBytesReceived(CRLF_SIZE + 1);
553

            
554
  // TODO(10646): Switch to use HeaderUtility::checkHeaderNameForUnderscores().
555
377496
  RETURN_IF_ERROR(checkHeaderNameForUnderscores());
556
377491
  if (!current_header_field_.empty()) {
557
    // Strip trailing whitespace of the current header value if any. Leading whitespace was trimmed
558
    // in ConnectionImpl::onHeaderValue. http_parser does not strip leading or trailing whitespace
559
    // as the spec requires: https://tools.ietf.org/html/rfc7230#section-3.2.4
560
376064
    current_header_value_.rtrim();
561

            
562
    // If there is a stateful formatter installed, remember the original header key before
563
    // converting to lower case.
564
376064
    auto formatter = headers_or_trailers.formatter();
565
376064
    if (formatter.has_value()) {
566
10
      formatter->processKey(current_header_field_.getStringView());
567
10
    }
568
4055313
    current_header_field_.inlineTransform([](char c) { return absl::ascii_tolower(c); });
569

            
570
376064
    headers_or_trailers.addViaMove(std::move(current_header_field_),
571
376064
                                   std::move(current_header_value_));
572
376064
  }
573

            
574
  // Check if the number of headers exceeds the limit.
575
377491
  if (headers_or_trailers.size() > max_headers_count_) {
576
8
    error_code_ = Http::Code::RequestHeaderFieldsTooLarge;
577
8
    RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().TooManyHeaders));
578
8
    const absl::string_view header_type =
579
8
        processing_trailers_ ? Http1HeaderTypes::get().Trailers : Http1HeaderTypes::get().Headers;
580
8
    return codecProtocolError(
581
8
        absl::StrCat("http/1.1 protocol error: ", header_type, " count exceeds limit"));
582
8
  }
583

            
584
377483
  header_parsing_state_ = HeaderParsingState::Field;
585
377483
  ASSERT(current_header_field_.empty());
586
377483
  ASSERT(current_header_value_.empty());
587
377483
  return okStatus();
588
377491
}
589

            
590
84276
Status ConnectionImpl::onMessageBeginImpl() {
591
84276
  ENVOY_CONN_LOG(trace, "message begin", connection_);
592
  // Make sure that if HTTP/1.0 and HTTP/1.1 requests share a connection Envoy correctly sets
593
  // protocol for each request. Envoy defaults to 1.1 but sets the protocol to 1.0 where applicable
594
  // in onHeadersCompleteBase
595
84276
  protocol_ = Protocol::Http11;
596
84276
  processing_trailers_ = false;
597
84276
  header_parsing_state_ = HeaderParsingState::Field;
598
84276
  allocHeaders(statefulFormatterFromSettings(codec_settings_));
599
84276
  return onMessageBeginBase();
600
84276
}
601

            
602
793833
uint32_t ConnectionImpl::getHeadersSize() {
603
793833
  return current_header_field_.size() + current_header_value_.size() +
604
793833
         headersOrTrailers().byteSize();
605
793833
}
606

            
607
793833
Status ConnectionImpl::checkMaxHeadersSize() {
608
793833
  const uint32_t total = getHeadersSize();
609
793833
  if (total > (max_headers_kb_ * 1024)) {
610
    const absl::string_view header_type =
611
        processing_trailers_ ? Http1HeaderTypes::get().Trailers : Http1HeaderTypes::get().Headers;
612
    error_code_ = Http::Code::RequestHeaderFieldsTooLarge;
613
    RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().HeadersTooLarge));
614
    return codecProtocolError(
615
        absl::StrCat("http/1.1 protocol error: ", header_type, " size exceeds limit"));
616
  }
617
793833
  return okStatus();
618
793833
}
619

            
620
296229
bool ConnectionImpl::maybeDirectDispatch(Buffer::Instance& data) {
621
296229
  if (!handling_upgrade_) {
622
    // Only direct dispatch for Upgrade requests.
623
285071
    return false;
624
285071
  }
625

            
626
11158
  ENVOY_CONN_LOG(trace, "direct-dispatched {} bytes", connection_, data.length());
627
11158
  onBody(data);
628
11158
  data.drain(data.length());
629
11158
  return true;
630
296229
}
631

            
632
154138
void ConnectionImpl::onDispatch(const Buffer::Instance& data) {
633
154138
  getBytesMeter().addWireBytesReceived(data.length());
634
154138
}
635

            
636
54257
Http::Status ClientConnectionImpl::dispatch(Buffer::Instance& data) {
637
54257
  Http::Status status = ConnectionImpl::dispatch(data);
638
54257
  if (status.ok() && data.length() > 0) {
639
    // The HTTP/1.1 codec pauses dispatch after a single response is complete. Extraneous data
640
    // after a response is complete indicates an error.
641
4
    return codecProtocolError("http/1.1 protocol error: extraneous data after response complete");
642
4
  }
643
54253
  return status;
644
54257
}
645

            
646
154138
Http::Status ConnectionImpl::dispatch(Buffer::Instance& data) {
647
  // Add self to the Dispatcher's tracked object stack.
648
154138
  ScopeTrackerScopeState scope(this, connection_.dispatcher());
649
154138
  ENVOY_CONN_LOG(trace, "parsing {} bytes", connection_, data.length());
650
  // Make sure that dispatching_ is set to false after dispatching, even when
651
  // http_parser exits early with an error code.
652
154138
  Cleanup cleanup([this]() { dispatching_ = false; });
653
154138
  ASSERT(!dispatching_);
654
154138
  ASSERT(codec_status_.ok());
655
154138
  ASSERT(buffered_body_.length() == 0);
656

            
657
154138
  dispatching_ = true;
658
154138
  onDispatch(data);
659
154138
  if (maybeDirectDispatch(data)) {
660
10397
    return Http::okStatus();
661
10397
  }
662

            
663
  // Always resume before dispatch.
664
143741
  parser_->resume();
665

            
666
143741
  ssize_t total_parsed = 0;
667
143741
  if (data.length() > 0) {
668
143536
    current_dispatching_buffer_ = &data;
669
293030
    while (data.length() > 0) {
670
232944
      auto slice = data.frontSlice();
671
232944
      dispatching_slice_already_drained_ = false;
672
232944
      auto statusor_parsed = dispatchSlice(static_cast<const char*>(slice.mem_), slice.len_);
673
232944
      if (!statusor_parsed.ok()) {
674
1593
        return statusor_parsed.status();
675
1593
      }
676
231351
      if (!dispatching_slice_already_drained_) {
677
143271
        ASSERT(statusor_parsed.value() <= slice.len_);
678
143271
        data.drain(statusor_parsed.value());
679
143271
      }
680

            
681
231351
      total_parsed += statusor_parsed.value();
682
231351
      if (parser_->getStatus() != ParserStatus::Ok) {
683
        // Parse errors trigger an exception in dispatchSlice so we are guaranteed to be paused at
684
        // this point.
685
81857
        ASSERT(parser_->getStatus() == ParserStatus::Paused);
686
81857
        break;
687
81857
      }
688
231351
    }
689
141943
    current_dispatching_buffer_ = nullptr;
690
141943
    dispatchBufferedBody();
691
141949
  } else {
692
205
    auto result = dispatchSlice(nullptr, 0);
693
205
    if (!result.ok()) {
694
57
      return result.status();
695
57
    }
696
205
  }
697
142091
  ASSERT(buffered_body_.length() == 0);
698

            
699
142091
  ENVOY_CONN_LOG(trace, "parsed {} bytes", connection_, total_parsed);
700

            
701
  // If an upgrade has been handled and there is body data or early upgrade
702
  // payload to send on, send it on.
703
142091
  maybeDirectDispatch(data);
704
142091
  return Http::okStatus();
705
143741
}
706

            
707
233148
Envoy::StatusOr<size_t> ConnectionImpl::dispatchSlice(const char* slice, size_t len) {
708
233148
  ASSERT(codec_status_.ok() && dispatching_);
709
233148
  const size_t nread = parser_->execute(slice, len);
710
233148
  if (!codec_status_.ok()) {
711
64
    return codec_status_;
712
64
  }
713

            
714
233084
  const ParserStatus status = parser_->getStatus();
715
233084
  if (status != ParserStatus::Ok && status != ParserStatus::Paused) {
716
1586
    absl::string_view error = Http1ResponseCodeDetails::get().HttpCodecError;
717
1586
    if (parser_->errorMessage() == "headers size exceeds limit" ||
718
1586
        parser_->errorMessage() == "trailers size exceeds limit") {
719
19
      error_code_ = Http::Code::RequestHeaderFieldsTooLarge;
720
19
      error = Http1ResponseCodeDetails::get().HeadersTooLarge;
721
1567
    } else if (parser_->errorMessage() == "header value contains invalid chars") {
722
322
      error = Http1ResponseCodeDetails::get().InvalidCharacters;
723
322
    }
724

            
725
1586
    RETURN_IF_ERROR(sendProtocolError(error));
726
    // Avoid overwriting the codec_status_ set in the callbacks.
727
1586
    ASSERT(codec_status_.ok());
728
1586
    codec_status_ =
729
1586
        codecProtocolError(absl::StrCat("http/1.1 protocol error: ", parser_->errorMessage()));
730
1586
    return codec_status_;
731
1586
  }
732

            
733
231498
  return nread;
734
233084
}
735

            
736
84273
CallbackResult ConnectionImpl::onMessageBegin() {
737
84273
  return setAndCheckCallbackStatus(onMessageBeginImpl());
738
84273
}
739

            
740
41677
CallbackResult ConnectionImpl::onUrl(const char* data, size_t length) {
741
41677
  return setAndCheckCallbackStatus(onUrlBase(data, length));
742
41677
}
743

            
744
41208
CallbackResult ConnectionImpl::onStatus(const char* data, size_t length) {
745
41208
  return setAndCheckCallbackStatus(onStatusBase(data, length));
746
41208
}
747

            
748
376083
CallbackResult ConnectionImpl::onHeaderField(const char* data, size_t length) {
749
376083
  return setAndCheckCallbackStatus(onHeaderFieldImpl(data, length));
750
376083
}
751

            
752
376078
CallbackResult ConnectionImpl::onHeaderValue(const char* data, size_t length) {
753
376078
  return setAndCheckCallbackStatus(onHeaderValueImpl(data, length));
754
376078
}
755

            
756
82705
CallbackResult ConnectionImpl::onHeadersComplete() {
757
82705
  return setAndCheckCallbackStatusOr(onHeadersCompleteImpl());
758
82705
}
759

            
760
166488
void ConnectionImpl::bufferBody(const char* data, size_t length) {
761
166488
  auto slice = current_dispatching_buffer_->frontSlice();
762
166488
  if (data == slice.mem_ && length == slice.len_) {
763
88081
    buffered_body_.move(*current_dispatching_buffer_, length);
764
88081
    dispatching_slice_already_drained_ = true;
765
138835
  } else {
766
78407
    buffered_body_.add(data, length);
767
78407
  }
768
166488
}
769

            
770
81760
CallbackResult ConnectionImpl::onMessageComplete() {
771
81760
  return setAndCheckCallbackStatusOr(onMessageCompleteImpl());
772
81760
}
773

            
774
91170
void ConnectionImpl::onChunkHeader(bool is_final_chunk) {
775
91170
  if (is_final_chunk) {
776
    // Dispatch body before parsing trailers, so body ends up dispatched even if an error is found
777
    // while processing trailers.
778
18264
    dispatchBufferedBody();
779
18264
  }
780
91170
}
781

            
782
376083
Status ConnectionImpl::onHeaderFieldImpl(const char* data, size_t length) {
783
376083
  ASSERT(dispatching_);
784

            
785
376083
  getBytesMeter().addHeaderBytesReceived(length);
786

            
787
  // We previously already finished up the headers, these headers are
788
  // now trailers.
789
376083
  if (header_parsing_state_ == HeaderParsingState::Done) {
790
280
    if (!enableTrailers()) {
791
      // Ignore trailers.
792
      return okStatus();
793
    }
794
280
    processing_trailers_ = true;
795
280
    header_parsing_state_ = HeaderParsingState::Field;
796
280
    allocTrailers();
797
280
  }
798
376083
  if (header_parsing_state_ == HeaderParsingState::Value) {
799
294513
    RETURN_IF_ERROR(completeCurrentHeader());
800
294513
  }
801

            
802
376078
  current_header_field_.append(data, length);
803

            
804
376078
  return checkMaxHeadersSize();
805
376083
}
806

            
807
376078
Status ConnectionImpl::onHeaderValueImpl(const char* data, size_t length) {
808
376078
  ASSERT(dispatching_);
809

            
810
376078
  getBytesMeter().addHeaderBytesReceived(length);
811

            
812
376078
  if (header_parsing_state_ == HeaderParsingState::Done && !enableTrailers()) {
813
    // Ignore trailers.
814
    return okStatus();
815
  }
816

            
817
376078
  absl::string_view header_value{data, length};
818
376078
  if (!Http::HeaderUtility::headerValueIsValid(header_value)) {
819
    ENVOY_CONN_LOG(debug, "invalid header value: {}", connection_, header_value);
820
    error_code_ = Http::Code::BadRequest;
821
    RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidCharacters));
822
    return codecProtocolError("http/1.1 protocol error: header value contains invalid chars");
823
  }
824

            
825
376078
  header_parsing_state_ = HeaderParsingState::Value;
826
376078
  if (current_header_value_.empty()) {
827
    // Strip leading whitespace if the current header value input contains the first bytes of the
828
    // encoded header value. Trailing whitespace is stripped once the full header value is known in
829
    // ConnectionImpl::completeCurrentHeader. http_parser does not strip leading or trailing
830
    // whitespace as the spec requires: https://tools.ietf.org/html/rfc7230#section-3.2.4 .
831
376078
    header_value = StringUtil::ltrim(header_value);
832
376078
  }
833
376078
  current_header_value_.append(header_value.data(), header_value.length());
834

            
835
376078
  return checkMaxHeadersSize();
836
376078
}
837

            
838
82705
StatusOr<CallbackResult> ConnectionImpl::onHeadersCompleteImpl() {
839
82705
  ASSERT(!processing_trailers_);
840
82705
  ASSERT(dispatching_);
841
82705
  ENVOY_CONN_LOG(trace, "onHeadersCompleteImpl", connection_);
842
82705
  RETURN_IF_ERROR(completeCurrentHeader());
843

            
844
  // There is no header field compression in HTTP/1.1, so the wire representation is the same as the
845
  // decompressed representation.
846
82700
  getBytesMeter().addDecompressedHeaderBytesReceived(getBytesMeter().headerBytesReceived());
847

            
848
82700
  if (!parser_->isHttp11()) {
849
    // This is not necessarily true, but it's good enough since higher layers only care if this is
850
    // HTTP/1.1 or not.
851
32
    protocol_ = Protocol::Http10;
852
32
  }
853
82700
  RequestOrResponseHeaderMap& request_or_response_headers = requestOrResponseHeaders();
854
82700
  const Http::HeaderValues& header_values = Http::Headers::get();
855
82700
  if (Utility::isUpgrade(request_or_response_headers) && upgradeAllowed()) {
856
200
    auto upgrade_value = request_or_response_headers.getUpgradeValue();
857
200
    const bool is_h2c = absl::EqualsIgnoreCase(upgrade_value, header_values.UpgradeValues.H2c);
858

            
859
    // Ignore h2c upgrade requests until we support them.
860
    // See https://github.com/envoyproxy/envoy/issues/7161 for details.
861
    // Upgrades are rejected unless ignore_http_11_upgrade is configured.
862
    // See https://github.com/envoyproxy/envoy/issues/36305 for details.
863
200
    if (is_h2c) {
864
3
      ENVOY_CONN_LOG(trace, "removing unsupported h2c upgrade headers.", connection_);
865
3
      request_or_response_headers.removeUpgrade();
866
3
      Utility::removeConnectionUpgrade(request_or_response_headers,
867
3
                                       caseUnorderedSetContainingUpgradeAndHttp2Settings());
868
3
      request_or_response_headers.remove(header_values.Http2Settings);
869
197
    } else if (codec_settings_.ignore_upgrade_matchers_ != nullptr &&
870
197
               !codec_settings_.ignore_upgrade_matchers_->empty()) {
871
4
      ENVOY_CONN_LOG(trace, "removing ignored upgrade headers.", connection_);
872

            
873
4
      Utility::removeUpgrade(request_or_response_headers,
874
4
                             *codec_settings_.ignore_upgrade_matchers_);
875

            
876
4
      if (!request_or_response_headers.Upgrade()) {
877
3
        Utility::removeConnectionUpgrade(request_or_response_headers,
878
3
                                         caseUnorderedSetContainingUpgrade());
879
3
      }
880
4
    }
881

            
882
200
    if (Utility::isUpgrade(request_or_response_headers)) {
883
194
      ENVOY_CONN_LOG(trace, "codec entering upgrade mode.", connection_);
884
194
      handling_upgrade_ = true;
885
194
    }
886
200
  }
887
82700
  if (parser_->methodName() == header_values.MethodValues.Connect) {
888
328
    if (request_or_response_headers.ContentLength()) {
889
2
      if (request_or_response_headers.getContentLengthValue() == "0") {
890
1
        request_or_response_headers.removeContentLength();
891
1
      } else {
892
        // Per https://tools.ietf.org/html/rfc7231#section-4.3.6 a payload with a
893
        // CONNECT request has no defined semantics, and may be rejected.
894
1
        error_code_ = Http::Code::BadRequest;
895
1
        RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().BodyDisallowed));
896
1
        return codecProtocolError("http/1.1 protocol error: unsupported content length");
897
1
      }
898
2
    }
899
327
    ENVOY_CONN_LOG(trace, "codec entering upgrade mode for CONNECT request.", connection_);
900
327
    handling_upgrade_ = true;
901
327
  }
902

            
903
  // https://tools.ietf.org/html/rfc7230#section-3.3.3
904
  // If a message is received with both a Transfer-Encoding and a
905
  // Content-Length header field, the Transfer-Encoding overrides the
906
  // Content-Length. Such a message might indicate an attempt to
907
  // perform request smuggling (Section 9.5) or response splitting
908
  // (Section 9.4) and ought to be handled as an error. A sender MUST
909
  // remove the received Content-Length field prior to forwarding such
910
  // a message.
911

            
912
82699
#ifndef ENVOY_ENABLE_UHV
913
  // This check is moved into default header validator.
914
  // TODO(yanavlasov): use runtime override here when UHV is moved into the main build
915

            
916
  // Reject message with Http::Code::BadRequest if both Transfer-Encoding and Content-Length
917
  // headers are present or if allowed by http1 codec settings and 'Transfer-Encoding'
918
  // is chunked - remove Content-Length and serve request.
919
82699
  if (parser_->hasTransferEncoding() != 0 && request_or_response_headers.ContentLength()) {
920
19
    if (parser_->isChunked() && codec_settings_.allow_chunked_length_) {
921
8
      request_or_response_headers.removeContentLength();
922
12
    } else {
923
11
      error_code_ = Http::Code::BadRequest;
924
11
      RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().ChunkedContentLength));
925
11
      return codecProtocolError(
926
11
          "http/1.1 protocol error: both 'Content-Length' and 'Transfer-Encoding' are set.");
927
11
    }
928
19
  }
929

            
930
  // Per https://tools.ietf.org/html/rfc7230#section-3.3.1 Envoy should reject
931
  // transfer-codings it does not understand.
932
  // Per https://tools.ietf.org/html/rfc7231#section-4.3.6 a payload with a
933
  // CONNECT request has no defined semantics, and may be rejected.
934
82688
  if (request_or_response_headers.TransferEncoding()) {
935
19134
    const absl::string_view encoding = request_or_response_headers.getTransferEncodingValue();
936
19134
    if (!absl::EqualsIgnoreCase(encoding, header_values.TransferEncodingValues.Chunked) ||
937
19134
        parser_->methodName() == header_values.MethodValues.Connect) {
938
8
      error_code_ = Http::Code::NotImplemented;
939
8
      RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidTransferEncoding));
940
8
      return codecProtocolError("http/1.1 protocol error: unsupported transfer encoding");
941
8
    }
942
19134
  }
943
82680
#endif
944

            
945
82680
  auto statusor = onHeadersCompleteBase();
946
82680
  if (!statusor.ok()) {
947
28
    RETURN_IF_ERROR(statusor.status());
948
28
  }
949

            
950
82652
  header_parsing_state_ = HeaderParsingState::Done;
951

            
952
  // Returning CallbackResult::NoBodyData informs http_parser to not expect a body or further data
953
  // on this connection.
954
82652
  return handling_upgrade_ ? CallbackResult::NoBodyData : statusor.value();
955
82680
}
956

            
957
81760
StatusOr<CallbackResult> ConnectionImpl::onMessageCompleteImpl() {
958
81760
  ENVOY_CONN_LOG(trace, "message complete", connection_);
959

            
960
81760
  dispatchBufferedBody();
961

            
962
81760
  if (handling_upgrade_) {
963
    // If this is an upgrade request, swallow the onMessageComplete. The
964
    // upgrade payload will be treated as stream body.
965
761
    ASSERT(!deferred_end_stream_headers_);
966
761
    ENVOY_CONN_LOG(trace, "Pausing parser due to upgrade.", connection_);
967
761
    return parser_->pause();
968
761
  }
969

            
970
  // If true, this indicates we were processing trailers and must
971
  // move the last header into current_header_map_
972
80999
  if (header_parsing_state_ == HeaderParsingState::Value) {
973
278
    RETURN_IF_ERROR(completeCurrentHeader());
974
278
  }
975

            
976
80996
  return onMessageCompleteBase();
977
80999
}
978

            
979
241968
void ConnectionImpl::dispatchBufferedBody() {
980
241968
  ASSERT(parser_->getStatus() == ParserStatus::Ok || parser_->getStatus() == ParserStatus::Paused);
981
241968
  ASSERT(codec_status_.ok());
982
241968
  if (buffered_body_.length() > 0) {
983
76453
    onBody(buffered_body_);
984
76453
    buffered_body_.drain(buffered_body_.length());
985
76453
  }
986
241968
}
987

            
988
3290
void ConnectionImpl::onResetStreamBase(StreamResetReason reason) {
989
3290
  ASSERT(!reset_stream_called_);
990
3290
  reset_stream_called_ = true;
991
3290
  onResetStream(reason);
992
3290
}
993

            
994
OptRef<const StreamInfo::StreamInfo> ConnectionImpl::trackedStream() const {
995
  return connection_.trackedStream();
996
}
997

            
998
3
void ConnectionImpl::dumpState(std::ostream& os, int indent_level) const {
999
3
  const char* spaces = spacesForLevel(indent_level);
3
  os << spaces << "Http1::ConnectionImpl " << this << DUMP_MEMBER(dispatching_)
3
     << DUMP_MEMBER(dispatching_slice_already_drained_) << DUMP_MEMBER(reset_stream_called_)
3
     << DUMP_MEMBER(handling_upgrade_) << DUMP_MEMBER(deferred_end_stream_headers_)
3
     << DUMP_MEMBER(processing_trailers_) << DUMP_MEMBER(buffered_body_.length());
  // Dump header parsing state, and any progress on headers.
3
  os << DUMP_MEMBER(header_parsing_state_);
3
  os << DUMP_MEMBER_AS(current_header_field_, current_header_field_.getStringView());
3
  os << DUMP_MEMBER_AS(current_header_value_, current_header_value_.getStringView());
  // Dump Child
3
  os << '\n';
3
  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.
3
  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.
2
    os << DUMP_NULLABLE_MEMBER(current_dispatching_buffer_, "drained");
2
    return;
2
  } else {
1
    absl::string_view front_slice = [](Buffer::RawSlice slice) {
1
      return absl::string_view(static_cast<const char*>(slice.mem_), slice.len_);
1
    }(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.
1
    os << spaces << "current_dispatching_buffer_ front_slice length: " << front_slice.length()
1
       << " contents: \"";
1
    StringUtil::escapeToOstream(os, front_slice);
1
    os << "\"\n";
1
  }
3
}
void ServerConnectionImpl::dumpAdditionalState(std::ostream& os, int indent_level) const {
  const char* spaces = spacesForLevel(indent_level);
  DUMP_DETAILS(active_request_);
  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_));
  }
}
3
void ClientConnectionImpl::dumpAdditionalState(std::ostream& os, int indent_level) const {
3
  const char* spaces = spacesForLevel(indent_level);
  // Dump header map, it may be null if it was moved to the request.
3
  if (absl::holds_alternative<ResponseHeaderMapPtr>(headers_or_trailers_)) {
3
    DUMP_DETAILS(absl::get<ResponseHeaderMapPtr>(headers_or_trailers_));
3
  } else {
    DUMP_DETAILS(absl::get<ResponseTrailerMapPtr>(headers_or_trailers_));
  }
  // Dump the associated request.
3
  os << spaces << "Dumping corresponding downstream request:";
3
  if (pending_response_.has_value()) {
3
    os << '\n';
3
    const ResponseDecoder* decoder = pending_response_.value().decoder_;
3
    DUMP_DETAILS(decoder);
3
  } else {
    os << " null\n";
  }
3
}
ServerConnectionImpl::ServerConnectionImpl(
    Network::Connection& connection, CodecStats& stats, ServerConnectionCallbacks& callbacks,
    const Http1Settings& settings, uint32_t max_request_headers_kb,
    const uint32_t max_request_headers_count,
    envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction
        headers_with_underscores_action,
    Server::OverloadManager& overload_manager)
35110
    : ConnectionImpl(connection, stats, settings, MessageType::Request, max_request_headers_kb,
35110
                     max_request_headers_count),
35110
      callbacks_(callbacks),
39679
      response_buffer_releasor_([this](const Buffer::OwnedBufferFragmentImpl* fragment) {
37097
        releaseOutboundResponse(fragment);
37097
      }),
35110
      owned_output_buffer_(connection.dispatcher().getWatermarkFactory().createBuffer(
36557
          [&]() -> void { this->onBelowLowWatermark(); },
36557
          [&]() -> void { this->onAboveHighWatermark(); },
35110
          []() -> void { /* TODO(adisuissa): handle overflow watermark */ })),
35110
      headers_with_underscores_action_(headers_with_underscores_action),
35110
      abort_dispatch_(overload_manager.getLoadShedPoint(
35110
          Server::LoadShedPointName::get().H1ServerAbortDispatch)) {
35110
  ENVOY_LOG_ONCE_IF(trace, abort_dispatch_ == nullptr,
35110
                    "LoadShedPoint envoy.load_shed_points.http1_server_abort_dispatch is not "
35110
                    "found. Is it configured?");
35110
  owned_output_buffer_->setWatermarks(connection.bufferLimit());
  // Inform parent
35110
  output_buffer_ = owned_output_buffer_.get();
35110
}
581417
uint32_t ServerConnectionImpl::getHeadersSize() {
  // Add in the size of the request URL if processing request headers.
581417
  const uint32_t url_size =
581417
      (!processing_trailers_ && active_request_) ? active_request_->request_url_.size() : 0;
581417
  return url_size + ConnectionImpl::getHeadersSize();
581417
}
41946
void ServerConnectionImpl::onEncodeComplete() {
41946
  if (active_request_->remote_complete_) {
    // Only do this if remote is complete. If we are replying before the request is complete the
    // only logical thing to do is for higher level code to reset() / close the connection so we
    // leave the request around so that it can fire reset callbacks.
40070
    connection_.dispatcher().deferredDelete(std::move(active_request_));
40070
  }
41946
}
41502
Status ServerConnectionImpl::handlePath(RequestHeaderMap& headers, absl::string_view method) {
41502
  const Http::HeaderValues& header_values = Http::Headers::get();
41502
  HeaderString path(header_values.Path);
41502
  bool is_connect = (method == header_values.MethodValues.Connect);
  // The url is relative or a wildcard when the method is OPTIONS. Nothing to do here.
41502
  if (!is_connect && !active_request_->request_url_.getStringView().empty() &&
41502
      (active_request_->request_url_.getStringView()[0] == '/' ||
41177
       (method == header_values.MethodValues.Options &&
41154
        active_request_->request_url_.getStringView()[0] == '*'))) {
41154
    headers.addViaMove(std::move(path), std::move(active_request_->request_url_));
41154
    return okStatus();
41154
  }
  // If absolute_urls and/or connect are not going be handled, copy the url and return.
  // This forces the behavior to be backwards compatible with the old codec behavior.
  // CONNECT "urls" are actually host:port so look like absolute URLs to the above checks.
  // Absolute URLS in CONNECT requests will be rejected below by the URL class validation.
  /**
   * @param scheme the scheme to validate
   * @return bool true if the scheme is http.
   */
348
  if (!codec_settings_.allow_absolute_url_ && !is_connect) {
2
    headers.addViaMove(std::move(path), std::move(active_request_->request_url_));
2
    return okStatus();
2
  }
346
  Utility::Url absolute_url;
346
  if (!absolute_url.initialize(active_request_->request_url_.getStringView(), is_connect)) {
3
    RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidUrl));
3
    return codecProtocolError("http/1.1 protocol error: invalid url in request line");
3
  }
  // RFC7230#5.7
  // When a proxy receives a request with an absolute-form of
  // request-target, the proxy MUST ignore the received Host header field
  // (if any) and instead replace it with the host information of the
  // request-target. A proxy that forwards such a request MUST generate a
  // new Host field-value based on the received request-target rather than
  // forward the received Host field-value.
343
  headers.setHost(absolute_url.hostAndPort());
  // Add the scheme and validate to ensure no https://
  // requests are accepted over unencrypted connections by front-line Envoys.
343
  if (!is_connect) {
19
    headers.setScheme(absl::AsciiStrToLower(absolute_url.scheme()));
19
    if (!Utility::schemeIsValid(headers.getSchemeValue())) {
1
      RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidScheme));
1
      return codecProtocolError("http/1.1 protocol error: invalid scheme");
1
    }
18
    if (codec_settings_.validate_scheme_ && Utility::schemeIsHttps(absolute_url.scheme()) &&
18
        !connection().ssl()) {
1
      error_code_ = Http::Code::Forbidden;
1
      RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().HttpsInPlaintext));
1
      return codecProtocolError("http/1.1 protocol error: https in the clear");
1
    }
18
  }
341
  if (!absolute_url.pathAndQueryParams().empty()) {
17
    headers.setPath(absolute_url.pathAndQueryParams());
17
  }
341
  active_request_->request_url_.clear();
341
  return okStatus();
343
}
41497
Status ServerConnectionImpl::checkProtocolVersion(RequestHeaderMap& headers) {
41497
  if (protocol() == Protocol::Http10) {
    // Assume this is HTTP/1.0. This is fine for HTTP/0.9 but this code will also affect any
    // requests with non-standard version numbers (0.9, 1.3), basically anything which is not
    // HTTP/1.1.
    //
    // The protocol may have shifted in the HTTP/1.0 case so reset it.
29
    if (!codec_settings_.accept_http_10_) {
      // Send "Upgrade Required" if HTTP/1.0 support is not explicitly configured on.
13
      error_code_ = Http::Code::UpgradeRequired;
13
      RETURN_IF_ERROR(sendProtocolError(StreamInfo::ResponseCodeDetails::get().LowVersion));
13
      return codecProtocolError("Upgrade required for HTTP/1.0 or HTTP/0.9");
13
    }
16
    if (!headers.Host() && !codec_settings_.default_host_for_http_10_.empty()) {
      // Add a default host if configured to do so.
7
      headers.setHost(codec_settings_.default_host_for_http_10_);
7
    }
16
  }
41484
  return okStatus();
41497
}
41503
Envoy::StatusOr<CallbackResult> ServerConnectionImpl::onHeadersCompleteBase() {
  // Handle the case where response happens prior to request complete. It's up to upper layer code
  // to disconnect the connection but we shouldn't fire any more events since it doesn't make
  // sense.
41503
  if (active_request_) {
41503
    auto& headers = absl::get<RequestHeaderMapPtr>(headers_or_trailers_);
41503
    ENVOY_CONN_LOG(trace, "Server: onHeadersComplete size={}", connection_, headers->size());
41503
    if (!handling_upgrade_ && headers->Connection()) {
      // If we fail to sanitize the request, return a 400 to the client
20
      if (!Utility::sanitizeConnectionHeader(*headers)) {
1
        absl::string_view header_value = headers->getConnectionValue();
1
        ENVOY_CONN_LOG(debug, "Invalid nominated headers in Connection: {}", connection_,
1
                       header_value);
1
        error_code_ = Http::Code::BadRequest;
1
        RETURN_IF_ERROR(
1
            sendProtocolError(Http1ResponseCodeDetails::get().ConnectionHeaderSanitization));
1
        return codecProtocolError("Invalid nominated headers in Connection.");
1
      }
20
    }
    // Inform the response encoder about any HEAD method, so it can set content
    // length and transfer encoding headers correctly.
41502
    const Http::HeaderValues& header_values = Http::Headers::get();
41502
    active_request_->response_encoder_.setIsResponseToHeadRequest(parser_->methodName() ==
41502
                                                                  header_values.MethodValues.Head);
41502
    active_request_->response_encoder_.setIsResponseToConnectRequest(
41502
        parser_->methodName() == header_values.MethodValues.Connect);
41502
    RETURN_IF_ERROR(handlePath(*headers, parser_->methodName()));
41497
    ASSERT(active_request_->request_url_.empty());
41497
    headers->setMethod(parser_->methodName());
41497
    RETURN_IF_ERROR(checkProtocolVersion(*headers));
    // Make sure the host is valid.
41484
    auto details = HeaderUtility::requestHeadersValid(*headers);
41484
    if (details.has_value()) {
3
      RETURN_IF_ERROR(sendProtocolError(details.value().get()));
3
      return codecProtocolError(
3
          "http/1.1 protocol error: request headers failed spec compliance checks");
3
    }
    // Determine here whether we have a body or not. This uses the new RFC semantics where the
    // presence of content-length or chunked transfer-encoding indicates a body vs. a particular
    // method. If there is no body, we defer raising decodeHeaders() until the parser is flushed
    // with message complete. This allows upper layers to behave like HTTP/2 and prevents a proxy
    // scenario where the higher layers stream through and implicitly switch to chunked transfer
    // encoding because end stream with zero body length has not yet been indicated.
41481
    if (parser_->isChunked() ||
41481
        (parser_->contentLength().has_value() && parser_->contentLength().value() > 0) ||
41481
        handling_upgrade_) {
6565
      active_request_->request_decoder_->decodeHeaders(std::move(headers), false);
      // If the connection has been closed (or is closing) after decoding headers, pause the parser
      // so we return control to the caller.
6565
      if (connection_.state() != Network::Connection::State::Open) {
265
        return parser_->pause();
265
      }
38909
    } else {
34916
      deferred_end_stream_headers_ = true;
34916
    }
41481
  }
41216
  return CallbackResult::Success;
41503
}
43055
Status ServerConnectionImpl::onMessageBeginBase() {
43055
  if (!resetStreamCalled()) {
43054
    ASSERT(active_request_ == nullptr);
43054
    active_request_ = std::make_unique<ActiveRequest>(*this, std::move(bytes_meter_before_stream_));
43054
    active_request_->request_decoder_ = &callbacks_.newStream(active_request_->response_encoder_);
    // Check for pipelined request flood as we prepare to accept a new request.
    // Parse errors that happen prior to onMessageBegin result in stream termination, it is not
    // possible to overflow output buffers with early parse errors.
43054
    RETURN_IF_ERROR(doFloodProtectionChecks());
43054
  }
43052
  return okStatus();
43055
}
41677
Status ServerConnectionImpl::onUrlBase(const char* data, size_t length) {
41677
  if (active_request_) {
41677
    active_request_->request_url_.append(data, length);
41677
    RETURN_IF_ERROR(checkMaxHeadersSize());
41677
  }
41677
  return okStatus();
41677
}
59817
void ServerConnectionImpl::onBody(Buffer::Instance& data) {
59817
  ASSERT(!deferred_end_stream_headers_);
59817
  if (active_request_) {
59799
    ENVOY_CONN_LOG(trace, "body size={}", connection_, data.length());
59799
    active_request_->request_decoder_->decodeData(data, false);
59799
  }
59817
}
99888
Http::Status ServerConnectionImpl::dispatch(Buffer::Instance& data) {
99888
  if (abort_dispatch_ != nullptr && abort_dispatch_->shouldShedLoad()) {
6
    RETURN_IF_ERROR(sendOverloadError());
6
    return envoyOverloadError("Aborting Server Dispatch");
6
  }
99882
  if (active_request_ != nullptr && active_request_->remote_complete_) {
    // Eagerly read disable the connection if the downstream is sending pipelined requests as we
    // serially process them. Reading from the connection will be re-enabled after the active
    // request is completed.
1
    active_request_->response_encoder_.readDisable(true);
1
    return okStatus();
1
  }
99881
  Http::Status status = ConnectionImpl::dispatch(data);
99881
  if (active_request_ != nullptr && active_request_->remote_complete_) {
    // Read disable the connection if the downstream is sending additional data while we are working
    // on an existing request. Reading from the connection will be re-enabled after the active
    // request is completed.
36938
    if (data.length() > 0) {
29
      active_request_->response_encoder_.readDisable(true);
29
    }
36938
  }
99881
  return status;
99882
}
40347
CallbackResult ServerConnectionImpl::onMessageCompleteBase() {
40347
  ASSERT(!handling_upgrade_);
40347
  if (active_request_) {
    // The request_decoder should be non-null after we've called the newStream on callbacks.
40329
    ASSERT(active_request_->request_decoder_);
40329
    active_request_->remote_complete_ = true;
40329
    if (deferred_end_stream_headers_) {
34916
      active_request_->request_decoder_->decodeHeaders(
34916
          std::move(absl::get<RequestHeaderMapPtr>(headers_or_trailers_)), true);
34916
      deferred_end_stream_headers_ = false;
38067
    } else if (processing_trailers_) {
62
      active_request_->request_decoder_->decodeTrailers(
62
          std::move(absl::get<RequestTrailerMapPtr>(headers_or_trailers_)));
5379
    } else {
5351
      Buffer::OwnedImpl buffer;
5351
      active_request_->request_decoder_->decodeData(buffer, true);
5351
    }
    // Reset to ensure no information from one requests persists to the next.
40329
    headers_or_trailers_.emplace<RequestHeaderMapPtr>(nullptr);
40329
  }
  // Always pause the parser so that the calling code can process 1 request at a time and apply
  // back pressure. However this means that the calling code needs to detect if there is more data
  // in the buffer and dispatch it again.
40347
  return parser_->pause();
40347
}
1863
void ServerConnectionImpl::onResetStream(StreamResetReason reason) {
1863
  if (active_request_) {
1863
    active_request_->response_encoder_.runResetCallbacks(reason, absl::string_view());
1863
    connection_.dispatcher().deferredDelete(std::move(active_request_));
1863
  }
1863
}
6
Status ServerConnectionImpl::sendOverloadError() {
6
  const bool latched_dispatching = dispatching_;
  // The codec might be in the early stages of server dispatching where this isn't yet
  // flipped to true.
6
  dispatching_ = true;
6
  error_code_ = Http::Code::InternalServerError;
6
  auto status = sendProtocolError(Envoy::StreamInfo::ResponseCodeDetails::get().Overload);
6
  dispatching_ = latched_dispatching;
6
  return status;
6
}
1536
Status ServerConnectionImpl::sendProtocolError(absl::string_view details) {
  // We do this here because we may get a protocol error before we have a logical stream.
1536
  if (active_request_ == nullptr) {
3
    RETURN_IF_ERROR(onMessageBeginImpl());
3
  }
1536
  if (resetStreamCalled()) {
1
    return okStatus();
1
  }
1535
  ASSERT(active_request_);
1535
  active_request_->response_encoder_.setDetails(details);
1535
  if (!active_request_->response_encoder_.startedResponse()) {
1534
    active_request_->request_decoder_->sendLocalReply(
1534
        error_code_, CodeUtility::toString(error_code_), nullptr, absl::nullopt, details);
1534
  }
1535
  return okStatus();
1536
}
3625
void ServerConnectionImpl::onAboveHighWatermark() {
3625
  if (active_request_) {
3625
    active_request_->response_encoder_.runHighWatermarkCallbacks();
3625
  }
3625
}
3624
void ServerConnectionImpl::onBelowLowWatermark() {
3624
  if (active_request_) {
3602
    active_request_->response_encoder_.runLowWatermarkCallbacks();
3602
  }
3624
}
void ServerConnectionImpl::releaseOutboundResponse(
37097
    const Buffer::OwnedBufferFragmentImpl* fragment) {
37097
  ASSERT(outbound_responses_ >= 1);
37097
  --outbound_responses_;
37097
  delete fragment;
37097
}
270946
Status ServerConnectionImpl::checkHeaderNameForUnderscores() {
270946
#ifndef ENVOY_ENABLE_UHV
  // This check has been moved to UHV
270946
  if (headers_with_underscores_action_ != envoy::config::core::v3::HttpProtocolOptions::ALLOW &&
270946
      Http::HeaderUtility::headerNameContainsUnderscore(current_header_field_.getStringView())) {
14
    if (headers_with_underscores_action_ ==
14
        envoy::config::core::v3::HttpProtocolOptions::DROP_HEADER) {
9
      ENVOY_CONN_LOG(debug, "Dropping header with invalid characters in its name: {}", connection_,
9
                     current_header_field_.getStringView());
9
      stats_.incDroppedHeadersWithUnderscores();
9
      current_header_field_.clear();
9
      current_header_value_.clear();
12
    } else {
5
      ENVOY_CONN_LOG(debug, "Rejecting request due to header name with underscores: {}",
5
                     connection_, current_header_field_.getStringView());
5
      error_code_ = Http::Code::BadRequest;
5
      RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidUnderscore));
5
      stats_.incRequestsRejectedWithUnderscoresInHeaders();
5
      return codecProtocolError("http/1.1 protocol error: header name contains underscores");
5
    }
14
  }
#else
  // Workaround for gcc not understanding [[maybe_unused]] for class members.
  (void)headers_with_underscores_action_;
#endif
270941
  return okStatus();
270946
}
void ServerConnectionImpl::ActiveRequest::dumpState(std::ostream& os, int indent_level) const {
  (void)indent_level;
  os << DUMP_MEMBER_AS(
      request_url_, !request_url_.getStringView().empty() ? request_url_.getStringView() : "null");
  os << DUMP_MEMBER(response_encoder_.local_end_stream_);
}
ClientConnectionImpl::ClientConnectionImpl(Network::Connection& connection, CodecStats& stats,
                                           ConnectionCallbacks&, const Http1Settings& settings,
                                           absl::optional<uint16_t> max_response_headers_kb,
                                           const uint32_t max_response_headers_count,
                                           bool passing_through_proxy)
34223
    : ConnectionImpl(connection, stats, settings, MessageType::Response,
34223
                     max_response_headers_kb.value_or(MAX_RESPONSE_HEADERS_KB),
34223
                     max_response_headers_count),
34223
      owned_output_buffer_(connection.dispatcher().getWatermarkFactory().createBuffer(
73482
          [&]() -> void { this->onBelowLowWatermark(); },
73482
          [&]() -> void { this->onAboveHighWatermark(); },
34223
          []() -> void { /* TODO(adisuissa): handle overflow watermark */ })),
34223
      passing_through_proxy_(passing_through_proxy),
34223
      force_reset_on_premature_upstream_half_close_(Runtime::runtimeFeatureEnabled(
34223
          "envoy.reloadable_features.allow_multiplexed_upstream_half_close")) {
34223
  owned_output_buffer_->setWatermarks(connection.bufferLimit());
  // Inform parent
34223
  output_buffer_ = owned_output_buffer_.get();
34223
}
82199
bool ClientConnectionImpl::cannotHaveBody() {
82199
  if (pending_response_.has_value() && pending_response_.value().encoder_.headRequest()) {
315
    ASSERT(!pending_response_done_);
315
    return true;
81884
  } else if (parser_->statusCode() == Http::Code::NoContent ||
81884
             parser_->statusCode() == Http::Code::NotModified ||
81884
             (parser_->statusCode() >= Http::Code::OK &&
81756
              (parser_->contentLength().has_value() && parser_->contentLength().value() == 0) &&
81756
              !parser_->isChunked())) {
49836
    return true;
74164
  } else {
32048
    return false;
32048
  }
82199
}
41964
RequestEncoder& ClientConnectionImpl::newStream(ResponseDecoder& response_decoder) {
  // If reads were disabled due to flow control, we expect reads to always be enabled again before
  // reusing this connection. This is done when the response is received.
41964
  ASSERT(connection_.readEnabled());
41964
  ASSERT(!pending_response_.has_value());
41964
  ASSERT(pending_response_done_);
41964
  pending_response_.emplace(*this, std::move(bytes_meter_before_stream_), &response_decoder);
41964
  pending_response_done_ = false;
41964
  return pending_response_.value().encoder_;
41964
}
41208
Status ClientConnectionImpl::onStatusBase(const char* data, size_t length) {
41208
  auto& headers = absl::get<ResponseHeaderMapPtr>(headers_or_trailers_);
41208
  StatefulHeaderKeyFormatterOptRef formatter(headers->formatter());
41208
  if (formatter.has_value()) {
4
    formatter->setReasonPhrase(absl::string_view(data, length));
4
  }
41208
  return okStatus();
41208
}
41177
Envoy::StatusOr<CallbackResult> ClientConnectionImpl::onHeadersCompleteBase() {
41177
  ENVOY_CONN_LOG(trace, "status_code {}", connection_, enumToInt(parser_->statusCode()));
  // Handle the case where the client is closing a kept alive connection (by sending a 408
  // with a 'Connection: close' header). In this case we just let response flush out followed
  // by the remote close.
41177
  if (!pending_response_.has_value() && !resetStreamCalled()) {
3
    return prematureResponseError("", parser_->statusCode());
41174
  } else if (pending_response_.has_value()) {
41174
    ASSERT(!pending_response_done_);
41174
    auto& headers = absl::get<ResponseHeaderMapPtr>(headers_or_trailers_);
41174
    ENVOY_CONN_LOG(trace, "Client: onHeadersComplete size={}", connection_, headers->size());
41174
    headers->setStatus(enumToInt(parser_->statusCode()));
41174
    if (parser_->statusCode() >= Http::Code::OK &&
41174
        parser_->statusCode() < Http::Code::MultipleChoices &&
41174
        pending_response_.value().encoder_.connectRequest()) {
243
      ENVOY_CONN_LOG(trace, "codec entering upgrade mode for CONNECT response.", connection_);
243
      handling_upgrade_ = true;
243
    }
41174
    if (parser_->statusCode() < Http::Code::OK || parser_->statusCode() == Http::Code::NoContent) {
223
      if (headers->TransferEncoding()) {
2
        RETURN_IF_ERROR(
2
            sendProtocolError(Http1ResponseCodeDetails::get().TransferEncodingNotAllowed));
2
        return codecProtocolError(
2
            "http/1.1 protocol error: transfer encoding not allowed in 1xx or 204");
2
      }
221
      if (headers->ContentLength()) {
        // Report a protocol error for non-zero Content-Length, but paper over zero Content-Length.
4
        if (headers->ContentLength()->value().getStringView() != "0") {
1
          RETURN_IF_ERROR(
1
              sendProtocolError(Http1ResponseCodeDetails::get().ContentLengthNotAllowed));
1
          return codecProtocolError(
1
              "http/1.1 protocol error: content length not allowed in 1xx or 204");
1
        }
3
        headers->removeContentLength();
3
      }
221
    }
41171
    if (HeaderUtility::isSpecial1xx(*headers)) {
143
      pending_response_.value().decoder_->decode1xxHeaders(std::move(headers));
41028
    } else if (cannotHaveBody() && !handling_upgrade_) {
25070
      deferred_end_stream_headers_ = true;
37060
    } else {
15958
      pending_response_.value().decoder_->decodeHeaders(std::move(headers), false);
15958
    }
    // http-parser treats 1xx headers as their own complete response. Swallow the spurious
    // onMessageComplete and continue processing for purely informational headers.
    // 101-SwitchingProtocols is exempt as all data after the header is proxied through after
    // upgrading.
41171
    if (CodeUtility::is1xx(enumToInt(parser_->statusCode())) &&
41171
        parser_->statusCode() != Http::Code::SwitchingProtocols) {
144
      ignore_message_complete_for_1xx_ = true;
      // Reset to ensure no information from the 1xx headers is used for the response headers.
144
      headers_or_trailers_.emplace<ResponseHeaderMapPtr>(nullptr);
144
    }
41171
  }
  // Here we deal with cases where the response cannot have a body by returning
  // CallbackResult::NoBody, but http_parser does not deal with it for us.
41171
  return cannotHaveBody() ? CallbackResult::NoBody : CallbackResult::Success;
41177
}
68
bool ClientConnectionImpl::upgradeAllowed() const {
68
  if (pending_response_.has_value()) {
67
    return pending_response_->encoder_.upgradeRequest();
67
  }
1
  return false;
68
}
27794
void ClientConnectionImpl::onBody(Buffer::Instance& data) {
27794
  ASSERT(!deferred_end_stream_headers_);
27794
  if (pending_response_.has_value()) {
27787
    ASSERT(!pending_response_done_);
27787
    pending_response_.value().decoder_->decodeData(data, false);
27787
  }
27794
}
40649
CallbackResult ClientConnectionImpl::onMessageCompleteBase() {
40649
  ENVOY_CONN_LOG(trace, "message complete", connection_);
40649
  if (ignore_message_complete_for_1xx_) {
144
    ignore_message_complete_for_1xx_ = false;
144
    return CallbackResult::Success;
144
  }
40505
  if (pending_response_.has_value()) {
40492
    ASSERT(!pending_response_done_);
    // After calling decodeData() with end stream set to true, we should no longer be able to reset.
40492
    PendingResponse& response = pending_response_.value();
    // Encoder is used as part of decode* calls later in this function so pending_response_ can not
    // be reset just yet. Preserve the state in pending_response_done_ instead.
40492
    pending_response_done_ = true;
40492
    if (deferred_end_stream_headers_) {
25070
      response.decoder_->decodeHeaders(
25070
          std::move(absl::get<ResponseHeaderMapPtr>(headers_or_trailers_)), true);
25070
      deferred_end_stream_headers_ = false;
36590
    } else if (processing_trailers_) {
213
      response.decoder_->decodeTrailers(
213
          std::move(absl::get<ResponseTrailerMapPtr>(headers_or_trailers_)));
15209
    } else {
15209
      Buffer::OwnedImpl buffer;
15209
      response.decoder_->decodeData(buffer, true);
15209
    }
40492
    if (force_reset_on_premature_upstream_half_close_ && !encode_complete_) {
      // H/1 connections are always reset if upstream is done before downstream.
      // When the allow_multiplexed_upstream_half_close is enabled the router filter does not
      // reset streams where upstream half closed before downstream. In this case the H/1 codec
      // has to reset the stream.
24
      ENVOY_CONN_LOG(trace, "Resetting stream due to premature H/1 upstream close.", connection_);
24
      response.encoder_.runResetCallbacks(StreamResetReason::Http1PrematureUpstreamHalfClose,
24
                                          absl::string_view());
24
    }
    // Reset to ensure no information from one requests persists to the next.
40492
    pending_response_.reset();
40492
    headers_or_trailers_.emplace<ResponseHeaderMapPtr>(nullptr);
40492
  }
  // Pause the parser after a response is complete. Any remaining data indicates an error.
40505
  return parser_->pause();
40649
}
1427
void ClientConnectionImpl::onResetStream(StreamResetReason reason) {
  // Only raise reset if we did not already dispatch a complete response.
1427
  if (pending_response_.has_value() && !pending_response_done_) {
1380
    pending_response_.value().encoder_.runResetCallbacks(reason, absl::string_view());
1380
    pending_response_done_ = true;
1380
    pending_response_.reset();
1380
  }
1427
}
114
Status ClientConnectionImpl::sendProtocolError(absl::string_view details) {
114
  if (pending_response_.has_value()) {
104
    ASSERT(!pending_response_done_);
104
    pending_response_.value().encoder_.setDetails(details);
104
  }
114
  return okStatus();
114
}
70076
void ClientConnectionImpl::onAboveHighWatermark() {
  // This should never happen without an active stream/request.
70076
  pending_response_.value().encoder_.runHighWatermarkCallbacks();
70076
}
70076
void ClientConnectionImpl::onBelowLowWatermark() {
  // This can get called without an active stream/request when the response completion causes us to
  // close the connection, but in doing so go below low watermark.
70076
  if (pending_response_.has_value() && !pending_response_done_) {
70074
    pending_response_.value().encoder_.runLowWatermarkCallbacks();
70074
  }
70076
}
} // namespace Http1
} // namespace Http
} // namespace Envoy