From a32988ef8322c3cc0aa3d823821becc0612e6ca6 Mon Sep 17 00:00:00 2001 From: doujiang24 Date: Tue, 3 Jan 2023 17:23:14 +0800 Subject: [PATCH 1/3] compile ok. --- BUILD | 1 + api/http/cluster/v3/BUILD | 10 ++++ api/http/cluster/v3/cluster.proto | 28 +++++++++ src/envoy/common/dso/dso.cc | 31 ++++++++++ src/envoy/common/dso/dso.h | 6 ++ src/envoy/http/cluster/BUILD | 46 +++++++++++++++ src/envoy/http/cluster/config.cc | 25 ++++++++ src/envoy/http/cluster/config.h | 27 +++++++++ src/envoy/http/cluster/golang_cluster.cc | 74 ++++++++++++++++++++++++ src/envoy/http/cluster/golang_cluster.h | 47 +++++++++++++++ 10 files changed, 295 insertions(+) create mode 100644 api/http/cluster/v3/BUILD create mode 100644 api/http/cluster/v3/cluster.proto create mode 100644 src/envoy/http/cluster/BUILD create mode 100644 src/envoy/http/cluster/config.cc create mode 100644 src/envoy/http/cluster/config.h create mode 100644 src/envoy/http/cluster/golang_cluster.cc create mode 100644 src/envoy/http/cluster/golang_cluster.h diff --git a/BUILD b/BUILD index 4791847730..7cfad9246f 100644 --- a/BUILD +++ b/BUILD @@ -11,6 +11,7 @@ envoy_cc_binary( deps = [ "//src/envoy/bootstrap/dso:config", "//src/envoy/http/golang:config", + "//src/envoy/http/cluster:config", "@envoy//source/exe:envoy_main_entry_lib", ], ) diff --git a/api/http/cluster/v3/BUILD b/api/http/cluster/v3/BUILD new file mode 100644 index 0000000000..8088aee934 --- /dev/null +++ b/api/http/cluster/v3/BUILD @@ -0,0 +1,10 @@ +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = [ + "@com_github_cncf_udpa//udpa/annotations:pkg", + "@com_github_cncf_udpa//xds/annotations/v3:pkg", + ], +) diff --git a/api/http/cluster/v3/cluster.proto b/api/http/cluster/v3/cluster.proto new file mode 100644 index 0000000000..3fb81eccb2 --- /dev/null +++ b/api/http/cluster/v3/cluster.proto @@ -0,0 +1,28 @@ +syntax = "proto3"; + +package envoy.extensions.clusters.golang.v3; + +import "google/protobuf/any.proto"; +import "google/protobuf/struct.proto"; + +import "xds/annotations/v3/status.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.clusters.golang.v3"; +option java_outer_classname = "GolangProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/golang/v3;golangv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; +option (xds.annotations.v3.file_status).work_in_progress = true; + +message Config { + // A unique ID for a set of go plugin library. + string so_id = 1 [(validate.rules).string = {min_bytes: 1}]; + + string default_cluster = 2 [(validate.rules).string = {min_bytes: 1}]; + + // this configuration is only parsed in the go side. + google.protobuf.Any config = 3; +} diff --git a/src/envoy/common/dso/dso.cc b/src/envoy/common/dso/dso.cc index 79d6d69486..31f97c829f 100644 --- a/src/envoy/common/dso/dso.cc +++ b/src/envoy/common/dso/dso.cc @@ -118,6 +118,25 @@ DsoInstance::DsoInstance(const std::string dsoName) : dsoName_(dsoName) { ENVOY_LOG_MISC(error, "lib: {}, cannot find symbol: moeOnHttpDecodeDestroy, err: {}", dsoName, dlerror()); } + + func = dlsym(handler_, "moeNewClusterConfig"); + if (func) { + moeNewClusterConfig_ = reinterpret_cast(func); + } else { + loaded_ = false; + ENVOY_LOG_MISC(error, "lib: {}, cannot find symbol: moeNewClusterConfig, err: {}", dsoName, + dlerror()); + } + + func = dlsym(handler_, "moeOnClusterSpecify"); + if (func) { + moeOnClusterSpecify_ = + reinterpret_cast(func); + } else { + loaded_ = false; + ENVOY_LOG_MISC(error, "lib: {}, cannot find symbol: moeOnClusterSpecify, err: {}", dsoName, + dlerror()); + } } DsoInstance::~DsoInstance() { @@ -127,6 +146,8 @@ DsoInstance::~DsoInstance() { moeOnHttpData_ = nullptr; moeOnHttpSemaCallback_ = nullptr; moeOnHttpDestroy_ = nullptr; + moeNewClusterConfig_ = nullptr; + moeOnClusterSpecify_ = nullptr; if (handler_ != nullptr) { dlclose(handler_); @@ -166,5 +187,15 @@ void DsoInstance::moeOnHttpDestroy(httpRequest* p0, int p1) { moeOnHttpDestroy_(p0, GoUint64(p1)); } +GoUint64 DsoInstance::moeNewClusterConfig(GoUint64 p0, GoUint64 p1) { + assert(moeNewClusterConfig_ != nullptr); + return moeNewClusterConfig_(p0, p1); +} + +GoInt64 DsoInstance::moeOnClusterSpecify(GoUint64 p0, GoUint64 p1, GoUint64 p2, GoUint64 p3) { + assert(moeOnClusterSpecify_ != nullptr); + return moeOnClusterSpecify_(p0, p1, p2, p3); +} + } // namespace Dso } // namespace Envoy diff --git a/src/envoy/common/dso/dso.h b/src/envoy/common/dso/dso.h index ce6220be04..d837d4b772 100644 --- a/src/envoy/common/dso/dso.h +++ b/src/envoy/common/dso/dso.h @@ -26,6 +26,9 @@ class DsoInstance { void moeOnHttpDestroy(httpRequest* p0, int p1); + GoUint64 moeNewClusterConfig(GoUint64 p0, GoUint64 p1); + GoInt64 moeOnClusterSpecify(GoUint64 p0, GoUint64 p1, GoUint64 p2, GoUint64 p3); + bool loaded() { return loaded_; } private: @@ -41,6 +44,9 @@ class DsoInstance { void (*moeOnHttpSemaCallback_)(httpRequest* p0) = {nullptr}; + GoUint64 (*moeNewClusterConfig_)(GoUint64 p0, GoUint64 p1) = {nullptr}; + GoInt64 (*moeOnClusterSpecify_)(GoUint64 p0, GoUint64 p1, GoUint64 p2, GoUint64 p3) = {nullptr}; + void (*moeOnHttpDestroy_)(httpRequest* p0, GoUint64 p1) = {nullptr}; }; diff --git a/src/envoy/http/cluster/BUILD b/src/envoy/http/cluster/BUILD new file mode 100644 index 0000000000..38d63e464f --- /dev/null +++ b/src/envoy/http/cluster/BUILD @@ -0,0 +1,46 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@envoy//bazel:envoy_build_system.bzl", + "envoy_cc_library", +) + +licenses(["notice"]) # Apache 2 + +envoy_cc_library( + name = "golang_cluster_lib", + srcs = [ + "golang_cluster.cc", + ], + hdrs = [ + "golang_cluster.h", + ], + repository = "@envoy", + deps = [ + "@envoy//source/common/common:enum_to_int", + "@envoy//source/common/common:utility_lib", + "@envoy//source/common/grpc:context_lib", + "@envoy//source/common/http:headers_lib", + "@envoy//source/common/http:utility_lib", + "@envoy//source/common/common:linked_object", + "@envoy//source/common/router:config_lib", + "//src/envoy/common/dso:dso_lib", + "//api/http/cluster/v3:pkg_cc_proto", + ], +) + +envoy_cc_library( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + repository = "@envoy", + deps = [ + ":golang_cluster_lib", + "@envoy//envoy/registry", + "@envoy//envoy/server:filter_config_interface", + "@envoy//envoy/router:cluster_specifier_plugin_interface", + "@envoy//source/extensions/filters/http/common:factory_base_lib", + "//src/envoy/common/dso:dso_lib", + "//api/http/cluster/v3:pkg_cc_proto", + ], +) diff --git a/src/envoy/http/cluster/config.cc b/src/envoy/http/cluster/config.cc new file mode 100644 index 0000000000..3aebe92535 --- /dev/null +++ b/src/envoy/http/cluster/config.cc @@ -0,0 +1,25 @@ +#include + +#include "envoy/router/cluster_specifier_plugin.h" + +#include "src/envoy/http/cluster/config.h" + +namespace Envoy { +namespace Router { +namespace Golang { + +ClusterSpecifierPluginSharedPtr +GolangClusterSpecifierPluginFactoryConfig::createClusterSpecifierPlugin( + const Protobuf::Message& config, Server::Configuration::CommonFactoryContext&) { + const auto& typed_config = dynamic_cast(config); + auto cluster_config = std::make_shared(typed_config); + auto dynamicLib = Dso::DsoInstanceManager::getDsoInstanceByID(typed_config.so_id()); + return std::make_shared(cluster_config, dynamicLib); +} + +REGISTER_FACTORY(GolangClusterSpecifierPluginFactoryConfig, + ClusterSpecifierPluginFactoryConfig){"envoy.golang"}; + +} // namespace Golang +} // namespace Router +} // namespace Envoy diff --git a/src/envoy/http/cluster/config.h b/src/envoy/http/cluster/config.h new file mode 100644 index 0000000000..7887fcb249 --- /dev/null +++ b/src/envoy/http/cluster/config.h @@ -0,0 +1,27 @@ +#pragma once + +#include "source/extensions/filters/http/common/factory_base.h" + +#include "src/envoy/http/cluster/golang_cluster.h" + +namespace Envoy { +namespace Router { +namespace Golang { + +class GolangClusterSpecifierPluginFactoryConfig : public ClusterSpecifierPluginFactoryConfig { +public: + GolangClusterSpecifierPluginFactoryConfig() = default; + ClusterSpecifierPluginSharedPtr + createClusterSpecifierPlugin(const Protobuf::Message& config, + Server::Configuration::CommonFactoryContext&) override; + + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } + + std::string name() const override { return "envoy.router.cluster_specifier_plugin.golang"; } +}; + +} // namespace Golang +} // namespace Router +} // namespace Envoy diff --git a/src/envoy/http/cluster/golang_cluster.cc b/src/envoy/http/cluster/golang_cluster.cc new file mode 100644 index 0000000000..c672edc573 --- /dev/null +++ b/src/envoy/http/cluster/golang_cluster.cc @@ -0,0 +1,74 @@ +#include + +#include "source/common/router/config_impl.h" +#include "src/envoy/http/cluster/golang_cluster.h" + +namespace Envoy { +namespace Router { +namespace Golang { + +ClusterConfig::ClusterConfig(const GolangClusterProto& config) + : so_id_(config.so_id()), default_cluster_(config.default_cluster()), config_(config.config()) { +} + +uint64_t ClusterConfig::getConfigId() { + if (config_id_ != 0) { + return config_id_; + } + auto dlib = Dso::DsoInstanceManager::getDsoInstanceByID(so_id_); + if (dlib == NULL) { + ENVOY_LOG(error, "golang extension filter dynamicLib is nullPtr."); + return 0; + } + + std::string str; + if (!config_.SerializeToString(&str)) { + ENVOY_LOG(error, "failed to serialize any pb to string"); + return 0; + } + auto ptr = reinterpret_cast(str.data()); + auto len = str.length(); + config_id_ = dlib->moeNewClusterConfig(ptr, len); + if (config_id_ == 0) { + ENVOY_LOG(error, "invalid golang plugin config"); + } + return config_id_; +} + +RouteConstSharedPtr +GolangClusterSpecifierPlugin::route(const RouteEntry& parent, + const Http::RequestHeaderMap& headers) const { + ASSERT(dynamic_cast(&parent) != nullptr); + int buffer_len = 256; + std::string buffer; + std::string cluster; + +again: + buffer.reserve(buffer_len); + auto config_id = config_->getConfigId(); + auto header_ptr = reinterpret_cast(&headers); + auto buffer_ptr = reinterpret_cast(buffer.data()); + auto new_len = dynamicLib_->moeOnClusterSpecify(header_ptr, config_id, buffer_ptr, buffer_len); + if (new_len == 0) { + ENVOY_LOG(debug, "golang choose the default cluster"); + cluster = config_->defaultCluster(); + } else if (new_len < 0) { + ENVOY_LOG(error, "error happened while golang choose cluster, using the default cluster"); + cluster = config_->defaultCluster(); + } else if (new_len <= buffer_len) { + ENVOY_LOG(debug, "buffer size fit the cluster name from golang"); + cluster = std::string(buffer.data(), new_len); + } else { + ENVOY_LOG(debug, "need larger size of buffer to save the cluster name in golang, try again"); + buffer_len = new_len; + goto again; + } + + // TODO: add cache for it? + return std::make_shared( + dynamic_cast(&parent), cluster); +} + +} // namespace Golang +} // namespace Router +} // namespace Envoy diff --git a/src/envoy/http/cluster/golang_cluster.h b/src/envoy/http/cluster/golang_cluster.h new file mode 100644 index 0000000000..298e44fd66 --- /dev/null +++ b/src/envoy/http/cluster/golang_cluster.h @@ -0,0 +1,47 @@ +#pragma once + +#include "api/http/cluster/v3/cluster.pb.h" +#include "api/http/cluster/v3/cluster.pb.validate.h" + +#include "source/common/common/base64.h" +#include "source/common/http/utility.h" + +#include "src/envoy/common/dso/dso.h" + +namespace Envoy { +namespace Router { +namespace Golang { + +using GolangClusterProto = envoy::extensions::clusters::golang::v3::Config; + +class ClusterConfig : Logger::Loggable { +public: + ClusterConfig(const GolangClusterProto& config); + uint64_t getConfigId(); + const std::string& defaultCluster() { return default_cluster_; } + +private: + const std::string so_id_; + const std::string default_cluster_; + const Protobuf::Any config_; + uint64_t config_id_{0}; +}; + +using ClusterConfigSharedPtr = std::shared_ptr; + +class GolangClusterSpecifierPlugin : public ClusterSpecifierPlugin, + Logger::Loggable { +public: + GolangClusterSpecifierPlugin(ClusterConfigSharedPtr config, Dso::DsoInstance* dynamicLib) + : config_(config), dynamicLib_(dynamicLib){}; + + RouteConstSharedPtr route(const RouteEntry& parent, const Http::RequestHeaderMap&) const override; + +private: + ClusterConfigSharedPtr config_; + Dso::DsoInstance* dynamicLib_; +}; + +} // namespace Golang +} // namespace Router +} // namespace Envoy From 95234fa3e8e3bcdbdc6fb3954ae9c02975b2922d Mon Sep 17 00:00:00 2001 From: doujiang24 Date: Wed, 4 Jan 2023 14:33:03 +0800 Subject: [PATCH 2/3] go compile ok. --- main.go | 2 ++ pkg/api/filter.go | 14 ++++++++++++++ pkg/http/config.go | 28 ++++++++++++++++++++++++++++ pkg/http/filtermanager.go | 22 ++++++++++++++++++++++ pkg/http/moe.go | 19 +++++++++++++++++++ pkg/utils/string.go | 10 ++++++++++ src/envoy/common/dso/libgolang.h | 3 +++ 7 files changed, 98 insertions(+) diff --git a/main.go b/main.go index 05c776438c..dbd1cb32c5 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,7 @@ package main import ( "os" + "mosn.io/envoy-go-extension/samples/clusters" "mosn.io/mosn/pkg/streamfilter" _ "mosn.io/envoy-go-extension/pkg/filter/stream/echo" @@ -31,6 +32,7 @@ var DefaultMosnConfigPath string = "/home/admin/mosn/config/mosn.json" func init() { http.RegisterHttpFilterConfigFactory(mosn.ConfigFactory) + http.RegisterClusterSpecifierFactory(clusters.ClusterSpecifierFactory) // load mosn config mosnConfigPath := DefaultMosnConfigPath diff --git a/pkg/api/filter.go b/pkg/api/filter.go index bf495840f7..1e89591e02 100644 --- a/pkg/api/filter.go +++ b/pkg/api/filter.go @@ -103,3 +103,17 @@ type FilterCallbacks interface { type FilterCallbackHandler interface { FilterCallbacks } + +/* cluster specifier plugin */ + +type ClusterConfigParser interface { + Parse(any *anypb.Any) interface{} +} + +type ClusterSpecifier interface { + // TODO: support header + // Choose(RequestHeaderMap) string + Choose() string +} + +type ClusterSpecifierFactory func(config interface{}) ClusterSpecifier diff --git a/pkg/http/config.go b/pkg/http/config.go index c5cbe6aeae..9414364781 100644 --- a/pkg/http/config.go +++ b/pkg/http/config.go @@ -89,3 +89,31 @@ func moeMergeHttpPluginConfig(parentId uint64, childId uint64) uint64 { return childId } } + +/* cluster specifier plugin */ + +var ( + clusterConfigNumGenerator uint64 + clusterConfigCache = &sync.Map{} // uint64 -> any +) + +//export moeNewClusterConfig +func moeNewClusterConfig(configPtr uint64, configLen uint64) uint64 { + buf := utils.BytesToSlice(configPtr, configLen) + var any anypb.Any + proto.Unmarshal(buf, &any) + + configNum := atomic.AddUint64(&clusterConfigNumGenerator, 1) + if clusterConfigParser != nil { + clusterConfigCache.Store(configNum, clusterConfigParser.Parse(&any)) + } else { + clusterConfigCache.Store(configNum, &any) + } + + return configNum +} + +//export moeDestroyClusterConfig +func moeDestroyClusterConfig(id uint64) { + clusterConfigCache.Delete(id) +} diff --git a/pkg/http/filtermanager.go b/pkg/http/filtermanager.go index 366784ad28..7850b942b7 100644 --- a/pkg/http/filtermanager.go +++ b/pkg/http/filtermanager.go @@ -47,3 +47,25 @@ func getOrCreateHttpFilterFactory(configId uint64) api.HttpFilterFactory { func RegisterStreamingHttpFilterConfigFactory(f api.HttpFilterConfigFactory) { httpFilterConfigFactory = f } + +/* cluster specifier plugin */ + +// no cluster config parser by default +var clusterConfigParser api.ClusterConfigParser = nil +var clusterSpecifierFactory api.ClusterSpecifierFactory + +func RegisterClusterConfigParser(parser api.ClusterConfigParser) { + clusterConfigParser = parser +} + +func RegisterClusterSpecifierFactory(f api.ClusterSpecifierFactory) { + clusterSpecifierFactory = f +} + +func getOrCreateClusterSpecifier(configId uint64) api.ClusterSpecifier { + config, ok := configCache.Load(configId) + if !ok { + // TODO: panic + } + return clusterSpecifierFactory(config) +} diff --git a/pkg/http/moe.go b/pkg/http/moe.go index 09b6b9ac0f..8117facaca 100644 --- a/pkg/http/moe.go +++ b/pkg/http/moe.go @@ -38,6 +38,7 @@ import ( "sync" "mosn.io/envoy-go-extension/pkg/api" + "mosn.io/envoy-go-extension/pkg/utils" ) var ErrDupRequestKey = errors.New("dup request key") @@ -225,3 +226,21 @@ func moeOnHttpSemaCallback(r *C.httpRequest) { defer req.RecoverPanic() req.sema.Done() } + +//export moeOnClusterSpecify +func moeOnClusterSpecify(headerPtr uint64, configId uint64, bufferPtr uint64, bufferLen uint64) int64 { + specifier := getOrCreateClusterSpecifier(configId) + cluster := specifier.Choose() + l := uint64(len(cluster)) + if l == 0 { + // means use the default cluster + return 0 + } + if l > bufferLen { + // buffer length is not large enough. + return int64(l) + } + buffer := utils.BufferToSlice(bufferPtr, bufferLen) + copy(buffer, cluster) + return int64(l) +} diff --git a/pkg/utils/string.go b/pkg/utils/string.go index 9bbafd24f8..8033ee3b23 100644 --- a/pkg/utils/string.go +++ b/pkg/utils/string.go @@ -39,3 +39,13 @@ func BytesToSlice(ptr uint64, len uint64) []byte { sHdr.Cap = int(len) return s } + +// BufferToSlice convert the memory buffer from C to a empty slice with reserved len. +func BufferToSlice(ptr uint64, len uint64) []byte { + var s []byte + var sHdr = (*reflect.SliceHeader)(unsafe.Pointer(&s)) + sHdr.Data = uintptr(ptr) + sHdr.Len = 0 + sHdr.Cap = int(len) + return s +} diff --git a/src/envoy/common/dso/libgolang.h b/src/envoy/common/dso/libgolang.h index 55e4ac08fe..3ae118e789 100644 --- a/src/envoy/common/dso/libgolang.h +++ b/src/envoy/common/dso/libgolang.h @@ -108,9 +108,12 @@ extern GoUint64 moeOnHttpHeader(httpRequest* r, GoUint64 endStream, GoUint64 hea extern GoUint64 moeOnHttpData(httpRequest* r, GoUint64 endStream, GoUint64 buffer, GoUint64 length); extern void moeOnHttpDestroy(httpRequest* r, GoUint64 reason); extern void moeOnHttpSemaCallback(httpRequest* r); +extern GoInt64 moeOnClusterSpecify(GoUint64 headerPtr, GoUint64 configId, GoUint64 bufferPtr, GoUint64 bufferLen); extern GoUint64 moeNewHttpPluginConfig(GoUint64 configPtr, GoUint64 configLen); extern void moeDestroyHttpPluginConfig(GoUint64 id); extern GoUint64 moeMergeHttpPluginConfig(GoUint64 parentId, GoUint64 childId); +extern GoUint64 moeNewClusterConfig(GoUint64 configPtr, GoUint64 configLen); +extern void moeDestroyClusterConfig(GoUint64 id); #ifdef __cplusplus } From 74ef4292a95354360c07e712f4184937bfc85c7d Mon Sep 17 00:00:00 2001 From: doujiang24 Date: Wed, 4 Jan 2023 15:36:28 +0800 Subject: [PATCH 3/3] basic work. --- samples/clusters/cluster.go | 16 ++++++++++++++++ src/envoy/http/cluster/config.cc | 3 +-- src/envoy/http/cluster/golang_cluster.cc | 22 ++++++++++++++++++---- src/envoy/http/cluster/golang_cluster.h | 6 +++--- test/http/golang/test_data/basic/filter.go | 19 +++++++++++++++++++ 5 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 samples/clusters/cluster.go diff --git a/samples/clusters/cluster.go b/samples/clusters/cluster.go new file mode 100644 index 0000000000..51139fc092 --- /dev/null +++ b/samples/clusters/cluster.go @@ -0,0 +1,16 @@ +package clusters + +import "mosn.io/envoy-go-extension/pkg/api" + +type specifier struct { + config interface{} +} + +func ClusterSpecifierFactory(config interface{}) api.ClusterSpecifier { + return &specifier{config: config} +} + +func (s *specifier) Choose() string { + // use the default cluster + return "" +} diff --git a/src/envoy/http/cluster/config.cc b/src/envoy/http/cluster/config.cc index 3aebe92535..ace129f1e4 100644 --- a/src/envoy/http/cluster/config.cc +++ b/src/envoy/http/cluster/config.cc @@ -13,8 +13,7 @@ GolangClusterSpecifierPluginFactoryConfig::createClusterSpecifierPlugin( const Protobuf::Message& config, Server::Configuration::CommonFactoryContext&) { const auto& typed_config = dynamic_cast(config); auto cluster_config = std::make_shared(typed_config); - auto dynamicLib = Dso::DsoInstanceManager::getDsoInstanceByID(typed_config.so_id()); - return std::make_shared(cluster_config, dynamicLib); + return std::make_shared(cluster_config); } REGISTER_FACTORY(GolangClusterSpecifierPluginFactoryConfig, diff --git a/src/envoy/http/cluster/golang_cluster.cc b/src/envoy/http/cluster/golang_cluster.cc index c672edc573..ed4d2436a0 100644 --- a/src/envoy/http/cluster/golang_cluster.cc +++ b/src/envoy/http/cluster/golang_cluster.cc @@ -11,13 +11,24 @@ ClusterConfig::ClusterConfig(const GolangClusterProto& config) : so_id_(config.so_id()), default_cluster_(config.default_cluster()), config_(config.config()) { } +Dso::DsoInstance* ClusterConfig::getDsoLib() { + if (dynamicLib_ != nullptr) { + return dynamicLib_; + } + auto dynamicLib_ = Dso::DsoInstanceManager::getDsoInstanceByID(so_id_); + if (dynamicLib_ == nullptr) { + ENVOY_LOG(error, "golang dynamicLib is nullPtr."); + } + return dynamicLib_; +} + uint64_t ClusterConfig::getConfigId() { if (config_id_ != 0) { return config_id_; } - auto dlib = Dso::DsoInstanceManager::getDsoInstanceByID(so_id_); - if (dlib == NULL) { - ENVOY_LOG(error, "golang extension filter dynamicLib is nullPtr."); + + auto dlib = getDsoLib(); + if (dlib == nullptr) { return 0; } @@ -42,13 +53,16 @@ GolangClusterSpecifierPlugin::route(const RouteEntry& parent, int buffer_len = 256; std::string buffer; std::string cluster; + auto dlib = config_->getDsoLib(); again: buffer.reserve(buffer_len); auto config_id = config_->getConfigId(); auto header_ptr = reinterpret_cast(&headers); auto buffer_ptr = reinterpret_cast(buffer.data()); - auto new_len = dynamicLib_->moeOnClusterSpecify(header_ptr, config_id, buffer_ptr, buffer_len); + auto new_len = dlib != nullptr + ? dlib->moeOnClusterSpecify(header_ptr, config_id, buffer_ptr, buffer_len) + : 0; if (new_len == 0) { ENVOY_LOG(debug, "golang choose the default cluster"); cluster = config_->defaultCluster(); diff --git a/src/envoy/http/cluster/golang_cluster.h b/src/envoy/http/cluster/golang_cluster.h index 298e44fd66..748430e574 100644 --- a/src/envoy/http/cluster/golang_cluster.h +++ b/src/envoy/http/cluster/golang_cluster.h @@ -19,12 +19,14 @@ class ClusterConfig : Logger::Loggable { ClusterConfig(const GolangClusterProto& config); uint64_t getConfigId(); const std::string& defaultCluster() { return default_cluster_; } + Dso::DsoInstance* getDsoLib(); private: const std::string so_id_; const std::string default_cluster_; const Protobuf::Any config_; uint64_t config_id_{0}; + Dso::DsoInstance* dynamicLib_{nullptr}; }; using ClusterConfigSharedPtr = std::shared_ptr; @@ -32,14 +34,12 @@ using ClusterConfigSharedPtr = std::shared_ptr; class GolangClusterSpecifierPlugin : public ClusterSpecifierPlugin, Logger::Loggable { public: - GolangClusterSpecifierPlugin(ClusterConfigSharedPtr config, Dso::DsoInstance* dynamicLib) - : config_(config), dynamicLib_(dynamicLib){}; + GolangClusterSpecifierPlugin(ClusterConfigSharedPtr config) : config_(config){}; RouteConstSharedPtr route(const RouteEntry& parent, const Http::RequestHeaderMap&) const override; private: ClusterConfigSharedPtr config_; - Dso::DsoInstance* dynamicLib_; }; } // namespace Golang diff --git a/test/http/golang/test_data/basic/filter.go b/test/http/golang/test_data/basic/filter.go index bd576e4a84..fecf8c97e8 100644 --- a/test/http/golang/test_data/basic/filter.go +++ b/test/http/golang/test_data/basic/filter.go @@ -13,6 +13,7 @@ import ( func init() { http.RegisterHttpFilterConfigFactory(configFactory) + http.RegisterClusterSpecifierFactory(clusterSpecifierFactory) } type filter struct { @@ -398,5 +399,23 @@ func configFactory(interface{}) api.HttpFilterFactory { } } +// cluster specifier plugin + +type clusterSpecifier struct { + config interface{} +} + +func clusterSpecifierFactory(config interface{}) api.ClusterSpecifier { + return &clusterSpecifier{ + config: config, + } +} + +func (s *clusterSpecifier) Choose() string { + // use the default cluster + fmt.Printf("choosing cluster, using the default cluster\n") + return "" +} + func main() { }