Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
d182cbe
wip: get an api listener at all costs
Dec 23, 2019
3c36ef8
fmt build
Dec 23, 2019
d91b112
building and worksgit add source/! :tada:
Dec 24, 2019
c6f2d8a
initial clean up. Builds, tested
Dec 26, 2019
31b8ecd
Merge branch 'master' into api-listener
Dec 26, 2019
cfa81d8
fmt
Dec 27, 2019
538d73c
back to singleton. ApiListener and ApiListenerHandle interfaces
Dec 27, 2019
ad81348
fmt
Dec 27, 2019
e617918
comments
Dec 28, 2019
efe5cff
comments split up
Dec 28, 2019
2760a21
move read callbacks outside of the lambda
Dec 28, 2019
1a57cf0
comment
Dec 28, 2019
d74abb6
fmt
Dec 28, 2019
5684186
change api listener to implemented
Dec 28, 2019
1427f3e
fixes
Dec 29, 2019
06d0043
Merge branch 'master' of https://github.com/envoyproxy/envoy into api…
Jan 2, 2020
3dd0b13
fmt
Jan 2, 2020
9f6094b
fmt, with clang-format 9
Jan 2, 2020
65e3a71
does this work with proto formatting?
Jan 2, 2020
c9f429b
change to implemented
Jan 2, 2020
c8f9658
Merge branch 'master' into api-listener
Jan 2, 2020
9647159
Merge branch 'master' into api-listener
Jan 3, 2020
dad95f6
remove acronym
Jan 3, 2020
25d9494
generated
Jan 3, 2020
45ec135
Merge branch 'master' into api-listener
Jan 6, 2020
542ceda
missing bazel deps
Jan 6, 2020
ae1442c
finish updating from merge
Jan 6, 2020
1df8a3e
comments
Jan 7, 2020
8354ad9
comments
Jan 7, 2020
8624c14
generated
Jan 7, 2020
6de2dbc
comments
Jan 7, 2020
1c68d73
accidental commit
Jan 7, 2020
f4e8d9e
Merge branch 'master' into api-listener
Jan 9, 2020
b2c9ba5
fmt
Jan 9, 2020
ce59043
comments
Jan 10, 2020
7ce32a5
fmt
Jan 10, 2020
6f242d9
Merge branch 'master' into api-listener
Jan 10, 2020
6e2ee13
bad merge
Jan 10, 2020
df69e8c
move stats back. my test will fail
Jan 11, 2020
0ce64d4
adjust
Jan 11, 2020
ed5e8e6
type
Jan 11, 2020
cacb666
fmt
Jan 11, 2020
c5f629a
test
Jan 11, 2020
ba3d861
spell
Jan 11, 2020
2116afa
stats
Jan 11, 2020
246eb28
Merge branch 'master' into api-listener
Jan 13, 2020
50cb982
Merge branch 'api-listener' of github.com:junr03/envoy into api-listener
Jan 14, 2020
e1c789e
comments and test
Jan 15, 2020
9b99e58
factory context
Jan 15, 2020
7d8ffe3
Merge branch 'master' into api-listener
Jan 15, 2020
cd640b3
hcm
Jan 15, 2020
63c3afb
Merge branch 'master' into api-listener
Jan 15, 2020
4d47fa5
optional reference_wrapper
Jan 15, 2020
516b71b
Merge branch 'master' into api-listener
Jan 16, 2020
835adbb
comments
Jan 17, 2020
77a5570
nits
Jan 17, 2020
7442f86
Merge branch 'master' into api-listener
Jan 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions api/envoy/config/listener/v2/api_listener.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@ option java_package = "io.envoyproxy.envoy.config.listener.v2";
option java_outer_classname = "ApiListenerProto";
option java_multiple_files = true;

// [#not-implemented-hide:]
// Describes a type of API listener, which is used in non-proxy clients. The type of API
// exposed to the non-proxy application depends on the type of API listener.
message ApiListener {
// The type in this field determines the type of API listener. At present, the following
// types are supported:
// envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager (HTTP)
// types are supported: envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager (HTTP)
// [#next-major-version: In the v3 API, replace this Any field with a oneof containing the
// specific config message for each type of API listener. We could not do this in v2 because
// it would have caused circular dependencies for go protos: lds.proto depends on this file,
Expand Down
1 change: 1 addition & 0 deletions include/envoy/http/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ envoy_cc_library(
":protocol_interface",
"//include/envoy/buffer:buffer_interface",
"//include/envoy/network:address_interface",
"//include/envoy/server:api_listener_interface",
],
)

Expand Down
6 changes: 5 additions & 1 deletion include/envoy/http/codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "envoy/http/metadata_interface.h"
#include "envoy/http/protocol.h"
#include "envoy/network/address.h"
#include "envoy/server/api_listener.h"

namespace Envoy {
namespace Http {
Expand Down Expand Up @@ -413,7 +414,8 @@ class DownstreamWatermarkCallbacks {
/**
* Callbacks for server connections.
*/
class ServerConnectionCallbacks : public virtual ConnectionCallbacks {
class ServerConnectionCallbacks : public virtual ConnectionCallbacks,
public virtual Server::ApiListenerHandle {
public:
/**
* Invoked when a new request stream is initiated by the remote.
Expand All @@ -427,6 +429,8 @@ class ServerConnectionCallbacks : public virtual ConnectionCallbacks {
bool is_internally_created = false) PURE;
};

using ServerConnectionCallbacksPtr = std::unique_ptr<ServerConnectionCallbacks>;

/**
* A server side HTTP connection.
*/
Expand Down
5 changes: 5 additions & 0 deletions include/envoy/server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "api_listener_interface",
hdrs = ["api_listener.h"],
)

envoy_cc_library(
name = "configuration_interface",
hdrs = ["configuration.h"],
Expand Down
39 changes: 39 additions & 0 deletions include/envoy/server/api_listener.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

namespace Envoy {
namespace Server {

/**
* Handle provided to users to interact with Envoy via a particular API.
* Given the flexibility of the api_listener config, this interface is also maximally flexible.
* Consumers of this interface have to cast this handle to narrower types.
*/
class ApiListenerHandle {
Comment thread
junr03 marked this conversation as resolved.
Outdated
public:
virtual ~ApiListenerHandle() = default;
};

/**
* Listener that provides an API to interact with Envoy via a handle.
*/
class ApiListener {
public:
virtual ~ApiListener() = default;

/**
* An ApiListener is uniquely identified by its name.
*
* @return the name of the ApiListener.
*/
virtual absl::string_view name() const PURE;

/**
* @return a handle for interaction, nullptr if the Listener can not construct one.
*/
virtual ApiListenerHandle* handle() PURE;
};

using ApiListenerPtr = std::unique_ptr<ApiListener>;

} // namespace Server
} // namespace Envoy
9 changes: 9 additions & 0 deletions include/envoy/server/listener_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,15 @@ class ListenerManager {
*/
using FailureStates = std::vector<std::unique_ptr<envoy::admin::v2alpha::UpdateFailureState>>;
virtual void endListenerUpdate(FailureStates&& failure_states) PURE;

// TODO(junr03): once ApiListeners support warming and draining, this function should return a
// weak_ptr of the ApiListenerHandle to its caller. This would allow the caller to verify if the
// ApiListener that backs the handle is available to receive API calls on it.
/**
* @return ApiListenerHandle* a handle to the API Listener if it exists, nullptr if
* it does not.
*/
virtual ApiListenerHandle* apiListener() PURE;
};

} // namespace Server
Expand Down
5 changes: 5 additions & 0 deletions source/common/http/conn_manager_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ void ConnectionManagerImpl::handleCodecException(const char* error) {
read_callbacks_->connection().close(Network::ConnectionCloseType::FlushWriteAndDelay);
}

void ConnectionManagerImpl::forceCodecCreation() {
Comment thread
junr03 marked this conversation as resolved.
Outdated
ASSERT(!codec_);
codec_ = config_.createCodec(read_callbacks_->connection(), Buffer::OwnedImpl(), *this);
}

Network::FilterStatus ConnectionManagerImpl::onData(Buffer::Instance& data, bool) {
if (!codec_) {
// Http3 codec should have been instantiated by now.
Expand Down
9 changes: 9 additions & 0 deletions source/common/http/conn_manager_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ class ConnectionManagerImpl : Logger::Loggable<Logger::Id::http>,
Stats::Scope& scope);
static const HeaderMapImpl& continueHeader();

// Currently the ConnectionManager creates a codec lazily when either:
// a) onConnection for H3.
// b) onData for H1 and H2.
// With the introduction of ApiListeners, neither even occurs. This function allows us to force
Comment thread
junr03 marked this conversation as resolved.
Outdated
// create a codec.
// TODO(junr03): consider passing a synthetic codec instead of creating once. The codec in the
// ApiListener case is solely used to determine the protocol version.
void forceCodecCreation();

// Network::ReadFilter
Network::FilterStatus onData(Buffer::Instance& data, bool end_stream) override;
Network::FilterStatus onNewConnection() override;
Expand Down
4 changes: 1 addition & 3 deletions source/extensions/filters/network/common/redis/codec_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -383,9 +383,7 @@ void DecoderImpl::parseSlice(const Buffer::RawSlice& slice) {
pending_value_stack_.front().value_->type(RespType::Integer);
break;
}
default: {
throw ProtocolError("invalid value type");
}
default: { throw ProtocolError("invalid value type"); }
}

remaining--;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ envoy_cc_extension(
deps = [
"//include/envoy/config:config_provider_manager_interface",
"//include/envoy/filesystem:filesystem_interface",
"//include/envoy/http:codec_interface",
"//include/envoy/http:filter_interface",
"//include/envoy/registry",
"//include/envoy/router:route_config_provider_manager_interface",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,74 @@ const Network::Address::Instance& HttpConnectionManagerConfig::localAddress() {
return *context_.localInfo().address();
}

// Singleton registration via macro defined in envoy/singleton/manager.h
SINGLETON_MANAGER_REGISTRATION(hcm_date_provider);
SINGLETON_MANAGER_REGISTRATION(hcm_route_config_provider_manager);
SINGLETON_MANAGER_REGISTRATION(hcm_scoped_routes_config_provider_manager);

// TODO(junr03): some of this code can be DRYed up and shared with the other factory code. Clean up
// if this factory approach is well received by reviewers.
std::function<Http::ServerConnectionCallbacksPtr()>
HttpConnectionManagerFactory::createHttpConnectionManagerFactoryFromProto(
const ProtobufWkt::Any& proto_config, Server::Configuration::FactoryContext& context,
Network::ReadFilterCallbacks& read_callbacks) {
auto typed_config = MessageUtil::anyConvert<
envoy::config::filter::network::http_connection_manager::v2::HttpConnectionManager>(
proto_config);

std::shared_ptr<Http::TlsCachingDateProviderImpl> hcm_date_provider =
context.singletonManager().getTyped<Http::TlsCachingDateProviderImpl>(
SINGLETON_MANAGER_REGISTERED_NAME(hcm_date_provider), [&context] {
return std::make_shared<Http::TlsCachingDateProviderImpl>(context.dispatcher(),
context.threadLocal());
});

std::shared_ptr<Router::RouteConfigProviderManager> hcm_route_config_provider_manager =
context.singletonManager().getTyped<Router::RouteConfigProviderManager>(
SINGLETON_MANAGER_REGISTERED_NAME(hcm_route_config_provider_manager), [&context] {
return std::make_shared<Router::RouteConfigProviderManagerImpl>(context.admin());
});

std::shared_ptr<Router::ScopedRoutesConfigProviderManager>
hcm_scoped_routes_config_provider_manager =
context.singletonManager().getTyped<Router::ScopedRoutesConfigProviderManager>(
SINGLETON_MANAGER_REGISTERED_NAME(hcm_scoped_routes_config_provider_manager),
[&context, hcm_route_config_provider_manager] {
return std::make_shared<Router::ScopedRoutesConfigProviderManager>(
context.admin(), *hcm_route_config_provider_manager);
});

std::shared_ptr<HttpConnectionManagerConfig> filter_config(new HttpConnectionManagerConfig(
typed_config, context, *hcm_date_provider, *hcm_route_config_provider_manager,
*hcm_scoped_routes_config_provider_manager));

// This lambda captures the shared_ptrs created above, thus preserving the
// reference count.
// Keep in mind the lambda capture list **doesn't** determine the destruction order, but it's fine
// as these captured objects are also global singletons.
return [hcm_scoped_routes_config_provider_manager, hcm_route_config_provider_manager,
hcm_date_provider, filter_config, &context,
&read_callbacks]() -> Http::ServerConnectionCallbacksPtr {
auto conn_manager = std::make_unique<Http::ConnectionManagerImpl>(
*filter_config, context.drainDecision(), context.random(), context.httpContext(),
context.runtime(), context.localInfo(), context.clusterManager(),
&context.overloadManager(), context.dispatcher().timeSource());

// This factory creates a new ConnectionManagerImpl in the absence of its usual environment as
// an L4 filter, so this factory needs to take a few actions.

// When a new connection is creating its filter chain it hydrates the factory with a filter
// manager which provides the ConnectionManager with its "read_callbacks".
conn_manager->initializeReadFilterCallbacks(read_callbacks);

// When the connection first calls onData on the ConnectionManager, the ConnectionManager
// creates a codec. Here we force create a codec as onData will not be called.
conn_manager->forceCodecCreation();

return conn_manager;
};
}

} // namespace HttpConnectionManager
} // namespace NetworkFilters
} // namespace Extensions
Expand Down
12 changes: 12 additions & 0 deletions source/extensions/filters/network/http_connection_manager/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "envoy/config/config_provider_manager.h"
#include "envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.pb.h"
#include "envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.pb.validate.h"
#include "envoy/http/codec.h"
#include "envoy/http/filter.h"
#include "envoy/router/route_config_provider_manager.h"

Expand Down Expand Up @@ -199,6 +200,17 @@ class HttpConnectionManagerConfig : Logger::Loggable<Logger::Id::config>,
static const uint64_t RequestTimeoutMs = 0;
};

/**
* Factory to create an HttpConnectionManager outside of a Network Filter Chain.
*/
class HttpConnectionManagerFactory {
public:
static std::function<Http::ServerConnectionCallbacksPtr()>
createHttpConnectionManagerFactoryFromProto(const ProtobufWkt::Any& proto_config,
Comment thread
junr03 marked this conversation as resolved.
Outdated
Server::Configuration::FactoryContext& context,
Network::ReadFilterCallbacks& read_callbacks);
};

} // namespace HttpConnectionManager
} // namespace NetworkFilters
} // namespace Extensions
Expand Down
33 changes: 33 additions & 0 deletions source/server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,32 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "api_listener_lib",
srcs = [
"api_listener_impl.cc",
],
hdrs = [
"api_listener_impl.h",
],
deps = [
":drain_manager_lib",
":listener_manager_impl",
"//include/envoy/network:connection_interface",
"//include/envoy/server:api_listener_interface",
"//include/envoy/server:filter_config_interface",
"//include/envoy/server:listener_manager_interface",
"//source/common/common:empty_string",
"//source/common/http:conn_manager_lib",
"//source/common/init:manager_lib",
"//source/common/network:resolver_lib",
"//source/common/stream_info:stream_info_lib",
"//source/extensions/filters/network/http_connection_manager:config",
"@envoy_api//envoy/api/v2:pkg_cc_proto",
"@envoy_api//envoy/api/v2/listener:pkg_cc_proto",
],
)

envoy_cc_library(
name = "listener_lib",
srcs = [
Expand Down Expand Up @@ -298,12 +324,16 @@ envoy_cc_library(
],
)

# TODO(junr03): actually separate this lib from the listener and api listener lib.
# this can be done if the parent_ in the listener and the api listener becomes the ListenerManager interface.
# the issue right now is that the listener's reach into the listener manager's server_ instance variable.
envoy_cc_library(
name = "listener_manager_impl",
srcs = [
"listener_manager_impl.cc",
],
hdrs = [
"api_listener_impl.h",
"listener_impl.h",
"listener_manager_impl.h",
],
Expand All @@ -320,12 +350,14 @@ envoy_cc_library(
"//include/envoy/server:transport_socket_config_interface",
"//include/envoy/server:worker_interface",
"//source/common/config:utility_lib",
"//source/common/http:conn_manager_lib",
"//source/common/init:manager_lib",
"//source/common/network:listen_socket_lib",
"//source/common/network:socket_option_factory_lib",
"//source/common/network:utility_lib",
"//source/common/protobuf:utility_lib",
"//source/extensions/filters/listener:well_known_names",
"//source/extensions/filters/network/http_connection_manager:config",
"//source/extensions/transport_sockets:well_known_names",
"@envoy_api//envoy/admin/v2alpha:pkg_cc_proto",
"@envoy_api//envoy/api/v2:pkg_cc_proto",
Expand Down Expand Up @@ -385,6 +417,7 @@ envoy_cc_library(
],
deps = [
":active_raw_udp_listener_config",
":api_listener_lib",
":configuration_lib",
":connection_handler_lib",
":guarddog_lib",
Expand Down
Loading