1
#pragma once
2

            
3
#include "envoy/common/time.h"
4
#include "envoy/config/core/v3/base.pb.h"
5
#include "envoy/config/endpoint/v3/endpoint_components.pb.h"
6

            
7
#include "source/common/upstream/upstream_impl.h"
8

            
9
namespace Envoy {
10
namespace Upstream {
11

            
12
/**
13
 * A host implementation that can have its address changed during request
14
 * processing in order to create temporal "real" hosts. This shares much of its
15
 * implementation with HostImpl, but has non-const address member variables that
16
 * are lock-protected.
17
 */
18
class LogicalHost : public HostImplBase, public HostDescriptionImplBase {
19
public:
20
  static absl::StatusOr<std::unique_ptr<LogicalHost>>
21
  create(const ClusterInfoConstSharedPtr& cluster, const std::string& hostname,
22
         const Network::Address::InstanceConstSharedPtr& address, const AddressVector& address_list,
23
         const envoy::config::endpoint::v3::LocalityLbEndpoints& locality_lb_endpoint,
24
         const envoy::config::endpoint::v3::LbEndpoint& lb_endpoint,
25
         const Network::TransportSocketOptionsConstSharedPtr& override_transport_socket_options);
26

            
27
  /**
28
   * Sets new addresses. This can be called dynamically during operation, and
29
   * is thread-safe.
30
   *
31
   * TODO: the health checker only gets the first address in the list and will
32
   * not walk the full happy eyeballs list. We should eventually fix this.
33
   *
34
   * TODO(jmarantz): change call-site to pass the address_list as a shared_ptr to
35
   * avoid having to copy it.
36
   *
37
   * @param address the primary address, also used for health checking
38
   * @param address_list alternative addresses; the first of these must be 'address'
39
   * @param lb_endpoint the load-balanced endpoint
40
   */
41
  void setNewAddresses(const Network::Address::InstanceConstSharedPtr& address,
42
                       const AddressVector& address_list,
43
                       const envoy::config::endpoint::v3::LbEndpoint& lb_endpoint);
44

            
45
  // Upstream::Host
46
  CreateConnectionData createConnection(
47
      Event::Dispatcher& dispatcher, const Network::ConnectionSocket::OptionsSharedPtr& options,
48
      Network::TransportSocketOptionsConstSharedPtr transport_socket_options) const override;
49

            
50
  // Upstream::HostDescription
51
  SharedConstAddressVector addressListOrNull() const override;
52
  Network::Address::InstanceConstSharedPtr address() const override;
53
  Network::Address::InstanceConstSharedPtr healthCheckAddress() const override;
54

            
55
protected:
56
  LogicalHost(
57
      const ClusterInfoConstSharedPtr& cluster, const std::string& hostname,
58
      const Network::Address::InstanceConstSharedPtr& address, const AddressVector& address_list,
59
      const envoy::config::endpoint::v3::LocalityLbEndpoints& locality_lb_endpoint,
60
      const envoy::config::endpoint::v3::LbEndpoint& lb_endpoint,
61
      const Network::TransportSocketOptionsConstSharedPtr& override_transport_socket_options,
62
      absl::Status& creation_status);
63

            
64
private:
65
  const Network::TransportSocketOptionsConstSharedPtr override_transport_socket_options_;
66

            
67
  // The first entry in the address_list_ should match the value in address_.
68
  Network::Address::InstanceConstSharedPtr address_ ABSL_GUARDED_BY(address_lock_);
69
  SharedConstAddressVector address_list_or_null_ ABSL_GUARDED_BY(address_lock_);
70
  Network::Address::InstanceConstSharedPtr health_check_address_ ABSL_GUARDED_BY(address_lock_);
71
  mutable absl::Mutex address_lock_;
72
};
73

            
74
using LogicalHostSharedPtr = std::shared_ptr<LogicalHost>;
75

            
76
/**
77
 * A real host that forwards most of its calls to a logical host, but returns a snapped address.
78
 */
79
class RealHostDescription : public HostDescription {
80
public:
81
  RealHostDescription(Network::Address::InstanceConstSharedPtr address,
82
                      HostConstSharedPtr logical_host)
83
109
      : address_(address), logical_host_(logical_host) {}
84

            
85
  // Upstream:HostDescription observers are delegated to logical_host_.
86
177
  bool canary() const override { return logical_host_->canary(); }
87
112
  MetadataConstSharedPtr metadata() const override { return logical_host_->metadata(); }
88
  std::size_t metadataHash() const override { return logical_host_->metadataHash(); }
89
107
  const MetadataConstSharedPtr localityMetadata() const override {
90
107
    return logical_host_->localityMetadata();
91
107
  }
92

            
93
1
  Network::UpstreamTransportSocketFactory& transportSocketFactory() const override {
94
1
    return logical_host_->transportSocketFactory();
95
1
  }
96
560
  const ClusterInfo& cluster() const override { return logical_host_->cluster(); }
97
1
  bool canCreateConnection(Upstream::ResourcePriority priority) const override {
98
1
    return logical_host_->canCreateConnection(priority);
99
1
  }
100
4
  HealthCheckHostMonitor& healthChecker() const override { return logical_host_->healthChecker(); }
101
262
  Outlier::DetectorHostMonitor& outlierDetector() const override {
102
262
    return logical_host_->outlierDetector();
103
262
  }
104
106
  HostStats& stats() const override { return logical_host_->stats(); }
105
1
  LoadMetricStats& loadMetricStats() const override { return logical_host_->loadMetricStats(); }
106
4
  const std::string& hostnameForHealthChecks() const override {
107
4
    return logical_host_->hostnameForHealthChecks();
108
4
  }
109
26
  const std::string& hostname() const override { return logical_host_->hostname(); }
110
86
  Network::Address::InstanceConstSharedPtr address() const override { return address_; }
111
9
  SharedConstAddressVector addressListOrNull() const override {
112
9
    return logical_host_->addressListOrNull();
113
9
  }
114
12
  const envoy::config::core::v3::Locality& locality() const override {
115
12
    return logical_host_->locality();
116
12
  }
117
168
  Stats::StatName localityZoneStatName() const override {
118
168
    return logical_host_->localityZoneStatName();
119
168
  }
120
1
  Network::Address::InstanceConstSharedPtr healthCheckAddress() const override {
121
    // Should never be called since real hosts are used only for forwarding.
122
1
    return nullptr;
123
1
  }
124
4
  absl::optional<MonotonicTime> lastHcPassTime() const override {
125
4
    return logical_host_->lastHcPassTime();
126
4
  }
127
5
  uint32_t priority() const override { return logical_host_->priority(); }
128
  Network::UpstreamTransportSocketFactory& resolveTransportSocketFactory(
129
      const Network::Address::InstanceConstSharedPtr& dest_address,
130
      const envoy::config::core::v3::Metadata* metadata,
131
      Network::TransportSocketOptionsConstSharedPtr transport_socket_options =
132
1
          nullptr) const override {
133
1
    return logical_host_->resolveTransportSocketFactory(dest_address, metadata,
134
1
                                                        transport_socket_options);
135
1
  }
136
82
  OptRef<HostLbPolicyData> lbPolicyData() const override { return logical_host_->lbPolicyData(); }
137

            
138
  // Upstream:HostDescription mutators are all no-ops, because logical_host_ is
139
  // const. These should never be called except during coverage tests.
140
  //
141
  // There may be an argument to suggest that HostDescription should contain
142
  // only the immutable member variables and observers, and the mutable
143
  // sections, along with 'address' and 'addressList' should be part of
144
  // Host. This would not be a small change, but might enable multiple hosts to
145
  // share common HostDescriptions.
146
1
  void setOutlierDetector(Outlier::DetectorHostMonitorPtr&&) override {}
147
1
  void setHealthChecker(HealthCheckHostMonitorPtr&&) override {}
148
1
  void metadata(MetadataConstSharedPtr) override {}
149
1
  void canary(bool) override {}
150
1
  void setLastHcPassTime(MonotonicTime) override {}
151
1
  void priority(uint32_t) override {}
152
  void setLbPolicyData(HostLbPolicyDataPtr) override {}
153

            
154
private:
155
  const Network::Address::InstanceConstSharedPtr address_;
156
  const HostConstSharedPtr logical_host_;
157
};
158

            
159
} // namespace Upstream
160
} // namespace Envoy