Lines
88.6 %
Functions
84.6 %
#pragma once
#include "envoy/network/connection.h"
#include "envoy/network/transport_socket.h"
#include "source/common/buffer/buffer_impl.h"
#include "source/common/common/logger.h"
#include "source/common/http/http1/balsa_parser.h"
#include "source/extensions/transport_sockets/common/passthrough.h"
namespace Envoy {
namespace Extensions {
namespace TransportSockets {
namespace Http11Connect {
// If the transport socket options contain http11ProxyInfo and the transport is
// secure, this will prepend a CONNECT request to the outbound data and strip
// the CONNECT response from the inbound data.
class UpstreamHttp11ConnectSocket : public TransportSockets::PassthroughSocket,
public Logger::Loggable<Logger::Id::connection> {
public:
// Processes response_payload and returns true if it is a valid connect
// response with status code 200.
// @param response_payload the HTTP response bytes
// @param header_complete will be set to true if the response payload contains complete headers.
// @param bytes_processed will return how many bytes of response_payload were processed.
static bool isValidConnectResponse(absl::string_view response_payload, bool& headers_complete,
size_t& bytes_processed);
// Helper method to create a properly formatted CONNECT request with Host header.
// @param target the target hostname:port or IP:port to connect to.
// @return a properly formatted CONNECT request string per RFC 9110 section 9.3.6.
static std::string formatConnectRequest(absl::string_view target);
UpstreamHttp11ConnectSocket(
Network::TransportSocketPtr&& transport_socket,
Network::TransportSocketOptionsConstSharedPtr options,
std::shared_ptr<const Upstream::HostDescription> host,
absl::optional<Network::TransportSocketOptions::Http11ProxyInfo> proxy_info = absl::nullopt);
void setTransportSocketCallbacks(Network::TransportSocketCallbacks& callbacks) override;
Network::IoResult doWrite(Buffer::Instance& buffer, bool end_stream) override;
Network::IoResult doRead(Buffer::Instance& buffer) override;
private:
void generateHeader();
Network::IoResult writeHeader();
inline void
handleProxyInfoConnect(const Network::TransportSocketOptions::Http11ProxyInfo& proxy_info);
inline void handleHostMetadataConnect(std::shared_ptr<const Upstream::HostDescription> host);
Network::TransportSocketOptionsConstSharedPtr options_;
Network::TransportSocketCallbacks* callbacks_{};
Buffer::OwnedImpl header_buffer_{};
bool need_to_strip_connect_response_{};
};
class UpstreamHttp11ConnectSocketFactory : public PassthroughFactory {
UpstreamHttp11ConnectSocketFactory(
Network::UpstreamTransportSocketFactoryPtr transport_socket_factory,
// Network::TransportSocketFactory
Network::TransportSocketPtr
createTransportSocket(Network::TransportSocketOptionsConstSharedPtr options,
std::shared_ptr<const Upstream::HostDescription> host) const override;
void hashKey(std::vector<uint8_t>& key,
Network::TransportSocketOptionsConstSharedPtr options) const override;
OptRef<const Network::TransportSocketOptions::Http11ProxyInfo>
defaultHttp11ProxyInfo() const override {
if (!proxy_info_.has_value()) {
return {};
}
return {proxy_info_.value()};
const absl::optional<Network::TransportSocketOptions::Http11ProxyInfo> proxy_info_;
// This is a utility class for isValidConnectResponse. It is only exposed for
// coverage testing purposes. See isValidConnectResponse for intended use.
class SelfContainedParser : public Http::Http1::ParserCallbacks {
SelfContainedParser()
: parser_(Http::Http1::MessageType::Response, this, 2000, /* enable_trailers = */ false,
/* allow_custom_methods = */ false) {}
Http::Http1::CallbackResult onMessageBegin() override {
return Http::Http1::CallbackResult::Success;
Http::Http1::CallbackResult onUrl(const char*, size_t) override {
Http::Http1::CallbackResult onStatus(const char*, size_t) override {
Http::Http1::CallbackResult onHeaderField(const char*, size_t) override {
Http::Http1::CallbackResult onHeaderValue(const char*, size_t) override {
Http::Http1::CallbackResult onHeadersComplete() override {
headers_complete_ = true;
parser_.pause();
void bufferBody(const char*, size_t) override {}
Http::Http1::CallbackResult onMessageComplete() override {
void onChunkHeader(bool) override {}
bool headersComplete() const { return headers_complete_; }
Http::Http1::BalsaParser& parser() { return parser_; }
bool headers_complete_ = false;
Http::Http1::BalsaParser parser_;
} // namespace Http11Connect
} // namespace TransportSockets
} // namespace Extensions
} // namespace Envoy