1
#pragma once
2

            
3
#include "envoy/common/optref.h"
4
#include "envoy/config/subscription.h"
5
#include "envoy/service/discovery/v3/discovery.pb.h"
6

            
7
#include "source/common/protobuf/utility.h"
8

            
9
#include "xds/core/v3/collection_entry.pb.h"
10

            
11
namespace Envoy {
12
namespace Config {
13

            
14
namespace {
15

            
16
std::vector<std::string>
17
15165
repeatedPtrFieldToVector(const Protobuf::RepeatedPtrField<std::string>& xs) {
18
15165
  std::vector<std::string> ys;
19
15165
  std::copy(xs.begin(), xs.end(), std::back_inserter(ys));
20
15165
  return ys;
21
15165
}
22

            
23
} // namespace
24

            
25
class DecodedResourceImpl;
26
using DecodedResourceImplPtr = std::unique_ptr<DecodedResourceImpl>;
27

            
28
class DecodedResourceImpl : public DecodedResource {
29
public:
30
  static absl::StatusOr<DecodedResourceImplPtr>
31
  fromResource(OpaqueResourceDecoder& resource_decoder, const Protobuf::Any& resource,
32
13574
               const std::string& version) {
33
13574
    if (resource.Is<envoy::service::discovery::v3::Resource>()) {
34
330
      envoy::service::discovery::v3::Resource r;
35
330
      RETURN_IF_NOT_OK(MessageUtil::unpackTo(resource, r));
36
330
      r.set_version(version);
37
330
      return std::make_unique<DecodedResourceImpl>(resource_decoder, r);
38
330
    }
39

            
40
13244
    return std::unique_ptr<DecodedResourceImpl>(new DecodedResourceImpl(
41
13244
        resource_decoder, absl::nullopt, Protobuf::RepeatedPtrField<std::string>(), resource, true,
42
13244
        version, absl::nullopt, absl::nullopt));
43
13574
  }
44

            
45
  static DecodedResourceImplPtr
46
  fromResource(OpaqueResourceDecoder& resource_decoder,
47
14
               const envoy::service::discovery::v3::Resource& resource) {
48
14
    return std::make_unique<DecodedResourceImpl>(resource_decoder, resource);
49
14
  }
50

            
51
  DecodedResourceImpl(OpaqueResourceDecoder& resource_decoder,
52
                      const envoy::service::discovery::v3::Resource& resource)
53
1925
      : DecodedResourceImpl(
54
1925
            resource_decoder, resource.name(), resource.aliases(), resource.resource(),
55
1925
            resource.has_resource(), resource.version(),
56
1925
            resource.has_ttl() ? absl::make_optional(std::chrono::milliseconds(
57
52
                                     DurationUtil::durationToMilliseconds(resource.ttl())))
58
1925
                               : absl::nullopt,
59
1925
            resource.has_metadata() ? absl::make_optional(resource.metadata()) : absl::nullopt) {}
60
  DecodedResourceImpl(OpaqueResourceDecoder& resource_decoder,
61
                      const xds::core::v3::CollectionEntry::InlineEntry& inline_entry)
62
6
      : DecodedResourceImpl(resource_decoder, inline_entry.name(),
63
6
                            Protobuf::RepeatedPtrField<std::string>(), inline_entry.resource(),
64
6
                            true, inline_entry.version(), absl::nullopt, absl::nullopt) {}
65
  DecodedResourceImpl(ProtobufTypes::MessagePtr resource, const std::string& name,
66
                      const std::vector<std::string>& aliases, const std::string& version)
67
343
      : resource_(std::move(resource)), has_resource_(true), name_(name), aliases_(aliases),
68
343
        version_(version), ttl_(absl::nullopt), metadata_(absl::nullopt) {}
69

            
70
  // Config::DecodedResource
71
19826
  const std::string& name() const override { return name_; }
72
416
  const std::vector<std::string>& aliases() const override { return aliases_; }
73
13226
  const std::string& version() const override { return version_; };
74
16299
  const Protobuf::Message& resource() const override { return *resource_; };
75
2623
  bool hasResource() const override { return has_resource_; }
76
2216
  absl::optional<std::chrono::milliseconds> ttl() const override { return ttl_; }
77
31
  const OptRef<const envoy::config::core::v3::Metadata> metadata() const override {
78
31
    return metadata_.has_value() ? makeOptRef(metadata_.value()) : absl::nullopt;
79
31
  }
80

            
81
private:
82
  DecodedResourceImpl(OpaqueResourceDecoder& resource_decoder, absl::optional<std::string> name,
83
                      const Protobuf::RepeatedPtrField<std::string>& aliases,
84
                      const Protobuf::Any& resource, bool has_resource, const std::string& version,
85
                      absl::optional<std::chrono::milliseconds> ttl,
86
                      const absl::optional<envoy::config::core::v3::Metadata>& metadata)
87
15175
      : resource_(resource_decoder.decodeResource(resource)), has_resource_(has_resource),
88
15175
        name_(name ? *name : resource_decoder.resourceName(*resource_)),
89
15175
        aliases_(repeatedPtrFieldToVector(aliases)), version_(version), ttl_(ttl),
90
15175
        metadata_(metadata) {}
91

            
92
  const ProtobufTypes::MessagePtr resource_;
93
  const bool has_resource_;
94
  const std::string name_;
95
  const std::vector<std::string> aliases_;
96
  const std::string version_;
97
  // Per resource TTL.
98
  const absl::optional<std::chrono::milliseconds> ttl_;
99

            
100
  // This is the metadata info under the Resource wrapper.
101
  // It is intended to be consumed in the xds_config_tracker extension.
102
  const absl::optional<envoy::config::core::v3::Metadata> metadata_;
103
};
104

            
105
struct DecodedResourcesWrapper {
106
11041
  DecodedResourcesWrapper() = default;
107
  static absl::StatusOr<std::unique_ptr<DecodedResourcesWrapper>>
108
  create(OpaqueResourceDecoder& resource_decoder,
109
10557
         const Protobuf::RepeatedPtrField<Protobuf::Any>& resources, const std::string& version) {
110
10557
    std::unique_ptr<DecodedResourcesWrapper> ret = std::make_unique<DecodedResourcesWrapper>();
111
11422
    for (const auto& resource : resources) {
112
11393
      absl::StatusOr<DecodedResourceImplPtr> resource_or_error =
113
11393
          DecodedResourceImpl::fromResource(resource_decoder, resource, version);
114
11393
      RETURN_IF_NOT_OK_REF(resource_or_error.status());
115
11393
      ret->pushBack(std::move(resource_or_error.value()));
116
11393
    }
117
10557
    return ret;
118
10557
  }
119

            
120
11398
  void pushBack(Config::DecodedResourcePtr&& resource) {
121
11398
    owned_resources_.push_back(std::move(resource));
122
11398
    refvec_.emplace_back(*owned_resources_.back());
123
11398
  }
124

            
125
  std::vector<Config::DecodedResourcePtr> owned_resources_;
126
  std::vector<Config::DecodedResourceRef> refvec_;
127
};
128

            
129
} // namespace Config
130
} // namespace Envoy