1
#pragma once
2

            
3
#include <cstdint>
4

            
5
#include "envoy/access_log/access_log.h"
6
#include "envoy/api/api.h"
7
#include "envoy/common/random_generator.h"
8
#include "envoy/config/core/v3/health_check.pb.h"
9
#include "envoy/data/core/v3/health_check_event.pb.h"
10
#include "envoy/grpc/status.h"
11
#include "envoy/network/socket.h"
12
#include "envoy/server/health_checker_config.h"
13
#include "envoy/type/v3/http.pb.h"
14
#include "envoy/type/v3/range.pb.h"
15

            
16
#include "source/common/common/dump_state_utils.h"
17
#include "source/common/common/logger.h"
18
#include "source/common/grpc/codec.h"
19
#include "source/common/http/codec_client.h"
20
#include "source/common/router/header_parser.h"
21
#include "source/common/stream_info/stream_info_impl.h"
22
#include "source/common/upstream/health_checker_impl.h"
23
#include "source/extensions/health_checkers/common/health_checker_base_impl.h"
24

            
25
#include "src/proto/grpc/health/v1/health.pb.h"
26

            
27
namespace Envoy {
28
namespace Upstream {
29

            
30
class TcpHealthCheckerFactory : public Server::Configuration::CustomHealthCheckerFactory {
31
public:
32
  Upstream::HealthCheckerSharedPtr
33
  createCustomHealthChecker(const envoy::config::core::v3::HealthCheck& config,
34
                            Server::Configuration::HealthCheckerFactoryContext& context) override;
35

            
36
11081
  std::string name() const override { return "envoy.health_checkers.tcp"; }
37
463
  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
38
463
    return ProtobufTypes::MessagePtr{new envoy::config::core::v3::HealthCheck::TcpHealthCheck()};
39
463
  }
40
};
41

            
42
DECLARE_FACTORY(TcpHealthCheckerFactory);
43

            
44
/**
45
 * TCP health checker implementation.
46
 */
47
class TcpHealthCheckerImpl : public HealthCheckerImplBase {
48
public:
49
  TcpHealthCheckerImpl(const Cluster& cluster, const envoy::config::core::v3::HealthCheck& config,
50
                       Event::Dispatcher& dispatcher, Runtime::Loader& runtime,
51
                       Random::RandomGenerator& random, HealthCheckEventLoggerPtr&& event_logger);
52

            
53
private:
54
  struct TcpActiveHealthCheckSession;
55

            
56
  struct TcpSessionCallbacks : public Network::ConnectionCallbacks,
57
                               public Network::ReadFilterBaseImpl {
58
44
    TcpSessionCallbacks(TcpActiveHealthCheckSession& parent) : parent_(parent) {}
59

            
60
    // Network::ConnectionCallbacks
61
83
    void onEvent(Network::ConnectionEvent event) override { parent_.onEvent(event); }
62
2
    void onAboveWriteBufferHighWatermark() override {}
63
2
    void onBelowWriteBufferLowWatermark() override {}
64

            
65
    // Network::ReadFilter
66
21
    Network::FilterStatus onData(Buffer::Instance& data, bool) override {
67
21
      parent_.onData(data);
68
21
      return Network::FilterStatus::StopIteration;
69
21
    }
70

            
71
    TcpActiveHealthCheckSession& parent_;
72
  };
73

            
74
  struct TcpActiveHealthCheckSession : public ActiveHealthCheckSession {
75
    TcpActiveHealthCheckSession(TcpHealthCheckerImpl& parent, const HostSharedPtr& host)
76
35
        : ActiveHealthCheckSession(parent, host), parent_(parent) {}
77
    ~TcpActiveHealthCheckSession() override;
78

            
79
    void onData(Buffer::Instance& data);
80
    void onEvent(Network::ConnectionEvent event);
81

            
82
    // ActiveHealthCheckSession
83
    void onInterval() override;
84
    void onTimeout() override;
85
    void onDeferredDelete() final;
86

            
87
    TcpHealthCheckerImpl& parent_;
88
    Network::ClientConnectionPtr client_;
89
    std::shared_ptr<TcpSessionCallbacks> session_callbacks_;
90
    // If true, stream close was initiated by us, not e.g. remote close or TCP reset.
91
    // In this case healthcheck status already reported, only state cleanup required.
92
    bool expect_close_{};
93
  };
94

            
95
  using TcpActiveHealthCheckSessionPtr = std::unique_ptr<TcpActiveHealthCheckSession>;
96

            
97
  // HealthCheckerImplBase
98
35
  ActiveHealthCheckSessionPtr makeSession(HostSharedPtr host) override {
99
35
    return std::make_unique<TcpActiveHealthCheckSession>(*this, host);
100
35
  }
101
11
  envoy::data::core::v3::HealthCheckerType healthCheckerType() const override {
102
11
    return envoy::data::core::v3::TCP;
103
11
  }
104

            
105
  const PayloadMatcher::MatchSegments send_bytes_;
106
  PayloadMatcher::MatchSegments receive_bytes_;
107
  const std::unique_ptr<envoy::config::core::v3::ProxyProtocolConfig> proxy_protocol_config_;
108
};
109

            
110
} // namespace Upstream
111
} // namespace Envoy