blob: b33187ce08e1b595c5b248584e9f661e30cd9282 [file]
// Copyright 2016-2019 Envoy Project Authors
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <memory>
#include "include/proxy-wasm/exports.h"
#include "include/proxy-wasm/null_vm_plugin.h"
#include "include/proxy-wasm/wasm.h"
#include "include/proxy-wasm/wasm_api_impl.h"
namespace proxy_wasm {
/**
* Registry for Plugin implementation.
*/
struct NullPluginRegistry {
void (*proxy_abi_version_0_1_0_)() = nullptr;
void (*proxy_abi_version_0_2_0_)() = nullptr;
void (*proxy_abi_version_0_2_1_)() = nullptr;
void (*proxy_on_log_)(uint32_t context_id) = nullptr;
uint32_t (*proxy_validate_configuration_)(uint32_t root_context_id,
uint32_t plugin_configuration_size) = nullptr;
void (*proxy_on_context_create_)(uint32_t context_id, uint32_t parent_context_id) = nullptr;
uint32_t (*proxy_on_vm_start_)(uint32_t root_context_id,
uint32_t vm_configuration_size) = nullptr;
uint32_t (*proxy_on_configure_)(uint32_t root_context_id,
uint32_t plugin_configuration_size) = nullptr;
void (*proxy_on_tick_)(uint32_t context_id) = nullptr;
void (*proxy_on_foreign_function_)(uint32_t context_id, uint32_t token,
uint32_t data_size) = nullptr;
uint32_t (*proxy_on_done_)(uint32_t context_id) = nullptr;
void (*proxy_on_delete_)(uint32_t context_id) = nullptr;
std::unordered_map<std::string, null_plugin::RootFactory> root_factories;
std::unordered_map<std::string, null_plugin::ContextFactory> context_factories;
};
/**
* Base class for all plugins, subclass to create a new plugin.
* NB: this class must implement
*/
class NullPlugin : public NullVmPlugin {
public:
using NewContextFnPtr = std::unique_ptr<ContextBase> (*)(uint32_t /* id */);
explicit NullPlugin(NullPluginRegistry *registry) : registry_(registry) {}
NullPlugin(const NullPlugin &other) : registry_(other.registry_) {}
#define _DECLARE_OVERRIDE(_t) void getFunction(std::string_view function_name, _t *f) override;
FOR_ALL_WASM_VM_EXPORTS(_DECLARE_OVERRIDE)
#undef _DECLARE_OVERRIDE
bool validateConfiguration(uint64_t root_context_id, uint64_t plugin_configuration_size);
bool onStart(uint64_t root_context_id, uint64_t vm_configuration_size);
bool onConfigure(uint64_t root_context_id, uint64_t plugin_configuration_size);
void onTick(uint64_t root_context_id);
void onQueueReady(uint64_t root_context_id, uint64_t token);
void onForeignFunction(uint64_t root_context_id, uint64_t foreign_function_id,
uint64_t data_size);
void onCreate(uint64_t context_id, uint64_t parent_context_id);
uint64_t onNewConnection(uint64_t context_id);
uint64_t onDownstreamData(uint64_t context_id, uint64_t data_length, uint64_t end_of_stream);
uint64_t onUpstreamData(uint64_t context_id, uint64_t data_length, uint64_t end_of_stream);
void onDownstreamConnectionClose(uint64_t context_id, uint64_t close_type);
void onUpstreamConnectionClose(uint64_t context_id, uint64_t close_type);
uint64_t onRequestHeaders(uint64_t context_id, uint64_t headers, uint64_t end_of_stream);
uint64_t onRequestBody(uint64_t context_id, uint64_t body_buffer_length, uint64_t end_of_stream);
uint64_t onRequestTrailers(uint64_t context_id, uint64_t trailers);
uint64_t onRequestMetadata(uint64_t context_id, uint64_t elements);
uint64_t onResponseHeaders(uint64_t context_id, uint64_t headers, uint64_t end_of_stream);
uint64_t onResponseBody(uint64_t context_id, uint64_t body_buffer_length, uint64_t end_of_stream);
uint64_t onResponseTrailers(uint64_t context_id, uint64_t trailers);
uint64_t onResponseMetadata(uint64_t context_id, uint64_t elements);
void onHttpCallResponse(uint64_t context_id, uint64_t token, uint64_t headers, uint64_t body_size,
uint64_t trailers);
void onGrpcReceive(uint64_t context_id, uint64_t token, size_t body_size);
void onGrpcClose(uint64_t context_id, uint64_t token, uint64_t status_code);
void onGrpcReceiveInitialMetadata(uint64_t context_id, uint64_t token, uint64_t headers);
void onGrpcReceiveTrailingMetadata(uint64_t context_id, uint64_t token, uint64_t trailers);
void onLog(uint64_t context_id);
uint64_t onDone(uint64_t context_id);
void onDelete(uint64_t context_id);
null_plugin::RootContext *getRoot(std::string_view root_id);
null_plugin::Context *getContext(uint64_t context_id);
void error(std::string_view message) { wasm_vm_->integration()->error(message); }
null_plugin::Context *ensureContext(uint64_t context_id, uint64_t root_context_id);
null_plugin::RootContext *ensureRootContext(uint64_t context_id);
null_plugin::RootContext *getRootContext(uint64_t context_id);
null_plugin::ContextBase *getContextBase(uint64_t context_id);
private:
NullPluginRegistry *registry_{};
std::unordered_map<std::string, null_plugin::RootContext *> root_context_map_;
std::unordered_map<int64_t, std::unique_ptr<null_plugin::ContextBase>> context_map_;
};
#define PROXY_WASM_NULL_PLUGIN_REGISTRY \
extern NullPluginRegistry *context_registry_; \
struct RegisterContextFactory { \
explicit RegisterContextFactory(null_plugin::ContextFactory context_factory, \
null_plugin::RootFactory root_factory, \
std::string_view root_id = "") { \
if (!context_registry_) { \
context_registry_ = new NullPluginRegistry; \
} \
context_registry_->context_factories[std::string(root_id)] = context_factory; \
context_registry_->root_factories[std::string(root_id)] = root_factory; \
} \
explicit RegisterContextFactory(null_plugin::ContextFactory context_factory, \
std::string_view root_id = "") { \
if (!context_registry_) { \
context_registry_ = new NullPluginRegistry; \
} \
context_registry_->context_factories[std::string(root_id)] = context_factory; \
} \
explicit RegisterContextFactory(null_plugin::RootFactory root_factory, \
std::string_view root_id = "") { \
if (!context_registry_) { \
context_registry_ = new NullPluginRegistry; \
} \
context_registry_->root_factories[std::string(root_id)] = root_factory; \
} \
};
#define START_WASM_PLUGIN(_name) \
namespace proxy_wasm { \
namespace null_plugin { \
namespace _name { \
PROXY_WASM_NULL_PLUGIN_REGISTRY
#define END_WASM_PLUGIN \
} \
} \
}
#define WASM_EXPORT(_t, _f, _a) \
_t _f _a; \
static int register_export_##_f() { \
if (!context_registry_) { \
context_registry_ = new NullPluginRegistry; \
} \
context_registry_->_f##_ = _f; \
return 0; \
}; \
static int register_export_##_f##_ = register_export_##_f(); \
_t _f _a
} // namespace proxy_wasm