Line data Source code
1 : #include "source/extensions/common/wasm/wasm_vm.h" 2 : 3 : #include <algorithm> 4 : #include <memory> 5 : 6 : #include "source/extensions/common/wasm/context.h" 7 : #include "source/extensions/common/wasm/ext/envoy_null_vm_wasm_api.h" 8 : #include "source/extensions/common/wasm/stats_handler.h" 9 : #include "source/extensions/common/wasm/wasm_runtime_factory.h" 10 : 11 : #include "include/proxy-wasm/null_plugin.h" 12 : 13 : using ContextBase = proxy_wasm::ContextBase; 14 : using Word = proxy_wasm::Word; 15 : 16 : namespace Envoy { 17 : namespace Extensions { 18 : namespace Common { 19 : namespace Wasm { 20 : 21 0 : proxy_wasm::LogLevel EnvoyWasmVmIntegration::getLogLevel() { 22 0 : switch (ENVOY_LOGGER().level()) { 23 0 : case spdlog::level::trace: 24 0 : return proxy_wasm::LogLevel::trace; 25 0 : case spdlog::level::debug: 26 0 : return proxy_wasm::LogLevel::debug; 27 0 : case spdlog::level::info: 28 0 : return proxy_wasm::LogLevel::info; 29 0 : case spdlog::level::warn: 30 0 : return proxy_wasm::LogLevel::warn; 31 0 : case spdlog::level::err: 32 0 : return proxy_wasm::LogLevel::error; 33 0 : default: 34 0 : return proxy_wasm::LogLevel::critical; 35 0 : } 36 0 : } 37 : 38 0 : void EnvoyWasmVmIntegration::error(std::string_view message) { ENVOY_LOG(error, message); } 39 0 : void EnvoyWasmVmIntegration::trace(std::string_view message) { ENVOY_LOG(trace, message); } 40 : 41 : bool EnvoyWasmVmIntegration::getNullVmFunction(std::string_view function_name, bool returns_word, 42 : int number_of_arguments, 43 : proxy_wasm::NullPlugin* plugin, 44 0 : void* ptr_to_function_return) { 45 0 : if (function_name == "envoy_on_resolve_dns" && returns_word == false && 46 0 : number_of_arguments == 3) { 47 0 : *reinterpret_cast<proxy_wasm::WasmCallVoid<3>*>(ptr_to_function_return) = 48 0 : [plugin](ContextBase* context, Word context_id, Word token, Word result_size) { 49 0 : proxy_wasm::SaveRestoreContext saved_context(context); 50 : // Need to add a new API header available to both .wasm and null vm targets. 51 0 : auto context_base = plugin->getContextBase(context_id); 52 0 : if (auto root = context_base->asRoot()) { 53 0 : static_cast<proxy_wasm::null_plugin::EnvoyRootContext*>(root)->onResolveDns( 54 0 : token, result_size); 55 0 : } 56 0 : }; 57 0 : return true; 58 0 : } else if (function_name == "envoy_on_stats_update" && returns_word == false && 59 0 : number_of_arguments == 2) { 60 0 : *reinterpret_cast<proxy_wasm::WasmCallVoid<2>*>( 61 0 : ptr_to_function_return) = [plugin](ContextBase* context, Word context_id, 62 0 : Word result_size) { 63 0 : proxy_wasm::SaveRestoreContext saved_context(context); 64 : // Need to add a new API header available to both .wasm and null vm targets. 65 0 : auto context_base = plugin->getContextBase(context_id); 66 0 : if (auto root = context_base->asRoot()) { 67 0 : static_cast<proxy_wasm::null_plugin::EnvoyRootContext*>(root)->onStatsUpdate(result_size); 68 0 : } 69 0 : }; 70 0 : return true; 71 0 : } 72 0 : return false; 73 0 : } 74 : 75 0 : bool isWasmEngineAvailable(absl::string_view runtime) { 76 0 : auto runtime_factory = Registry::FactoryRegistry<WasmRuntimeFactory>::getFactory(runtime); 77 0 : return runtime_factory != nullptr; 78 0 : } 79 : 80 0 : absl::string_view getFirstAvailableWasmEngineName() { 81 0 : constexpr absl::string_view wasm_engines[] = { 82 0 : "envoy.wasm.runtime.v8", "envoy.wasm.runtime.wasmtime", "envoy.wasm.runtime.wamr", 83 0 : "envoy.wasm.runtime.wavm"}; 84 0 : for (const auto wasm_engine : wasm_engines) { 85 0 : if (isWasmEngineAvailable(wasm_engine)) { 86 0 : return wasm_engine; 87 0 : } 88 0 : } 89 0 : return ""; 90 0 : } 91 : 92 0 : WasmVmPtr createWasmVm(absl::string_view runtime) { 93 : // Set wasm runtime to built-in Wasm engine if it is not specified 94 0 : if (runtime.empty()) { 95 0 : runtime = getFirstAvailableWasmEngineName(); 96 0 : } 97 : 98 0 : auto runtime_factory = Registry::FactoryRegistry<WasmRuntimeFactory>::getFactory(runtime); 99 0 : if (runtime_factory == nullptr) { 100 0 : ENVOY_LOG_TO_LOGGER( 101 0 : Envoy::Logger::Registry::getLog(Envoy::Logger::Id::wasm), warn, 102 0 : "Failed to create Wasm VM using {} runtime. Envoy was compiled without support for it", 103 0 : runtime); 104 0 : return nullptr; 105 0 : } 106 : 107 0 : auto wasm = runtime_factory->createWasmVm(); 108 0 : wasm->integration() = std::make_unique<EnvoyWasmVmIntegration>(); 109 0 : return wasm; 110 0 : } 111 : 112 : } // namespace Wasm 113 : } // namespace Common 114 : } // namespace Extensions 115 : } // namespace Envoy