Line data Source code
1 : #pragma once 2 : 3 : #include "envoy/extensions/router/cluster_specifiers/lua/v3/lua.pb.h" 4 : #include "envoy/router/cluster_specifier_plugin.h" 5 : 6 : #include "source/common/config/datasource.h" 7 : #include "source/extensions/filters/common/lua/wrappers.h" 8 : 9 : namespace Envoy { 10 : namespace Extensions { 11 : namespace Router { 12 : namespace Lua { 13 : 14 : using LuaClusterSpecifierConfigProto = 15 : envoy::extensions::router::cluster_specifiers::lua::v3::LuaConfig; 16 : 17 : class PerLuaCodeSetup : Logger::Loggable<Logger::Id::lua> { 18 : public: 19 : PerLuaCodeSetup(const std::string& lua_code, ThreadLocal::SlotAllocator& tls); 20 : 21 0 : Extensions::Filters::Common::Lua::CoroutinePtr createCoroutine() { 22 0 : return lua_state_.createCoroutine(); 23 0 : } 24 : 25 0 : int clusterFunctionRef() { return lua_state_.getGlobalRef(cluster_function_slot_); } 26 : 27 : private: 28 : uint64_t cluster_function_slot_{}; 29 : 30 : Filters::Common::Lua::ThreadLocalState lua_state_; 31 : }; 32 : 33 : using PerLuaCodeSetupPtr = std::unique_ptr<PerLuaCodeSetup>; 34 : 35 : class HeaderMapWrapper : public Filters::Common::Lua::BaseLuaObject<HeaderMapWrapper> { 36 : public: 37 0 : HeaderMapWrapper(const Http::HeaderMap& headers) : headers_(headers) {} 38 : 39 0 : static ExportedFunctions exportedFunctions() { return {{"get", static_luaGet}}; } 40 : 41 : private: 42 : /** 43 : * Get a header value from the map. 44 : * @param 1 (string): header name. 45 : * @return string value if found or nil. 46 : */ 47 : DECLARE_LUA_FUNCTION(HeaderMapWrapper, luaGet); 48 : 49 : const Http::HeaderMap& headers_; 50 : }; 51 : 52 : using HeaderMapRef = Filters::Common::Lua::LuaDeathRef<HeaderMapWrapper>; 53 : 54 : class RouteHandleWrapper : public Filters::Common::Lua::BaseLuaObject<RouteHandleWrapper> { 55 : public: 56 0 : RouteHandleWrapper(const Http::HeaderMap& headers) : headers_(headers) {} 57 : 58 0 : static ExportedFunctions exportedFunctions() { return {{"headers", static_luaHeaders}}; } 59 : 60 : private: 61 : /** 62 : * @return a handle to the headers. 63 : */ 64 : DECLARE_LUA_FUNCTION(RouteHandleWrapper, luaHeaders); 65 : 66 : const Http::HeaderMap& headers_; 67 : HeaderMapRef headers_wrapper_; 68 : }; 69 : 70 : using RouteHandleRef = Filters::Common::Lua::LuaDeathRef<RouteHandleWrapper>; 71 : 72 : class LuaClusterSpecifierConfig : Logger::Loggable<Logger::Id::lua> { 73 : public: 74 : LuaClusterSpecifierConfig(const LuaClusterSpecifierConfigProto& config, 75 : Server::Configuration::CommonFactoryContext& context); 76 : 77 0 : ~LuaClusterSpecifierConfig() { 78 : // The design of the TLS system does not allow TLS state to be modified in worker threads. 79 : // However, when the route configuration is dynamically updated via RDS, the old 80 : // LuaClusterSpecifierConfig object may be destructed in a random worker thread. Therefore, to 81 : // ensure thread safety, ownership of per_lua_code_setup_ptr_ must be transferred to the main 82 : // thread and destroyed when the LuaClusterSpecifierConfig object is not destructed in the main 83 : // thread. 84 0 : if (per_lua_code_setup_ptr_ && !main_thread_dispatcher_.isThreadSafe()) { 85 0 : auto shared_ptr_wrapper = 86 0 : std::make_shared<PerLuaCodeSetupPtr>(std::move(per_lua_code_setup_ptr_)); 87 0 : main_thread_dispatcher_.post([shared_ptr_wrapper] { shared_ptr_wrapper->reset(); }); 88 0 : } 89 0 : } 90 : 91 0 : PerLuaCodeSetup* perLuaCodeSetup() const { return per_lua_code_setup_ptr_.get(); } 92 0 : const std::string& defaultCluster() const { return default_cluster_; } 93 : 94 : private: 95 : Event::Dispatcher& main_thread_dispatcher_; 96 : PerLuaCodeSetupPtr per_lua_code_setup_ptr_; 97 : const std::string default_cluster_; 98 : }; 99 : 100 : using LuaClusterSpecifierConfigSharedPtr = std::shared_ptr<LuaClusterSpecifierConfig>; 101 : 102 : class LuaClusterSpecifierPlugin : public Envoy::Router::ClusterSpecifierPlugin, 103 : Logger::Loggable<Logger::Id::lua> { 104 : public: 105 : LuaClusterSpecifierPlugin(LuaClusterSpecifierConfigSharedPtr config); 106 : Envoy::Router::RouteConstSharedPtr route(Envoy::Router::RouteConstSharedPtr parent, 107 : const Http::RequestHeaderMap& header) const override; 108 : 109 : private: 110 : std::string startLua(const Http::HeaderMap& headers) const; 111 : 112 : LuaClusterSpecifierConfigSharedPtr config_; 113 : const int function_ref_; 114 : }; 115 : 116 : } // namespace Lua 117 : } // namespace Router 118 : } // namespace Extensions 119 : } // namespace Envoy