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

            
3
#include "envoy/common/hashable.h"
4
#include "envoy/common/optref.h"
5
#include "envoy/extensions/transport_sockets/internal_upstream/v3/internal_upstream.pb.validate.h"
6
#include "envoy/registry/registry.h"
7

            
8
#include "source/common/common/scalar_to_byte_vector.h"
9
#include "source/common/config/utility.h"
10
#include "source/extensions/transport_sockets/internal_upstream/internal_upstream.h"
11

            
12
namespace Envoy {
13
namespace Extensions {
14
namespace TransportSockets {
15
namespace InternalUpstream {
16

            
17
namespace {
18

            
19
class InternalUpstreamConfigFactory
20
    : public Server::Configuration::UpstreamTransportSocketConfigFactory {
21
public:
22
44
  std::string name() const override { return "envoy.transport_sockets.internal_upstream"; }
23
20
  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
24
20
    return std::make_unique<
25
20
        envoy::extensions::transport_sockets::internal_upstream::v3::InternalUpstreamTransport>();
26
20
  }
27
  absl::StatusOr<Network::UpstreamTransportSocketFactoryPtr> createTransportSocketFactory(
28
      const Protobuf::Message& config,
29
16
      Server::Configuration::TransportSocketFactoryContext& context) override {
30
16
    const auto& outer_config =
31
16
        MessageUtil::downcastAndValidate<const envoy::extensions::transport_sockets::
32
16
                                             internal_upstream::v3::InternalUpstreamTransport&>(
33
16
            config, context.messageValidationVisitor());
34
16
    auto& inner_config_factory = Envoy::Config::Utility::getAndCheckFactory<
35
16
        Server::Configuration::UpstreamTransportSocketConfigFactory>(
36
16
        outer_config.transport_socket());
37
16
    ProtobufTypes::MessagePtr inner_factory_config =
38
16
        Envoy::Config::Utility::translateToFactoryConfig(outer_config.transport_socket(),
39
16
                                                         context.messageValidationVisitor(),
40
16
                                                         inner_config_factory);
41
16
    auto factory_or_error =
42
16
        inner_config_factory.createTransportSocketFactory(*inner_factory_config, context);
43
16
    RETURN_IF_NOT_OK_REF(factory_or_error.status());
44
16
    return std::make_unique<InternalSocketFactory>(context, outer_config,
45
16
                                                   std::move(factory_or_error.value()));
46
16
  }
47
};
48

            
49
} // namespace
50

            
51
Config::Config(
52
    const envoy::extensions::transport_sockets::internal_upstream::v3::InternalUpstreamTransport&
53
        config_proto,
54
    Stats::Scope& scope)
55
20
    : stats_{ALL_INTERNAL_UPSTREAM_STATS(POOL_COUNTER_PREFIX(scope, "internal_upstream."))} {
56
37
  for (const auto& metadata : config_proto.passthrough_metadata()) {
57
37
    MetadataKind kind;
58
37
    switch (metadata.kind().kind_case()) {
59
18
    case envoy::type::metadata::v3::MetadataKind::KindCase::kHost:
60
18
      kind = MetadataKind::Host;
61
18
      break;
62
18
    case envoy::type::metadata::v3::MetadataKind::KindCase::kCluster:
63
18
      kind = MetadataKind::Cluster;
64
18
      break;
65
1
    default:
66
1
      throw EnvoyException(
67
1
          absl::StrCat("metadata type is not supported: ", metadata.kind().DebugString()));
68
37
    }
69
36
    metadata_sources_.push_back(MetadataSource(kind, metadata.name()));
70
36
  }
71
20
}
72

            
73
std::unique_ptr<envoy::config::core::v3::Metadata>
74
19
Config::extractMetadata(const Upstream::HostDescriptionConstSharedPtr& host) const {
75
19
  if (metadata_sources_.empty()) {
76
1
    return nullptr;
77
1
  }
78
18
  auto metadata = std::make_unique<envoy::config::core::v3::Metadata>();
79
36
  for (const auto& source : metadata_sources_) {
80
36
    OptRef<const envoy::config::core::v3::Metadata> source_metadata;
81
36
    switch (source.kind_) {
82
18
    case MetadataKind::Host: {
83
18
      if (host->metadata()) {
84
16
        source_metadata = makeOptRef(*host->metadata());
85
16
      }
86
18
      break;
87
    }
88
18
    case MetadataKind::Cluster:
89
18
      source_metadata = makeOptRef(host->cluster().metadata());
90
18
      break;
91
36
    }
92
36
    if (source_metadata && source_metadata->filter_metadata().contains(source.name_)) {
93
30
      (*metadata->mutable_filter_metadata())[source.name_] =
94
30
          source_metadata->filter_metadata().at(source.name_);
95
30
    } else {
96
6
      ENVOY_LOG(trace, "Internal upstream missing metadata: {}", source.name_);
97
6
      stats_.no_metadata_.inc();
98
6
    }
99
36
  }
100
18
  return metadata;
101
18
}
102

            
103
InternalSocketFactory::InternalSocketFactory(
104
    Server::Configuration::TransportSocketFactoryContext& context,
105
    const envoy::extensions::transport_sockets::internal_upstream::v3::InternalUpstreamTransport&
106
        config_proto,
107
    Network::UpstreamTransportSocketFactoryPtr&& inner_factory)
108
16
    : PassthroughFactory(std::move(inner_factory)), config_(config_proto, context.statsScope()) {}
109

            
110
Network::TransportSocketPtr
111
InternalSocketFactory::createTransportSocket(Network::TransportSocketOptionsConstSharedPtr options,
112
16
                                             Upstream::HostDescriptionConstSharedPtr host) const {
113
16
  auto inner_socket = transport_socket_factory_->createTransportSocket(options, host);
114
16
  if (inner_socket == nullptr) {
115
    return nullptr;
116
  }
117
16
  std::unique_ptr<envoy::config::core::v3::Metadata> extracted_metadata;
118
16
  if (host) {
119
16
    extracted_metadata = config_.extractMetadata(host);
120
16
  }
121
16
  return std::make_unique<InternalSocket>(std::move(inner_socket), std::move(extracted_metadata),
122
16
                                          options ? options->downstreamSharedFilterStateObjects()
123
16
                                                  : StreamInfo::FilterState::Objects());
124
16
}
125

            
126
REGISTER_FACTORY(InternalUpstreamConfigFactory,
127
                 Server::Configuration::UpstreamTransportSocketConfigFactory);
128

            
129
} // namespace InternalUpstream
130
} // namespace TransportSockets
131
} // namespace Extensions
132
} // namespace Envoy