1
#include "source/extensions/transport_sockets/tcp_stats/config.h"
2

            
3
#include "envoy/extensions/transport_sockets/tcp_stats/v3/tcp_stats.pb.validate.h"
4
#include "envoy/registry/registry.h"
5
#include "envoy/server/transport_socket_config.h"
6

            
7
#include "source/common/config/utility.h"
8
#include "source/extensions/transport_sockets/tcp_stats/tcp_stats.h"
9

            
10
namespace Envoy {
11
namespace Extensions {
12
namespace TransportSockets {
13
namespace TcpStats {
14

            
15
TcpStatsSocketFactory::TcpStatsSocketFactory(
16
    Server::Configuration::TransportSocketFactoryContext& context,
17
4
    const envoy::extensions::transport_sockets::tcp_stats::v3::Config& config) {
18
4
#if defined(__linux__)
19
4
  config_ = std::make_shared<Config>(config, context.statsScope());
20
#else
21
  UNREFERENCED_PARAMETER(config);
22
  UNREFERENCED_PARAMETER(context);
23
  throw EnvoyException("envoy.transport_sockets.tcp_stats is not supported on this platform.");
24
#endif
25
4
}
26

            
27
UpstreamTcpStatsSocketFactory::UpstreamTcpStatsSocketFactory(
28
    Server::Configuration::TransportSocketFactoryContext& context,
29
    const envoy::extensions::transport_sockets::tcp_stats::v3::Config& config,
30
    Network::UpstreamTransportSocketFactoryPtr&& inner_factory)
31
3
    : TcpStatsSocketFactory(context, config), PassthroughFactory(std::move(inner_factory)) {}
32

            
33
Network::TransportSocketPtr UpstreamTcpStatsSocketFactory::createTransportSocket(
34
    Network::TransportSocketOptionsConstSharedPtr options,
35
2
    Upstream::HostDescriptionConstSharedPtr host) const {
36
2
#if defined(__linux__)
37
2
  auto inner_socket = transport_socket_factory_->createTransportSocket(options, host);
38
2
  if (inner_socket == nullptr) {
39
1
    return nullptr;
40
1
  }
41
1
  return std::make_unique<TcpStatsSocket>(config_, std::move(inner_socket));
42
#else
43
  UNREFERENCED_PARAMETER(options);
44
  UNREFERENCED_PARAMETER(host);
45
  return nullptr;
46
#endif
47
2
}
48

            
49
DownstreamTcpStatsSocketFactory::DownstreamTcpStatsSocketFactory(
50
    Server::Configuration::TransportSocketFactoryContext& context,
51
    const envoy::extensions::transport_sockets::tcp_stats::v3::Config& config,
52
    Network::DownstreamTransportSocketFactoryPtr&& inner_factory)
53
1
    : TcpStatsSocketFactory(context, config),
54
1
      DownstreamPassthroughFactory(std::move(inner_factory)) {}
55

            
56
Network::TransportSocketPtr
57
1
DownstreamTcpStatsSocketFactory::createDownstreamTransportSocket() const {
58
1
#if defined(__linux__)
59
1
  auto inner_socket = transport_socket_factory_->createDownstreamTransportSocket();
60
1
  if (inner_socket == nullptr) {
61
    return nullptr;
62
  }
63
1
  return std::make_unique<TcpStatsSocket>(config_, std::move(inner_socket));
64
#else
65
  return nullptr;
66
#endif
67
1
}
68

            
69
class TcpStatsConfigFactory : public virtual Server::Configuration::TransportSocketConfigFactory {
70
public:
71
14
  std::string name() const override { return "envoy.transport_sockets.tcp_stats"; }
72
8
  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
73
8
    return std::make_unique<envoy::extensions::transport_sockets::tcp_stats::v3::Config>();
74
8
  }
75
};
76

            
77
class UpstreamTcpStatsConfigFactory
78
    : public Server::Configuration::UpstreamTransportSocketConfigFactory,
79
      public TcpStatsConfigFactory {
80
public:
81
  absl::StatusOr<Network::UpstreamTransportSocketFactoryPtr> createTransportSocketFactory(
82
      const Protobuf::Message& config,
83
1
      Server::Configuration::TransportSocketFactoryContext& context) override {
84
1
    const auto& outer_config = MessageUtil::downcastAndValidate<
85
1
        const envoy::extensions::transport_sockets::tcp_stats::v3::Config&>(
86
1
        config, context.messageValidationVisitor());
87
1
    auto& inner_config_factory = Envoy::Config::Utility::getAndCheckFactory<
88
1
        Server::Configuration::UpstreamTransportSocketConfigFactory>(
89
1
        outer_config.transport_socket());
90
1
    ProtobufTypes::MessagePtr inner_factory_config =
91
1
        Envoy::Config::Utility::translateToFactoryConfig(outer_config.transport_socket(),
92
1
                                                         context.messageValidationVisitor(),
93
1
                                                         inner_config_factory);
94
1
    auto factory_or_error =
95
1
        inner_config_factory.createTransportSocketFactory(*inner_factory_config, context);
96
1
    RETURN_IF_NOT_OK_REF(factory_or_error.status());
97
1
    return std::make_unique<UpstreamTcpStatsSocketFactory>(context, outer_config,
98
1
                                                           std::move(factory_or_error.value()));
99
1
  }
100
};
101

            
102
class DownstreamTcpStatsConfigFactory
103
    : public Server::Configuration::DownstreamTransportSocketConfigFactory,
104
      public TcpStatsConfigFactory {
105
public:
106
  absl::StatusOr<Network::DownstreamTransportSocketFactoryPtr>
107
  createTransportSocketFactory(const Protobuf::Message& config,
108
                               Server::Configuration::TransportSocketFactoryContext& context,
109
1
                               const std::vector<std::string>& server_names) override {
110
1
    const auto& outer_config = MessageUtil::downcastAndValidate<
111
1
        const envoy::extensions::transport_sockets::tcp_stats::v3::Config&>(
112
1
        config, context.messageValidationVisitor());
113
1
    auto& inner_config_factory = Envoy::Config::Utility::getAndCheckFactory<
114
1
        Server::Configuration::DownstreamTransportSocketConfigFactory>(
115
1
        outer_config.transport_socket());
116
1
    ProtobufTypes::MessagePtr inner_factory_config =
117
1
        Envoy::Config::Utility::translateToFactoryConfig(outer_config.transport_socket(),
118
1
                                                         context.messageValidationVisitor(),
119
1
                                                         inner_config_factory);
120
1
    auto factory_or_error = inner_config_factory.createTransportSocketFactory(
121
1
        *inner_factory_config, context, server_names);
122
1
    RETURN_IF_NOT_OK_REF(factory_or_error.status());
123
1
    return std::make_unique<DownstreamTcpStatsSocketFactory>(context, outer_config,
124
1
                                                             std::move(factory_or_error.value()));
125
1
  }
126
};
127

            
128
REGISTER_FACTORY(UpstreamTcpStatsConfigFactory,
129
                 Server::Configuration::UpstreamTransportSocketConfigFactory);
130

            
131
REGISTER_FACTORY(DownstreamTcpStatsConfigFactory,
132
                 Server::Configuration::DownstreamTransportSocketConfigFactory);
133

            
134
} // namespace TcpStats
135
} // namespace TransportSockets
136
} // namespace Extensions
137
} // namespace Envoy