1
#pragma once
2

            
3
#include <memory>
4
#include <typeinfo>
5

            
6
#include "envoy/config/route/v3/scoped_route.pb.h"
7
#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h"
8
#include "envoy/router/rds.h"
9
#include "envoy/router/router.h"
10
#include "envoy/router/scopes.h"
11
#include "envoy/thread_local/thread_local.h"
12

            
13
#include "source/common/common/hash.h"
14
#include "source/common/protobuf/utility.h"
15
#include "source/common/router/config_impl.h"
16

            
17
#include "absl/numeric/int128.h"
18
#include "absl/strings/str_format.h"
19

            
20
namespace Envoy {
21
namespace Router {
22

            
23
using envoy::extensions::filters::network::http_connection_manager::v3::ScopedRoutes;
24

            
25
/**
26
 * Base class for fragment builders.
27
 */
28
class FragmentBuilderBase {
29
public:
30
  explicit FragmentBuilderBase(ScopedRoutes::ScopeKeyBuilder::FragmentBuilder&& config)
31
130
      : config_(std::move(config)) {}
32
130
  virtual ~FragmentBuilderBase() = default;
33

            
34
  // Returns a fragment if the fragment rule applies, a nullptr indicates no fragment could be
35
  // generated from the headers.
36
  virtual std::unique_ptr<ScopeKeyFragmentBase>
37
  computeFragment(const Http::HeaderMap& headers) const PURE;
38

            
39
protected:
40
  const ScopedRoutes::ScopeKeyBuilder::FragmentBuilder config_;
41
};
42

            
43
class HeaderValueExtractorImpl : public FragmentBuilderBase {
44
public:
45
  explicit HeaderValueExtractorImpl(ScopedRoutes::ScopeKeyBuilder::FragmentBuilder&& config);
46

            
47
  std::unique_ptr<ScopeKeyFragmentBase>
48
  computeFragment(const Http::HeaderMap& headers) const override;
49

            
50
private:
51
  const ScopedRoutes::ScopeKeyBuilder::FragmentBuilder::HeaderValueExtractor&
52
      header_value_extractor_config_;
53
};
54

            
55
/**
56
 * Base class for ScopeKeyBuilder implementations.
57
 */
58
class ScopeKeyBuilderBase : public ScopeKeyBuilder {
59
public:
60
  explicit ScopeKeyBuilderBase(ScopedRoutes::ScopeKeyBuilder&& config)
61
121
      : config_(std::move(config)) {}
62

            
63
protected:
64
  const ScopedRoutes::ScopeKeyBuilder config_;
65
};
66

            
67
class ScopeKeyBuilderImpl : public ScopeKeyBuilderBase {
68
public:
69
  explicit ScopeKeyBuilderImpl(ScopedRoutes::ScopeKeyBuilder&& config);
70

            
71
  ScopeKeyPtr computeScopeKey(const Http::HeaderMap& headers) const override;
72

            
73
private:
74
  std::vector<std::unique_ptr<FragmentBuilderBase>> fragment_builders_;
75
};
76

            
77
// ScopedRouteConfiguration and corresponding RouteConfigProvider.
78
class ScopedRouteInfo {
79
public:
80
  ScopedRouteInfo(envoy::config::route::v3::ScopedRouteConfiguration&& config_proto,
81
                  ConfigConstSharedPtr route_config);
82

            
83
390
  const ConfigConstSharedPtr& routeConfig() const { return route_config_; }
84
1200
  const ScopeKey& scopeKey() const { return scope_key_; }
85
190
  const envoy::config::route::v3::ScopedRouteConfiguration& configProto() const {
86
190
    return config_proto_;
87
190
  }
88
1494
  const std::string& scopeName() const { return config_proto_.name(); }
89
41
  uint64_t configHash() const { return config_hash_; }
90

            
91
private:
92
  const envoy::config::route::v3::ScopedRouteConfiguration config_proto_;
93
  ScopeKey scope_key_;
94
  const ConfigConstSharedPtr route_config_;
95
  const uint64_t config_hash_;
96
};
97
using ScopedRouteInfoConstSharedPtr = std::shared_ptr<const ScopedRouteInfo>;
98
// Ordered map for consistent config dumping.
99
using ScopedRouteMap = std::map<std::string, ScopedRouteInfoConstSharedPtr>;
100

            
101
/**
102
 * Each Envoy worker is assigned an instance of this type. When config updates are received,
103
 * addOrUpdateRoutingScope() and removeRoutingScope() are called to update the set of scoped routes.
104
 *
105
 * ConnectionManagerImpl::refreshCachedRoute() will call getRouterConfig() to obtain the
106
 * Router::ConfigConstSharedPtr to use for route selection.
107
 */
108
class ScopedConfigImpl : public ScopedConfig {
109
public:
110
187
  ScopedConfigImpl() = default;
111

            
112
6
  ScopedConfigImpl(const std::vector<ScopedRouteInfoConstSharedPtr>& scoped_route_infos) {
113
6
    addOrUpdateRoutingScopes(scoped_route_infos);
114
6
  }
115

            
116
  void
117
  addOrUpdateRoutingScopes(const std::vector<ScopedRouteInfoConstSharedPtr>& scoped_route_infos);
118

            
119
  void removeRoutingScopes(const std::vector<std::string>& scope_names);
120

            
121
  // Envoy::Router::ScopedConfig
122
  Router::ConfigConstSharedPtr getRouteConfig(const ScopeKeyPtr& scope_key) const override;
123

            
124
private:
125
  // From scope name to cached ScopedRouteInfo.
126
  absl::flat_hash_map<std::string, ScopedRouteInfoConstSharedPtr> scoped_route_info_by_name_;
127
  // Hash by ScopeKey hash to lookup in constant time.
128
  absl::flat_hash_map<uint64_t, ScopedRouteInfoConstSharedPtr> scoped_route_info_by_key_;
129
};
130

            
131
/**
132
 * A NULL implementation of the scoped routing configuration.
133
 */
134
class NullScopedConfigImpl : public ScopedConfig {
135
public:
136
  Router::ConfigConstSharedPtr getRouteConfig(const ScopeKeyPtr&) const override {
137
    return std::make_shared<const NullConfigImpl>();
138
  }
139
};
140

            
141
} // namespace Router
142
} // namespace Envoy