• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef GRPC_SRC_CORE_XDS_GRPC_XDS_LISTENER_H
18 #define GRPC_SRC_CORE_XDS_GRPC_XDS_LISTENER_H
19 
20 #include <stdint.h>
21 #include <string.h>
22 
23 #include <algorithm>
24 #include <array>
25 #include <map>
26 #include <memory>
27 #include <string>
28 #include <vector>
29 
30 #include "absl/types/optional.h"
31 #include "absl/types/variant.h"
32 #include "src/core/lib/iomgr/resolved_address.h"
33 #include "src/core/util/time.h"
34 #include "src/core/xds/grpc/xds_common_types.h"
35 #include "src/core/xds/grpc/xds_http_filter.h"
36 #include "src/core/xds/grpc/xds_route_config.h"
37 #include "src/core/xds/xds_client/xds_resource_type.h"
38 #include "src/core/xds/xds_client/xds_resource_type_impl.h"
39 
40 namespace grpc_core {
41 
42 struct XdsListenerResource : public XdsResourceType::ResourceData {
43   struct HttpConnectionManager {
44     // The RDS resource name or inline RouteConfiguration.
45     absl::variant<std::string, std::shared_ptr<const XdsRouteConfigResource>>
46         route_config;
47 
48     // Storing the Http Connection Manager Common Http Protocol Option
49     // max_stream_duration
50     Duration http_max_stream_duration;
51 
52     struct HttpFilter {
53       std::string name;
54       XdsHttpFilterImpl::FilterConfig config;
55 
56       bool operator==(const HttpFilter& other) const {
57         return name == other.name && config == other.config;
58       }
59 
60       std::string ToString() const;
61     };
62     std::vector<HttpFilter> http_filters;
63 
64     bool operator==(const HttpConnectionManager& other) const {
65       if (absl::holds_alternative<std::string>(route_config)) {
66         if (route_config != other.route_config) return false;
67       } else {
68         auto& rc1 = absl::get<std::shared_ptr<const XdsRouteConfigResource>>(
69             route_config);
70         auto* rc2 = absl::get_if<std::shared_ptr<const XdsRouteConfigResource>>(
71             &other.route_config);
72         if (rc2 == nullptr) return false;
73         if (!(*rc1 == **rc2)) return false;
74       }
75       return http_max_stream_duration == other.http_max_stream_duration &&
76              http_filters == other.http_filters;
77     }
78 
79     std::string ToString() const;
80   };
81 
82   struct DownstreamTlsContext {
DownstreamTlsContextXdsListenerResource::DownstreamTlsContext83     DownstreamTlsContext() {}
84 
85     CommonTlsContext common_tls_context;
86     bool require_client_certificate = false;
87 
88     bool operator==(const DownstreamTlsContext& other) const {
89       return common_tls_context == other.common_tls_context &&
90              require_client_certificate == other.require_client_certificate;
91     }
92 
93     std::string ToString() const;
94     bool Empty() const;
95   };
96 
97   struct FilterChainData {
98     DownstreamTlsContext downstream_tls_context;
99     // This is in principle the filter list.
100     // We currently require exactly one filter, which is the HCM.
101     HttpConnectionManager http_connection_manager;
102 
103     bool operator==(const FilterChainData& other) const {
104       return downstream_tls_context == other.downstream_tls_context &&
105              http_connection_manager == other.http_connection_manager;
106     }
107 
108     std::string ToString() const;
109   };
110 
111   // A multi-level map used to determine which filter chain to use for a given
112   // incoming connection. Determining the right filter chain for a given
113   // connection checks the following properties, in order:
114   // - destination port (never matched, so not present in map)
115   // - destination IP address
116   // - server name (never matched, so not present in map)
117   // - transport protocol (allows only "raw_buffer" or unset, prefers the
118   //   former, so only one of those two types is present in map)
119   // - application protocol (never matched, so not present in map)
120   // - connection source type (any, local or external)
121   // - source IP address
122   // - source port
123   // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/listener/v3/listener_components.proto#config-listener-v3-filterchainmatch
124   // for more details
125   struct FilterChainMap {
126     struct FilterChainDataSharedPtr {
127       std::shared_ptr<FilterChainData> data;
128       bool operator==(const FilterChainDataSharedPtr& other) const {
129         return *data == *other.data;
130       }
131     };
132     struct CidrRange {
133       grpc_resolved_address address;
134       uint32_t prefix_len;
135 
136       bool operator==(const CidrRange& other) const {
137         return memcmp(&address, &other.address, sizeof(address)) == 0 &&
138                prefix_len == other.prefix_len;
139       }
140 
141       std::string ToString() const;
142     };
143     using SourcePortsMap = std::map<uint16_t, FilterChainDataSharedPtr>;
144     struct SourceIp {
145       absl::optional<CidrRange> prefix_range;
146       SourcePortsMap ports_map;
147 
148       bool operator==(const SourceIp& other) const {
149         return prefix_range == other.prefix_range &&
150                ports_map == other.ports_map;
151       }
152     };
153     using SourceIpVector = std::vector<SourceIp>;
154     enum class ConnectionSourceType { kAny = 0, kSameIpOrLoopback, kExternal };
155     using ConnectionSourceTypesArray = std::array<SourceIpVector, 3>;
156     struct DestinationIp {
157       absl::optional<CidrRange> prefix_range;
158       // We always fail match on server name, so those filter chains are not
159       // included here.
160       ConnectionSourceTypesArray source_types_array;
161 
162       bool operator==(const DestinationIp& other) const {
163         return prefix_range == other.prefix_range &&
164                source_types_array == other.source_types_array;
165       }
166     };
167     // We always fail match on destination ports map
168     using DestinationIpVector = std::vector<DestinationIp>;
169     DestinationIpVector destination_ip_vector;
170 
171     bool operator==(const FilterChainMap& other) const {
172       return destination_ip_vector == other.destination_ip_vector;
173     }
174 
175     std::string ToString() const;
176   };
177 
178   struct TcpListener {
179     std::string address;  // host:port listening address
180     FilterChainMap filter_chain_map;
181     absl::optional<FilterChainData> default_filter_chain;
182 
183     bool operator==(const TcpListener& other) const {
184       return address == other.address &&
185              filter_chain_map == other.filter_chain_map &&
186              default_filter_chain == other.default_filter_chain;
187     }
188 
189     std::string ToString() const;
190   };
191 
192   absl::variant<HttpConnectionManager, TcpListener> listener;
193 
194   bool operator==(const XdsListenerResource& other) const {
195     return listener == other.listener;
196   }
197 
198   std::string ToString() const;
199 };
200 
201 }  // namespace grpc_core
202 
203 #endif  // GRPC_SRC_CORE_XDS_GRPC_XDS_LISTENER_H
204