From 36141dcdb21598f3d57109cf20445842ead5b6c6 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Mon, 9 Mar 2020 23:54:45 +0000 Subject: [PATCH 01/19] Review of the ContextBase include. Tests will follow after the Wasm header when the .cc files are sent for review. Signed-off-by: John Plevyak --- BUILD | 29 ++- include/proxy-wasm/compat.h | 12 +- include/proxy-wasm/context.h | 350 +++++++++++++++++++++++++++++++++++ include/proxy-wasm/wasm_vm.h | 1 + 4 files changed, 381 insertions(+), 11 deletions(-) create mode 100644 include/proxy-wasm/context.h diff --git a/BUILD b/BUILD index db623b01..e2de48ce 100644 --- a/BUILD +++ b/BUILD @@ -6,6 +6,7 @@ cc_library( name = "include", hdrs = [ "include/proxy-wasm/compat.h", + "include/proxy-wasm/context.h", "include/proxy-wasm/wasm_vm.h", "include/proxy-wasm/word.h", ], @@ -19,6 +20,7 @@ cc_library( name = "include14", hdrs = [ "include/proxy-wasm/compat.h", + "include/proxy-wasm/context.h", "include/proxy-wasm/wasm_vm.h", "include/proxy-wasm/word.h", ], @@ -33,9 +35,16 @@ cc_test( srcs = ["wasm_vm_test.cc"], deps = [ ":include", - "@com_google_absl//absl/base", - "@com_google_absl//absl/strings:strings", - "@com_google_absl//absl/types:optional", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "context_test", + srcs = ["context_test.cc"], + deps = [ + ":include", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], @@ -55,3 +64,17 @@ cc_test( "@com_google_googletest//:gtest_main", ], ) + +cc_test( + name = "context_14_test", + srcs = ["context_test.cc"], + copts = ["-std=c++14"], + deps = [ + ":include14", + "@com_google_absl//absl/base", + "@com_google_absl//absl/strings:strings", + "@com_google_absl//absl/types:optional", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/include/proxy-wasm/compat.h b/include/proxy-wasm/compat.h index 092f7fd4..f92732c7 100644 --- a/include/proxy-wasm/compat.h +++ b/include/proxy-wasm/compat.h @@ -17,16 +17,12 @@ // Provide compatibiliby for projects which have not yet moved to C++17. // TODO: remove this when all dependent projects have upgraded. -#ifndef __cpp_lib_optional -#include "absl/types/optional.h" -#else +#if __cplusplus >= 201703L #include -#endif - -#ifndef __cpp_lib_string_view -#include "absl/strings/string_view.h" -#else #include +#else +#include "absl/types/optional.h" +#include "absl/strings/string_view.h" #endif namespace proxy_wasm { diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h new file mode 100644 index 00000000..b21126d7 --- /dev/null +++ b/include/proxy-wasm/context.h @@ -0,0 +1,350 @@ +// 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 "include/proxy-wasm/compat.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace proxy_wasm { + +#include "proxy_wasm_common.h" +#include "proxy_wasm_enums.h" + +class WasmBase; +class WasmVm; + +using Pairs = std::vector>; +using PairsWithStringValues = std::vector>; +using CallOnThreadFunction = std::function)>; + +struct BufferInterface { + virtual ~BufferInterface() {} + virtual size_t size() const = 0; + // Returns true on success. + virtual bool copyTo(WasmBase *wasm, size_t start, size_t length, uint64_t ptr_ptr, + uint64_t size_ptr) const = 0; +}; + +// Opaque context object. +class StorageObject { +public: + virtual ~StorageObject() = default; +}; + +struct PluginBase { + PluginBase(string_view name, string_view root_id, string_view vm_id, + string_view plugin_configuration) + : name_(std::string(name)), root_id_(std::string(root_id)), vm_id_(std::string(vm_id)), + plugin_configuration_(plugin_configuration) {} + + const std::string name_; + const std::string root_id_; + const std::string vm_id_; + std::string plugin_configuration_; + const std::string &log_prefix() const { return log_prefix_; } + +private: + std::string makeLogPrefix() const; + + std::string log_prefix_; +}; + +// A context which will be the target of callbacks for a particular session +// e.g. a handler of a stream. +class ContextBase { +public: + ContextBase(); // Testing. + ContextBase(WasmBase *wasm); // Vm Context. + ContextBase(WasmBase *wasm, std::shared_ptr plugin); // Root Context. + ContextBase(WasmBase *wasm, uint32_t root_context_id, + std::shared_ptr plugin); // Stream context. + virtual ~ContextBase(); + + WasmBase *wasm() const { return wasm_; } + uint32_t id() const { return id_; } + bool isVmContext() { return id_ == 0; } + bool isRootContext() { return root_context_id_ == 0; } + ContextBase *root_context() { return root_context_; } + string_view root_id() const { return plugin_->root_id_; } + string_view log_prefix() const { return plugin_->log_prefix(); } + WasmVm *wasmVm() const; + + // Called before deleting the context. + virtual void destroy(); + + // + // VM level downcalls into the WASM code on Context(id == 0). + // + virtual bool onStart(std::shared_ptr plugin); + virtual bool onConfigure(std::shared_ptr plugin); + + // + // Stream downcalls on Context(id > 0). + // + // General stream downcall on a new stream. + virtual void onCreate(uint32_t root_context_id); + // Network + virtual FilterStatus onNetworkNewConnection() { + unimplemented(); + return FilterStatus::Continue; + } + virtual FilterStatus onDownstreamData(int /* data_length */, bool /* end_of_stream */) { + unimplemented(); + return FilterStatus::Continue; + } + virtual FilterStatus onUpstreamData(int /* data_length */, bool /* end_of_stream */) { + unimplemented(); + return FilterStatus::Continue; + } + enum class PeerType : uint32_t { + Unknown = 0, + Local = 1, + Remote = 2, + }; + virtual void onDownstreamConnectionClose(PeerType) { unimplemented(); } + virtual void onUpstreamConnectionClose(PeerType) { unimplemented(); } + // HTTP Filter Stream Request Downcalls. + virtual FilterHeadersStatus onRequestHeaders() { + unimplemented(); + return FilterHeadersStatus::Continue; + } + virtual FilterDataStatus onRequestBody(int /* body_buffer_length */, bool /* end_of_stream */) { + unimplemented(); + return FilterDataStatus::Continue; + } + virtual FilterTrailersStatus onRequestTrailers() { + unimplemented(); + return FilterTrailersStatus::Continue; + } + virtual FilterMetadataStatus onRequestMetadata() { + unimplemented(); + return FilterMetadataStatus::Continue; + } + // HTTP Filter Stream Response Downcalls. + virtual FilterHeadersStatus onResponseHeaders() { + unimplemented(); + return FilterHeadersStatus::Continue; + } + virtual FilterDataStatus onResponseBody(int /* body_buffer_length */, bool /* end_of_stream */) { + unimplemented(); + return FilterDataStatus::Continue; + } + virtual FilterTrailersStatus onResponseTrailers() { + unimplemented(); + return FilterTrailersStatus::Continue; + } + virtual FilterMetadataStatus onResponseMetadata() { + unimplemented(); + return FilterMetadataStatus::Continue; + } + // Async call response. + virtual void onHttpCallResponse(uint32_t /* token */, uint32_t /* headers */, + uint32_t /* body_size */, uint32_t /* trailers */) {} + // Inter-VM shared queue message arrival. + virtual void onQueueReady(uint32_t /* token */) { unimplemented(); } + // General stream downcall when the stream/vm has ended. + virtual bool onDone(); + // General stream downcall for logging. Occurs after onDone(). + virtual void onLog(); + // General stream downcall when no further stream calls will occur. + virtual void onDelete(); + + virtual void error(string_view message) { + std::cerr << message << "\n"; + abort(); + } + virtual void unimplemented() { error("unimplemented proxy-wasm API"); } + + // + // General Callbacks. + // + virtual WasmResult log(uint64_t /* level */, string_view /* message */) { + unimplemented(); + return WasmResult::Unimplemented; + } + virtual WasmResult setTimerPeriod(std::chrono::milliseconds /* period */) { + unimplemented(); + return WasmResult::Unimplemented; + } + virtual uint64_t getCurrentTimeNanoseconds() { + struct timespec tpe; + clock_gettime(CLOCK_REALTIME, &tpe); + uint64_t t = tpe.tv_sec; + t *= 1000000000; + t += tpe.tv_nsec; + return t; + } + virtual std::pair getStatus() { + unimplemented(); + return std::make_pair(1, "unimplmemented"); + } + + // Buffer + virtual const BufferInterface *getBuffer(WasmBufferType /* type */) { + unimplemented(); + return nullptr; + } + virtual bool end_of_stream() { + unimplemented(); + return true; + } + + // HTTP + // Returns a token which will be used with the corresponding onHttpCallResponse. + virtual WasmResult httpCall(string_view /* target */, const Pairs & /*request_headers */, + string_view /* request_body */, const Pairs & /* request_trailers */, + int /* timeout_millisconds */, uint32_t * /* token_ptr */) { + unimplemented(); + return WasmResult::Unimplemented; + } + + // gRPC + // Returns a token which will be used with the corresponding onGrpc and grpc calls. + virtual WasmResult grpcCall(string_view /* grpc_service */, string_view /* service_name */, + string_view /* method_name */, string_view /* request */, + const optional & /* timeout */, + uint32_t * /* token_ptr */) { + unimplemented(); + return WasmResult::Unimplemented; + } + virtual WasmResult grpcStream(string_view /* grpc_service */, string_view /* service_name */, + string_view /* method_name */, uint32_t * /* token_ptr */) { + unimplemented(); + return WasmResult::Unimplemented; + } + virtual WasmResult grpcClose(uint32_t /* token */) { // cancel on call, close on stream. + unimplemented(); + return WasmResult::Unimplemented; + } + virtual WasmResult grpcCancel(uint32_t /* token */) { // cancel on call, reset on stream. + unimplemented(); + return WasmResult::Unimplemented; + } + virtual WasmResult grpcSend(uint32_t /* token */, string_view /* message */, + bool /* end_stream */) { // stream only + unimplemented(); + return WasmResult::Unimplemented; + } + + // Metrics + virtual WasmResult defineMetric(MetricType /* type */, string_view /* name */, + uint32_t * /* metric_id_ptr */) { + unimplemented(); + return WasmResult::Unimplemented; + } + virtual WasmResult incrementMetric(uint32_t /* metric_id */, int64_t /* offset */) { + unimplemented(); + return WasmResult::Unimplemented; + } + virtual WasmResult recordMetric(uint32_t /* metric_id */, uint64_t /* value */) { + unimplemented(); + return WasmResult::Unimplemented; + } + virtual WasmResult getMetric(uint32_t /* metric_id */, uint64_t * /* value_ptr */) { + unimplemented(); + return WasmResult::Unimplemented; + } + + // Properties + virtual WasmResult getProperty(string_view /* path */, std::string * /* result */) { + unimplemented(); + return WasmResult::Unimplemented; + } + virtual WasmResult setProperty(string_view /* key */, string_view /* serialized_value */) { + unimplemented(); + return WasmResult::Unimplemented; + } + + // Continue + virtual void continueRequest() { unimplemented(); } + virtual void continueResponse() { unimplemented(); } + virtual void sendLocalResponse(uint64_t /* response_code */, string_view /* body_text */, + Pairs /* additional_headers */, uint64_t /* grpc_status */, + string_view /* details */) { + unimplemented(); + } + + // Shared Data + virtual WasmResult getSharedData(string_view /* key */, + std::pair * /* data */); + virtual WasmResult setSharedData(string_view /* key */, string_view /* value */, + uint32_t /* cas */); + + // Shared Queue + virtual uint32_t registerSharedQueue(string_view /* queue_name */); + virtual WasmResult resolveSharedQueue(string_view /* vm_id */, string_view /* queue_name */, + uint32_t * /* token */); + virtual WasmResult dequeueSharedQueue(uint32_t /* token */, std::string * /* data */); + virtual WasmResult enqueueSharedQueue(uint32_t /* token */, string_view /* value */); + + // Header/Trailer/Metadata Maps + virtual void addHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, + string_view /* value */) { + unimplemented(); + } + virtual string_view getHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */) { + unimplemented(); + return ""; + } + virtual Pairs getHeaderMapPairs(WasmHeaderMapType /* type */) { + unimplemented(); + return {}; + } + virtual void setHeaderMapPairs(WasmHeaderMapType /* type */, const Pairs & /* pairs */) { + unimplemented(); + } + + virtual void removeHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */) { + unimplemented(); + } + virtual void replaceHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, + string_view /* value */) { + unimplemented(); + } + + virtual uint32_t getHeaderMapSize(WasmHeaderMapType /* type */) { + unimplemented(); + return 0; + } + +protected: + friend class WasmBase; + + virtual void initializeRoot(WasmBase *wasm, std::shared_ptr plugin); + std::string makeRootLogPrefix(string_view vm_id) const; + + WasmBase *wasm_{nullptr}; + uint32_t id_{0}; + uint32_t root_context_id_{0}; // 0 for roots and the general context. + ContextBase *root_context_{nullptr}; // set in all contexts. + std::string root_id_; // set only in root context. + std::string root_log_prefix_; // set only in root context. + std::shared_ptr plugin_; + bool in_vm_context_created_ = false; + bool destroyed_ = false; +}; + +uint32_t resolveQueueForTest(string_view vm_id, string_view queue_name); + +} // namespace proxy_wasm diff --git a/include/proxy-wasm/wasm_vm.h b/include/proxy-wasm/wasm_vm.h index b3a2106a..da6f4daa 100644 --- a/include/proxy-wasm/wasm_vm.h +++ b/include/proxy-wasm/wasm_vm.h @@ -17,6 +17,7 @@ #include "include/proxy-wasm/compat.h" +#include #include #include "include/proxy-wasm/word.h" From 88b5cd624a6d131cf3bd2fcf4fb24885b9d83523 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Tue, 10 Mar 2020 18:30:19 +0000 Subject: [PATCH 02/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index b21126d7..a975d95b 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -41,7 +41,16 @@ using CallOnThreadFunction = std::function)>; struct BufferInterface { virtual ~BufferInterface() {} virtual size_t size() const = 0; - // Returns true on success. + /** + * Copy bytes from the buffer into the Wasm VM corresponding to 'wasm'. + * @param start is the first buffer byte to copy. + * @param length is the length of sequence of buffer bytes to copy. + * @param ptr_ptr is the location in the VM address space to place the address of the newly + * allocated memory block which contains the copied bytes. + * @param size_ptr is the location in the VM address space to place the size of the newly + * allocated memory block which contains the copied bytes (e.g. length). + * @return true on success. + */ virtual bool copyTo(WasmBase *wasm, size_t start, size_t length, uint64_t ptr_ptr, uint64_t size_ptr) const = 0; }; From c03beb3680a587b21396c57b99ed4baf3309e29a Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Thu, 12 Mar 2020 00:59:06 +0000 Subject: [PATCH 03/19] Add tests. Signed-off-by: John Plevyak --- context_test.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 context_test.cc diff --git a/context_test.cc b/context_test.cc new file mode 100644 index 00000000..14cd1377 --- /dev/null +++ b/context_test.cc @@ -0,0 +1,20 @@ +#include "include/proxy-wasm/context.h" + +#include "gtest/gtest.h" + +namespace proxy_wasm { +namespace { + +class Context : public ContextBase { +public: + Context(std::function error_function) : error_function_(error_function) {} + void error(string_view message) { error_function_(message); } + +private: + std::function error_function_; +}; + +TEST(Context, IncludeParses) {} + +} // namespace +} // namespace proxy_wasm From 23bb4b1886bb0d05d4be89fea29639232801b8f8 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Thu, 12 Mar 2020 22:35:47 +0000 Subject: [PATCH 04/19] Add comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context.h | 463 ++++++++++++++++++++++++++++++----- 1 file changed, 407 insertions(+), 56 deletions(-) diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index a975d95b..d7e6b4e3 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -34,6 +34,13 @@ namespace proxy_wasm { class WasmBase; class WasmVm; +// TODO: use the SDK version when it is updated. +enum class ProxyAction : uint32_t { + Illegal = 0, + Continue = 1, + Pause = 2, +}; + using Pairs = std::vector>; using PairsWithStringValues = std::vector>; using CallOnThreadFunction = std::function)>; @@ -55,12 +62,8 @@ struct BufferInterface { uint64_t size_ptr) const = 0; }; -// Opaque context object. -class StorageObject { -public: - virtual ~StorageObject() = default; -}; - +// A container to hold plugin information which is shared with all Context(s) created for this +// plugin. struct PluginBase { PluginBase(string_view name, string_view root_id, string_view vm_id, string_view plugin_configuration) @@ -99,103 +102,248 @@ class ContextBase { string_view log_prefix() const { return plugin_->log_prefix(); } WasmVm *wasmVm() const; - // Called before deleting the context. - virtual void destroy(); - // - // VM level downcalls into the WASM code on Context(id == 0). + // Calls into the VM. // + + // Root Context + + /** + * Call on a Root Context when a VM first starts up. + * @param plugin is the plugin which caused the VM to be started. + */ virtual bool onStart(std::shared_ptr plugin); + + /** + * Call on a Root Context when a plugin is configured or reconfigured dyanmically. + * @param plugin is the plugin which is being configured or reconfigured. + */ virtual bool onConfigure(std::shared_ptr plugin); - // - // Stream downcalls on Context(id > 0). - // - // General stream downcall on a new stream. - virtual void onCreate(uint32_t root_context_id); + // Context + + /** + * Call on a host Context to create a corresponding Context in the VM. Note: + * onNetworkNewConnection and onRequestHeaders() call onCreate(). + * @param parent_context_id is the parent Context id for the context being created. For a Network + * stream Context, this will be a Root Context id. + */ + virtual void onCreate(uint32_t parent_context_id); + // Network - virtual FilterStatus onNetworkNewConnection() { + + /** + * Call on a stream Context to indicate that a new network connection has been been created. + * Calls onStart(). + */ + virtual ProxyAction onNetworkNewConnection() { unimplemented(); - return FilterStatus::Continue; + return ProxyAction::Continue; } - virtual FilterStatus onDownstreamData(int /* data_length */, bool /* end_of_stream */) { + /** + * Call on a stream Context to indicate that data has arrived from downstream (e.g. on the + * incoming port that was accepted and for which the proxy is acting as a server). + * @param data_length the amount of data in the buffer. + * @param end_of_stream is true if no more data will be arriving. + * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause + * proxying. + */ + virtual ProxyAction onDownstreamData(int /* data_length */, bool /* end_of_stream */) { unimplemented(); - return FilterStatus::Continue; + return ProxyAction::Continue; } - virtual FilterStatus onUpstreamData(int /* data_length */, bool /* end_of_stream */) { + /** + * Call on a stream Context to indicate that data has arrived from upstream (e.g. on the outgoing + * port that the proxy connected and for which the proxy is acting as a client). + * @param data_length the amount of data in the buffer. + * @param end_of_stream is true if no more data will be arriving. + * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause + * proxying. + */ + virtual ProxyAction onUpstreamData(int /* data_length */, bool /* end_of_stream */) { unimplemented(); - return FilterStatus::Continue; + return ProxyAction::Continue; } - enum class PeerType : uint32_t { + + /* + * The source of the close event. + * Unknown is when the source is not known. + * Local is when the close was initiated by the proxy. + * Remote is when the close was recieved from the peer. + */ + enum class CloseType : uint32_t { Unknown = 0, Local = 1, Remote = 2, }; - virtual void onDownstreamConnectionClose(PeerType) { unimplemented(); } - virtual void onUpstreamConnectionClose(PeerType) { unimplemented(); } - // HTTP Filter Stream Request Downcalls. - virtual FilterHeadersStatus onRequestHeaders() { + + /** + * Call on a stream context to indicate that the downstream connection has closed. + * @close_type is the source of the close. + */ + virtual void onDownstreamConnectionClose(CloseType /* close_type */) { unimplemented(); } + + /** + * Call on a stream context to indicate that the upstream connection has closed. + * @close_type is the source of the close. + */ + virtual void onUpstreamConnectionClose(CloseType /* close_type */) { unimplemented(); } + + // HTTP + + /** + * Call on a stream context to indicate that the request headers have arrived. Calls onCreate(). + */ + virtual ProxyAction onRequestHeaders() { unimplemented(); - return FilterHeadersStatus::Continue; + return ProxyAction::Continue; } - virtual FilterDataStatus onRequestBody(int /* body_buffer_length */, bool /* end_of_stream */) { + + /** + * Call on a stream context to indicate that body data has arrived. + * @param body_buffer_length the amount of data in the body buffer. + * @param end_of_stream is true if no more body data will be arriving. + */ + virtual ProxyAction onRequestBody(int /* body_buffer_length */, bool /* end_of_stream */) { unimplemented(); - return FilterDataStatus::Continue; + return ProxyAction::Continue; } - virtual FilterTrailersStatus onRequestTrailers() { + + /** + * Call on a stream context to indicate that the request trailers have arrived. + */ + virtual ProxyAction onRequestTrailers() { unimplemented(); - return FilterTrailersStatus::Continue; + return ProxyAction::Continue; } - virtual FilterMetadataStatus onRequestMetadata() { + + /** + * Call on a stream context to indicate that the request metadata has arrived. + */ + virtual ProxyAction onRequestMetadata() { unimplemented(); - return FilterMetadataStatus::Continue; + return ProxyAction::Continue; } - // HTTP Filter Stream Response Downcalls. - virtual FilterHeadersStatus onResponseHeaders() { + + /** + * Call on a stream context to indicate that the request trailers have arrived. + */ + virtual ProxyAction onResponseHeaders() { unimplemented(); - return FilterHeadersStatus::Continue; + return ProxyAction::Continue; } - virtual FilterDataStatus onResponseBody(int /* body_buffer_length */, bool /* end_of_stream */) { + + /** + * Call on a stream context to indicate that body data has arrived. + * @param body_buffer_length the amount of data in the body buffer. + * @param end_of_stream is true if no more body data will be arriving. + */ + virtual ProxyAction onResponseBody(int /* body_buffer_length */, bool /* end_of_stream */) { unimplemented(); - return FilterDataStatus::Continue; + return ProxyAction::Continue; } - virtual FilterTrailersStatus onResponseTrailers() { + + /** + * Call on a stream context to indicate that the request trailers have arrived. + */ + virtual ProxyAction onResponseTrailers() { unimplemented(); - return FilterTrailersStatus::Continue; + return ProxyAction::Continue; } - virtual FilterMetadataStatus onResponseMetadata() { + + /** + * Call on a stream context to indicate that the request metadata has arrived. + */ + virtual ProxyAction onResponseMetadata() { unimplemented(); - return FilterMetadataStatus::Continue; + return ProxyAction::Continue; } - // Async call response. + + // Root Context async events + + /** + * Called on a Root Context when a response arrives for an outstanding httpCall(). + * @param token is the token returned by the corresponding httpCall(). + * @param headers are the number of headers in the response. + * @param body_size is the size in bytes of the response body. + * @param trailers is the number of trailres in the response. + */ virtual void onHttpCallResponse(uint32_t /* token */, uint32_t /* headers */, uint32_t /* body_size */, uint32_t /* trailers */) {} - // Inter-VM shared queue message arrival. + + /** + * Called on a Root Context to indicate that an Inter-VM shared queue message has arrived. + * @token is the token returned by registerSharedQueue(). + */ virtual void onQueueReady(uint32_t /* token */) { unimplemented(); } - // General stream downcall when the stream/vm has ended. + + // Context + + /** + * Call when a stream has completed (both sides have closed) or on a Root Context when the VM is + * shutting down. + * @return true for stream contexts or for Root Context(s) if the VM can shutdown, false for Root + * Context(s) if the VM should wait until the Root Context calls the proxy_done() ABI call. Note: + * the VM may (optionally) shutdown after some configured timeout even if the Root Context does + * not call proxy_done(). + */ virtual bool onDone(); - // General stream downcall for logging. Occurs after onDone(). + + /** + * Call when a stream should log the final status of the stream. Occurs after onDone(). + */ virtual void onLog(); - // General stream downcall when no further stream calls will occur. + + /** + * Call when no further stream calls will occur. This will cause the corresponding Context in the + * VM to be deleted. + */ virtual void onDelete(); + /** + * Will be called on sever Wasm errors. Callees may report and handle the error (e.g. via an + * Exception) to prevent the proxy from crashing. + */ virtual void error(string_view message) { std::cerr << message << "\n"; abort(); } + + /** + * Called by all functions which are not overriden with a proxy-specific implementation. + */ virtual void unimplemented() { error("unimplemented proxy-wasm API"); } // - // General Callbacks. + // Calls from the VM> + // Note: most of these return a WasmResult, assume: + // @return a WasmResult with the status of the call. + // // + + /** + * Log a message. Note: log_prefix() is *not* auto-prepended end may be useful to provide some + * context. + */ virtual WasmResult log(uint64_t /* level */, string_view /* message */) { unimplemented(); return WasmResult::Unimplemented; } + + /** + * Enables a periodic timer with the given period or sets the period of an existing timer. Note: + * the timer is associated with the Root Context of whatever Context this call was made on and + * there is only one timer available per Root Context. + * @param period is the period of the periodic timer in milliseconds. + */ virtual WasmResult setTimerPeriod(std::chrono::milliseconds /* period */) { unimplemented(); return WasmResult::Unimplemented; } + + /** + * Provides the current time in nanoseconds. + */ virtual uint64_t getCurrentTimeNanoseconds() { struct timespec tpe; clock_gettime(CLOCK_REALTIME, &tpe); @@ -204,23 +352,48 @@ class ContextBase { t += tpe.tv_nsec; return t; } + + /** + * Provides the status of the call into the VM or out of the VM. + * @return the status code and a descriptive string. + */ virtual std::pair getStatus() { unimplemented(); return std::make_pair(1, "unimplmemented"); } // Buffer + + /** + * Provides a BufferInterface to be used to return buffered data to the VM. + * @param type is the type of buffer to provide. + */ virtual const BufferInterface *getBuffer(WasmBufferType /* type */) { unimplemented(); return nullptr; } + + /** + * Provides the end-of-stream status of the current stream (if any) or false. + */ virtual bool end_of_stream() { unimplemented(); return true; } // HTTP - // Returns a token which will be used with the corresponding onHttpCallResponse. + + /** + * Make an outgoing HTTP request. + * @param target specifies the proxy-specific target of the call (e.g. a cluster, peer, or host). + * @param request_headers are the request headers. + * @param request_body is the request body. + * @param request_trailers are the request trailers. + * @param timeout_milliseconds is a timeout after which the request will be conidered to have + * failed. + * @param token_ptr contains a pointer to a location to store the token which will be used with + * the corresponding onHttpCallResponse. + */ virtual WasmResult httpCall(string_view /* target */, const Pairs & /*request_headers */, string_view /* request_body */, const Pairs & /* request_trailers */, int /* timeout_millisconds */, uint32_t * /* token_ptr */) { @@ -229,27 +402,66 @@ class ContextBase { } // gRPC - // Returns a token which will be used with the corresponding onGrpc and grpc calls. + + /** + * Make a gRPC call. + * @param grpc_service is proxy-specific metadata describing the service (e.g. security certs). + * @param service_name the name of the gRPC service. + * @param method_name the gRPC method name. + * @param request the serialized request. + * @param initial_metadata the initial metadata. + * @param timeout a timeout in milliseconds. + * @param token_ptr contains a pointer to a location to store the token which will be used with + * the corresponding onGrpc and grpc calls. + */ virtual WasmResult grpcCall(string_view /* grpc_service */, string_view /* service_name */, string_view /* method_name */, string_view /* request */, + const Pairs & /* initial_metadata */, const optional & /* timeout */, uint32_t * /* token_ptr */) { unimplemented(); return WasmResult::Unimplemented; } + + /** + * Open a gRPC stream. + * @param grpc_service is proxy-specific metadata describing the service (e.g. security certs). + * @param service_name the name of the gRPC service. + * @param method_name the gRPC method name. + * @param token_ptr contains a pointer to a location to store the token which will be used with + * the corresponding onGrpc and grpc calls. + */ virtual WasmResult grpcStream(string_view /* grpc_service */, string_view /* service_name */, string_view /* method_name */, uint32_t * /* token_ptr */) { unimplemented(); return WasmResult::Unimplemented; } + + /** + * Close a gRPC stream. In flight data may stil result in calls into the VM. + * @param token is a token returned from grpcSream. + */ virtual WasmResult grpcClose(uint32_t /* token */) { // cancel on call, close on stream. unimplemented(); return WasmResult::Unimplemented; } + + /** + * Cancel a gRPC stream or call. No more calls will occur. + * @param token is a token returned from grpcSream or grpcCall. + */ virtual WasmResult grpcCancel(uint32_t /* token */) { // cancel on call, reset on stream. unimplemented(); return WasmResult::Unimplemented; } + + /** + * Close a gRPC stream. In flight data may stil result in calls into the VM. + * @param token is a token returned from grpcSream. + * @param message is a (serialized) message to be sent. + * @param end_stream indicates that the stream is now end_of_stream (e.g. WriteLast() or + * WritesDone). + */ virtual WasmResult grpcSend(uint32_t /* token */, string_view /* message */, bool /* end_stream */) { // stream only unimplemented(); @@ -257,81 +469,221 @@ class ContextBase { } // Metrics + + /** + * Define a metric (Stat). + * @param type is the type of metric (e.g. Counter). + * @param name is a string uniquely identifying the metric. + * @param metric_id_ptr is a location to store a token used for subsequent operations on the + * metric. + */ virtual WasmResult defineMetric(MetricType /* type */, string_view /* name */, uint32_t * /* metric_id_ptr */) { unimplemented(); return WasmResult::Unimplemented; } + + /** + * Increment a metric. + * @param metric_id is a token returned by defineMetric() identifying the metric to operate on. + * @param offset is the offset to apply to the Counter. + */ virtual WasmResult incrementMetric(uint32_t /* metric_id */, int64_t /* offset */) { unimplemented(); return WasmResult::Unimplemented; } + + /** + * Record a metric. + * @param metric_id is a token returned by defineMetric() identifying the metric to operate on. + * @param value is the value to store for a Gauge or increment for a histogram or Counter. + */ virtual WasmResult recordMetric(uint32_t /* metric_id */, uint64_t /* value */) { unimplemented(); return WasmResult::Unimplemented; } + + /** + * Get the current value of a metric. + * @param metric_id is a token returned by defineMetric() identifying the metric to operate on. + * @param value_ptr is a location to store the value of the metric. + */ virtual WasmResult getMetric(uint32_t /* metric_id */, uint64_t * /* value_ptr */) { unimplemented(); return WasmResult::Unimplemented; } // Properties + + /** + * Get the value of a property. Some properties are proxy-independent (e.g. ["plugin_root_id"]) + * while others can be proxy-specific. + * @param path is a sequence of strings describing a path to a property. + * @param result is a location to write the value of the property. + */ virtual WasmResult getProperty(string_view /* path */, std::string * /* result */) { unimplemented(); return WasmResult::Unimplemented; } - virtual WasmResult setProperty(string_view /* key */, string_view /* serialized_value */) { + + /** + * Set the value of a property. + * @param path is a sequence of strings describing a path to a property. + * @param value the value to set. For non-string, non-integral types, the value may be + * serialized.. + */ + virtual WasmResult setProperty(string_view /* key */, string_view /* value */) { unimplemented(); return WasmResult::Unimplemented; } // Continue + + /** + * Continue processing a request e.g. after returning ProxyAction::Pause. + */ virtual void continueRequest() { unimplemented(); } + + /** + * Continue processing a response e.g. after returning ProxyAction::Pause. + */ virtual void continueResponse() { unimplemented(); } - virtual void sendLocalResponse(uint64_t /* response_code */, string_view /* body_text */, + + /** + * Respond directly to an HTTP request. + * @param response_code is the response code to send. + * @param body is the body of the response. + * @param additional_headers are additional headers to send in the response. + * @param grpc_status is an optional gRPC status if the connection is a gRPC connection. + * @param details are details of any (gRPC) error. + */ + virtual void sendLocalResponse(uint64_t /* response_code */, string_view /* body */, Pairs /* additional_headers */, uint64_t /* grpc_status */, string_view /* details */) { unimplemented(); } // Shared Data + + /** + * Get proxy-wide key-value data shared between VMs. + * @param key is a proxy-wide key mapping to the shared data value. + * @param cas is a number which will be incremented when a data value has been changed. + * @param data is a location to store the returned value. + */ virtual WasmResult getSharedData(string_view /* key */, std::pair * /* data */); + + /** + * Set a key-value data shared between VMs. + * @param key is a proxy-wide key mapping to the shared data value. + * @param cas is a compare-and-swap value. If it is zero it is ignored, otherwise it must match + * the cas associated with the value. + * @param data is a location to store the returned value. + */ virtual WasmResult setSharedData(string_view /* key */, string_view /* value */, uint32_t /* cas */); // Shared Queue - virtual uint32_t registerSharedQueue(string_view /* queue_name */); + + /** + * Register a proxy-wide queue. + * @param queue_name is a name for the queue. The queue_name is combined with the vm_id (if any) + * to make a unique identifier for the queue. + * @param token_ptr a location to store a token corresponding to the queue. + */ + virtual WasmResult registerSharedQueue(string_view /* queue_name */, uint32_t *token_ptr); + + /** + * Get the token for a queue. + * @param vm_id is the vm_id of the Plugin of the Root Context which registered the queue. + * @param queue_name is a name for the queue. The queue_name is combined with the vm_id (if any) + * to make a unique identifier for the queue. + * @param token_ptr a location to store a token corresponding to the queue. + */ virtual WasmResult resolveSharedQueue(string_view /* vm_id */, string_view /* queue_name */, - uint32_t * /* token */); - virtual WasmResult dequeueSharedQueue(uint32_t /* token */, std::string * /* data */); + uint32_t * /* token_ptr */); + + /** + * Dequeue a message from a shared queue. + * @param token is a token returned by registerSharedQueue(); + * @param data_ptr is a location to store the data dequeued. + */ + virtual WasmResult dequeueSharedQueue(uint32_t /* token */, std::string * /* data_ptr */); + + /** + * Enqueue a message on a shared queue. + * @param token is a token returned by resolveSharedQueue(); + * @param data is the data to be queued. + */ virtual WasmResult enqueueSharedQueue(uint32_t /* token */, string_view /* value */); // Header/Trailer/Metadata Maps + + /** + * Add a key-value pair to a header map. + * @param type of the header map. + * @param key is the key (header). + * @param value is the value (header value). + */ virtual void addHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, string_view /* value */) { unimplemented(); } + + /** + * Get a value from to a header map. + * @param type of the header map. + * @param key is the key (header). + */ virtual string_view getHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */) { unimplemented(); return ""; } + + /** + * Get all the key-value pairs in a header map. + * @param type of the header map. + * @return the pairs. + */ virtual Pairs getHeaderMapPairs(WasmHeaderMapType /* type */) { unimplemented(); return {}; } + + /** + * Set a header map so that it contains the given pairs (does not merge with existing data). + * @param type of the header map. + * @param the pairs to set the header map to. + */ virtual void setHeaderMapPairs(WasmHeaderMapType /* type */, const Pairs & /* pairs */) { unimplemented(); } + /** + * Remove a key-value pair from a header map. + * @param type of the header map. + * @param key of the header map. + */ virtual void removeHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */) { unimplemented(); } + + /** + * Replace (or set) a value in a header map. + * @param type of the header map. + * @param key of the header map. + * @param value to set in the header map. + */ virtual void replaceHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, string_view /* value */) { unimplemented(); } + /** + * Returns the number of entries in a header map. + * @param type of the header map. + */ virtual uint32_t getHeaderMapSize(WasmHeaderMapType /* type */) { unimplemented(); return 0; @@ -351,7 +703,6 @@ class ContextBase { std::string root_log_prefix_; // set only in root context. std::shared_ptr plugin_; bool in_vm_context_created_ = false; - bool destroyed_ = false; }; uint32_t resolveQueueForTest(string_view vm_id, string_view queue_name); From 07be628dff6c0c8fc574b3f8ae93aa0fb9241535 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Fri, 13 Mar 2020 17:38:47 +0000 Subject: [PATCH 05/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context.h | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index d7e6b4e3..c4f5510f 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -45,6 +45,11 @@ using Pairs = std::vector>; using PairsWithStringValues = std::vector>; using CallOnThreadFunction = std::function)>; +/** + * BufferInterface provides a interface between proxy-specifc buffers and the proxy-independent ABI + * implementation. Embedders should subclass BufferInterface to enable the proxy-independent code to + * implement ABI calls which use buffers (e.g. the HTTP body). + */ struct BufferInterface { virtual ~BufferInterface() {} virtual size_t size() const = 0; @@ -62,8 +67,11 @@ struct BufferInterface { uint64_t size_ptr) const = 0; }; -// A container to hold plugin information which is shared with all Context(s) created for this -// plugin. +/** + * PluginBase is container to hold plugin information which is shared with all Context(s) created + * for a given plugin. Embedders may extend this class with additional host-specific plugin + * information as required. + */ struct PluginBase { PluginBase(string_view name, string_view root_id, string_view vm_id, string_view plugin_configuration) @@ -82,8 +90,21 @@ struct PluginBase { std::string log_prefix_; }; -// A context which will be the target of callbacks for a particular session -// e.g. a handler of a stream. +/** + * ContextBase is the interface between the VM host and the VM. It has several uses: + * + * 1) To provide host-specific implementations of ABI calls out of the VM. For example, a proxy + * which wants to provide the ability to make an HTTP call must implement the + * ContextBase::httpCall() method. + * + * 2) To call into the VM. For example, when the above mentioned httpCall() completes, the host must + * call ContextBase::onHttpCallResponse(). Similarly, when a new HTTP request arrives and the + * headers are available, the host must create a new ContextBase object to manage the new stream and + * call onRequestHeaders() on that object which will cause a corresponding Context to be allocated + * in the VM which will receive the proxy_on_context_create and proxy_on_request_headers calls. + * + * 3) For testing and instrumentation the methods of ContextBase can be replaces or augmented. + */ class ContextBase { public: ContextBase(); // Testing. From 7ef8976a1e99ceae885f5188d6e30f46a259aeaf Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Fri, 13 Mar 2020 17:39:36 +0000 Subject: [PATCH 06/19] Address comments. Signed-off-by: John Plevyak --- VERSIONING.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 VERSIONING.md diff --git a/VERSIONING.md b/VERSIONING.md new file mode 100644 index 00000000..86103c25 --- /dev/null +++ b/VERSIONING.md @@ -0,0 +1,3 @@ +# ABI Versioning + +TODO From daeae36573d2666636c820baacb519c19a489c53 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Tue, 17 Mar 2020 00:47:39 +0000 Subject: [PATCH 07/19] Address comments. Signed-off-by: John Plevyak --- BUILD | 8 +- include/proxy-wasm/context.h | 209 ++++++++++++------------ context_test.cc => test/context_test.cc | 0 wasm_vm_test.cc => test/wasm_vm_test.cc | 0 4 files changed, 111 insertions(+), 106 deletions(-) rename context_test.cc => test/context_test.cc (100%) rename wasm_vm_test.cc => test/wasm_vm_test.cc (100%) diff --git a/BUILD b/BUILD index e2de48ce..08bcdc72 100644 --- a/BUILD +++ b/BUILD @@ -32,7 +32,7 @@ cc_library( cc_test( name = "wasm_vm_test", - srcs = ["wasm_vm_test.cc"], + srcs = ["test/wasm_vm_test.cc"], deps = [ ":include", "@com_google_googletest//:gtest", @@ -42,7 +42,7 @@ cc_test( cc_test( name = "context_test", - srcs = ["context_test.cc"], + srcs = ["test/context_test.cc"], deps = [ ":include", "@com_google_googletest//:gtest", @@ -53,7 +53,7 @@ cc_test( # TODO: remove when dependent projects have been upgraded. cc_test( name = "wasm_vm_14_test", - srcs = ["wasm_vm_test.cc"], + srcs = ["test/wasm_vm_test.cc"], copts = ["-std=c++14"], deps = [ ":include14", @@ -67,7 +67,7 @@ cc_test( cc_test( name = "context_14_test", - srcs = ["context_test.cc"], + srcs = ["test/context_test.cc"], copts = ["-std=c++14"], deps = [ ":include14", diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index c4f5510f..74fae74d 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -46,7 +46,7 @@ using PairsWithStringValues = std::vector>; using CallOnThreadFunction = std::function)>; /** - * BufferInterface provides a interface between proxy-specifc buffers and the proxy-independent ABI + * BufferInterface provides a interface between proxy-specific buffers and the proxy-independent ABI * implementation. Embedders should subclass BufferInterface to enable the proxy-independent code to * implement ABI calls which use buffers (e.g. the HTTP body). */ @@ -60,23 +60,27 @@ struct BufferInterface { * @param ptr_ptr is the location in the VM address space to place the address of the newly * allocated memory block which contains the copied bytes. * @param size_ptr is the location in the VM address space to place the size of the newly - * allocated memory block which contains the copied bytes (e.g. length). - * @return true on success. + * allocated memory block which contains the copied bytes (i.e. length). + * @return a WasmResult with any error or WasmResult::Ok. */ - virtual bool copyTo(WasmBase *wasm, size_t start, size_t length, uint64_t ptr_ptr, - uint64_t size_ptr) const = 0; + virtual WasmResult copyTo(WasmBase *wasm, size_t start, size_t length, uint64_t ptr_ptr, + uint64_t size_ptr) const = 0; }; /** * PluginBase is container to hold plugin information which is shared with all Context(s) created * for a given plugin. Embedders may extend this class with additional host-specific plugin * information as required. + * @param name is the name of the plugin. + * @param root_id is an identifier for the in VM handlers for this plugin. + * @param vm_id is a string used to differentiate VMs with the same code and VM configuration. + * @param plugin_configuration is configuration for this plugin. */ struct PluginBase { PluginBase(string_view name, string_view root_id, string_view vm_id, string_view plugin_configuration) : name_(std::string(name)), root_id_(std::string(root_id)), vm_id_(std::string(vm_id)), - plugin_configuration_(plugin_configuration) {} + plugin_configuration_(plugin_configuration), log_prefix_(makeLogPrefix()) {} const std::string name_; const std::string root_id_; @@ -116,27 +120,25 @@ class ContextBase { WasmBase *wasm() const { return wasm_; } uint32_t id() const { return id_; } + // The VM Context used for calling "malloc" has an id_ == 0. bool isVmContext() { return id_ == 0; } + // Root Contexts have the VM Context as a parent. bool isRootContext() { return root_context_id_ == 0; } ContextBase *root_context() { return root_context_; } string_view root_id() const { return plugin_->root_id_; } string_view log_prefix() const { return plugin_->log_prefix(); } WasmVm *wasmVm() const; - // - // Calls into the VM. - // - - // Root Context - /** - * Call on a Root Context when a VM first starts up. - * @param plugin is the plugin which caused the VM to be started. + * Calls into the VM. + * These are implemented by the proxy-independent host code. They are virtual to support some + * types of testing. */ - virtual bool onStart(std::shared_ptr plugin); + + // Root Context /** - * Call on a Root Context when a plugin is configured or reconfigured dyanmically. + * Call on a Root Context when a plugin is configured or reconfigured dynamically. * @param plugin is the plugin which is being configured or reconfigured. */ virtual bool onConfigure(std::shared_ptr plugin); @@ -151,16 +153,18 @@ class ContextBase { */ virtual void onCreate(uint32_t parent_context_id); - // Network + /** + * Network + * Note: Body data is obtained by the code in the VM via calls implemented by the + * proxy-independent host code using the getBuffer() call. + */ /** * Call on a stream Context to indicate that a new network connection has been been created. * Calls onStart(). */ - virtual ProxyAction onNetworkNewConnection() { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onNetworkNewConnection(); + /** * Call on a stream Context to indicate that data has arrived from downstream (e.g. on the * incoming port that was accepted and for which the proxy is acting as a server). @@ -169,10 +173,8 @@ class ContextBase { * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause * proxying. */ - virtual ProxyAction onDownstreamData(int /* data_length */, bool /* end_of_stream */) { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onDownstreamData(uint32_t data_length, bool end_of_stream); + /** * Call on a stream Context to indicate that data has arrived from upstream (e.g. on the outgoing * port that the proxy connected and for which the proxy is acting as a client). @@ -181,16 +183,13 @@ class ContextBase { * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause * proxying. */ - virtual ProxyAction onUpstreamData(int /* data_length */, bool /* end_of_stream */) { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onUpstreamData(uint32_t data_length, bool end_of_stream); /* * The source of the close event. * Unknown is when the source is not known. * Local is when the close was initiated by the proxy. - * Remote is when the close was recieved from the peer. + * Remote is when the close was received from the peer. */ enum class CloseType : uint32_t { Unknown = 0, @@ -202,83 +201,64 @@ class ContextBase { * Call on a stream context to indicate that the downstream connection has closed. * @close_type is the source of the close. */ - virtual void onDownstreamConnectionClose(CloseType /* close_type */) { unimplemented(); } + virtual void onDownstreamConnectionClose(CloseType close_type); /** * Call on a stream context to indicate that the upstream connection has closed. * @close_type is the source of the close. */ - virtual void onUpstreamConnectionClose(CloseType /* close_type */) { unimplemented(); } + virtual void onUpstreamConnectionClose(CloseType close_type); - // HTTP + /* + * HTTP + * Note: headers and trailers are obtained by the code in the VM via the XXXHeaderMapXXX set of + * functions. Body data is obtained by the code in the VM via calls implemented by the + * proxy-independent host code using the getBuffer() call. + */ /** * Call on a stream context to indicate that the request headers have arrived. Calls onCreate(). */ - virtual ProxyAction onRequestHeaders() { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onRequestHeaders(); /** * Call on a stream context to indicate that body data has arrived. * @param body_buffer_length the amount of data in the body buffer. * @param end_of_stream is true if no more body data will be arriving. */ - virtual ProxyAction onRequestBody(int /* body_buffer_length */, bool /* end_of_stream */) { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onRequestBody(uint32_t body_buffer_length, bool end_of_stream); /** * Call on a stream context to indicate that the request trailers have arrived. */ - virtual ProxyAction onRequestTrailers() { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onRequestTrailers(); /** * Call on a stream context to indicate that the request metadata has arrived. */ - virtual ProxyAction onRequestMetadata() { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onRequestMetadata(); /** * Call on a stream context to indicate that the request trailers have arrived. */ - virtual ProxyAction onResponseHeaders() { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onResponseHeaders(); /** * Call on a stream context to indicate that body data has arrived. * @param body_buffer_length the amount of data in the body buffer. * @param end_of_stream is true if no more body data will be arriving. */ - virtual ProxyAction onResponseBody(int /* body_buffer_length */, bool /* end_of_stream */) { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onResponseBody(uint32_t body_buffer_length, bool end_of_stream); /** * Call on a stream context to indicate that the request trailers have arrived. */ - virtual ProxyAction onResponseTrailers() { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onResponseTrailers(); /** * Call on a stream context to indicate that the request metadata has arrived. */ - virtual ProxyAction onResponseMetadata() { - unimplemented(); - return ProxyAction::Continue; - } + virtual ProxyAction onResponseMetadata(); // Root Context async events @@ -287,16 +267,16 @@ class ContextBase { * @param token is the token returned by the corresponding httpCall(). * @param headers are the number of headers in the response. * @param body_size is the size in bytes of the response body. - * @param trailers is the number of trailres in the response. + * @param trailers is the number of trailers in the response. */ - virtual void onHttpCallResponse(uint32_t /* token */, uint32_t /* headers */, - uint32_t /* body_size */, uint32_t /* trailers */) {} + virtual void onHttpCallResponse(uint32_t token, uint32_t headers, uint32_t body_size, + uint32_t trailers); /** * Called on a Root Context to indicate that an Inter-VM shared queue message has arrived. * @token is the token returned by registerSharedQueue(). */ - virtual void onQueueReady(uint32_t /* token */) { unimplemented(); } + virtual void onQueueReady(uint32_t token); // Context @@ -315,12 +295,6 @@ class ContextBase { */ virtual void onLog(); - /** - * Call when no further stream calls will occur. This will cause the corresponding Context in the - * VM to be deleted. - */ - virtual void onDelete(); - /** * Will be called on sever Wasm errors. Callees may report and handle the error (e.g. via an * Exception) to prevent the proxy from crashing. @@ -331,16 +305,20 @@ class ContextBase { } /** - * Called by all functions which are not overriden with a proxy-specific implementation. + * Called by all functions which are not overridden with a proxy-specific implementation. */ virtual void unimplemented() { error("unimplemented proxy-wasm API"); } - // - // Calls from the VM> - // Note: most of these return a WasmResult, assume: - // @return a WasmResult with the status of the call. - // - // + /** + * Calls from the VM> + * This collection represents all the calls into the VM in the ABI + * (https://github.com/proxy-wasm/spec). They are not broken into separate interfaces because + * doing so would result in duplication since calls into the VM must be overriden by the + * implementations in the ContextBase. + * + * Note: most of these return a WasmResult, assume: + * @return a WasmResult with the status of the call. + */ /** * Log a message. Note: log_prefix() is *not* auto-prepended end may be useful to provide some @@ -375,12 +353,12 @@ class ContextBase { } /** - * Provides the status of the call into the VM or out of the VM. + * Provides the status of the last call into the VM or out of the VM, similar to errno. * @return the status code and a descriptive string. */ virtual std::pair getStatus() { unimplemented(); - return std::make_pair(1, "unimplmemented"); + return std::make_pair(1, "unimplemented"); } // Buffer @@ -410,14 +388,14 @@ class ContextBase { * @param request_headers are the request headers. * @param request_body is the request body. * @param request_trailers are the request trailers. - * @param timeout_milliseconds is a timeout after which the request will be conidered to have + * @param timeout_milliseconds is a timeout after which the request will be considered to have * failed. * @param token_ptr contains a pointer to a location to store the token which will be used with * the corresponding onHttpCallResponse. */ virtual WasmResult httpCall(string_view /* target */, const Pairs & /*request_headers */, string_view /* request_body */, const Pairs & /* request_trailers */, - int /* timeout_millisconds */, uint32_t * /* token_ptr */) { + int /* timeout_milliseconds */, uint32_t * /* token_ptr */) { unimplemented(); return WasmResult::Unimplemented; } @@ -459,8 +437,8 @@ class ContextBase { } /** - * Close a gRPC stream. In flight data may stil result in calls into the VM. - * @param token is a token returned from grpcSream. + * Close a gRPC stream. In flight data may still result in calls into the VM. + * @param token is a token returned from grpcStream. */ virtual WasmResult grpcClose(uint32_t /* token */) { // cancel on call, close on stream. unimplemented(); @@ -477,7 +455,7 @@ class ContextBase { } /** - * Close a gRPC stream. In flight data may stil result in calls into the VM. + * Close a gRPC stream. In flight data may still result in calls into the VM. * @param token is a token returned from grpcSream. * @param message is a (serialized) message to be sent. * @param end_stream indicates that the stream is now end_of_stream (e.g. WriteLast() or @@ -647,29 +625,32 @@ class ContextBase { * @param key is the key (header). * @param value is the value (header value). */ - virtual void addHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, - string_view /* value */) { + virtual WasmResult addHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, + string_view /* value */) { unimplemented(); + return WasmResult::Unimplemented; } /** * Get a value from to a header map. * @param type of the header map. * @param key is the key (header). + * @param result is a pointer to the returned header value. */ - virtual string_view getHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */) { + virtual WasmResult getHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, + string_view *result) { unimplemented(); - return ""; + return WasmResult::Unimplemented; } /** * Get all the key-value pairs in a header map. * @param type of the header map. - * @return the pairs. + * @param result is a pointer to the pairs. */ - virtual Pairs getHeaderMapPairs(WasmHeaderMapType /* type */) { + virtual WasmResult getHeaderMapPairs(WasmHeaderMapType /* type */, Pairs * /* result */) { unimplemented(); - return {}; + return WasmResult::Unimplemented; } /** @@ -677,8 +658,9 @@ class ContextBase { * @param type of the header map. * @param the pairs to set the header map to. */ - virtual void setHeaderMapPairs(WasmHeaderMapType /* type */, const Pairs & /* pairs */) { + virtual WasmResult setHeaderMapPairs(WasmHeaderMapType /* type */, const Pairs & /* pairs */) { unimplemented(); + return WasmResult::Unimplemented; } /** @@ -686,8 +668,9 @@ class ContextBase { * @param type of the header map. * @param key of the header map. */ - virtual void removeHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */) { + virtual WasmResult removeHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */) { unimplemented(); + return WasmResult::Unimplemented; } /** @@ -696,23 +679,45 @@ class ContextBase { * @param key of the header map. * @param value to set in the header map. */ - virtual void replaceHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, - string_view /* value */) { + virtual WasmResult replaceHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, + string_view /* value */) { unimplemented(); + return WasmResult::Unimplemented; } /** * Returns the number of entries in a header map. * @param type of the header map. + * @param result is a pointer to the result. */ - virtual uint32_t getHeaderMapSize(WasmHeaderMapType /* type */) { + virtual WasmResult getHeaderMapSize(WasmHeaderMapType /* type */, uint32_t * /* result */) { unimplemented(); - return 0; + return WasmResult::Unimplemented; } protected: friend class WasmBase; + /** + * Calls into the VM. + * These are implemented and called by the proxy-independent host code. They are virtual to + * support some types of testing. + */ + + /** + * Call on a Root Context when a VM first starts up. + * @param plugin is the plugin which caused the VM to be started. + * Called by the host code. + */ + bool onStart(std::shared_ptr plugin); + + /** + * Call when no further stream calls will occur. This will cause the corresponding Context in the + * VM to be deleted. + * Called by the host code. + */ + virtual void onDelete(); + virtual void initializeRoot(WasmBase *wasm, std::shared_ptr plugin); std::string makeRootLogPrefix(string_view vm_id) const; diff --git a/context_test.cc b/test/context_test.cc similarity index 100% rename from context_test.cc rename to test/context_test.cc diff --git a/wasm_vm_test.cc b/test/wasm_vm_test.cc similarity index 100% rename from wasm_vm_test.cc rename to test/wasm_vm_test.cc From 0fccf245ff8709957262d541eaec74ba18bd7193 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Tue, 17 Mar 2020 17:26:31 +0000 Subject: [PATCH 08/19] Address comments. Signed-off-by: John Plevyak --- BUILD | 14 +-- include/proxy-wasm/context.h | 133 +++++----------------------- include/proxy-wasm/http_interface.h | 101 +++++++++++++++++++++ include/proxy-wasm/proxy_action.h | 27 ++++++ 4 files changed, 152 insertions(+), 123 deletions(-) create mode 100644 include/proxy-wasm/http_interface.h create mode 100644 include/proxy-wasm/proxy_action.h diff --git a/BUILD b/BUILD index 08bcdc72..6758e317 100644 --- a/BUILD +++ b/BUILD @@ -4,12 +4,7 @@ package(default_visibility = ["//visibility:public"]) cc_library( name = "include", - hdrs = [ - "include/proxy-wasm/compat.h", - "include/proxy-wasm/context.h", - "include/proxy-wasm/wasm_vm.h", - "include/proxy-wasm/word.h", - ], + hdrs = glob(["include/proxy-wasm/*.h"]), deps = [ "@proxy_wasm_cpp_sdk//:common_lib", ], @@ -18,12 +13,7 @@ cc_library( # TODO: remove when dependent projects have been upgraded. cc_library( name = "include14", - hdrs = [ - "include/proxy-wasm/compat.h", - "include/proxy-wasm/context.h", - "include/proxy-wasm/wasm_vm.h", - "include/proxy-wasm/word.h", - ], + hdrs = glob(["include/proxy-wasm/*.h"]), copts = ["-std=c++14"], deps = [ "@proxy_wasm_cpp_sdk//:common_lib", diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index 74fae74d..4a91ee13 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -26,6 +26,9 @@ #include #include +#include "include/proxy-wasm/http_interface.h" +#include "include/proxy-wasm/network_interface.h" + namespace proxy_wasm { #include "proxy_wasm_common.h" @@ -34,13 +37,6 @@ namespace proxy_wasm { class WasmBase; class WasmVm; -// TODO: use the SDK version when it is updated. -enum class ProxyAction : uint32_t { - Illegal = 0, - Continue = 1, - Pause = 2, -}; - using Pairs = std::vector>; using PairsWithStringValues = std::vector>; using CallOnThreadFunction = std::function)>; @@ -109,7 +105,7 @@ struct PluginBase { * * 3) For testing and instrumentation the methods of ContextBase can be replaces or augmented. */ -class ContextBase { +class ContextBase : public HttpInterface, NetworkInterface { public: ContextBase(); // Testing. ContextBase(WasmBase *wasm); // Vm Context. @@ -154,111 +150,26 @@ class ContextBase { virtual void onCreate(uint32_t parent_context_id); /** - * Network - * Note: Body data is obtained by the code in the VM via calls implemented by the - * proxy-independent host code using the getBuffer() call. - */ - - /** - * Call on a stream Context to indicate that a new network connection has been been created. - * Calls onStart(). - */ - virtual ProxyAction onNetworkNewConnection(); - - /** - * Call on a stream Context to indicate that data has arrived from downstream (e.g. on the - * incoming port that was accepted and for which the proxy is acting as a server). - * @param data_length the amount of data in the buffer. - * @param end_of_stream is true if no more data will be arriving. - * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause - * proxying. - */ - virtual ProxyAction onDownstreamData(uint32_t data_length, bool end_of_stream); - - /** - * Call on a stream Context to indicate that data has arrived from upstream (e.g. on the outgoing - * port that the proxy connected and for which the proxy is acting as a client). - * @param data_length the amount of data in the buffer. - * @param end_of_stream is true if no more data will be arriving. - * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause - * proxying. + * Network - see network_interface.h */ - virtual ProxyAction onUpstreamData(uint32_t data_length, bool end_of_stream); + ProxyAction onNetworkNewConnection() override; + ProxyAction onDownstreamData(uint32_t data_length, bool end_of_stream) override; + ProxyAction onUpstreamData(uint32_t data_length, bool end_of_stream) override; + using CloseType = NetworkInterface::CloseType; + void onDownstreamConnectionClose(CloseType close_type) override; + void onUpstreamConnectionClose(CloseType close_type) override; /* - * The source of the close event. - * Unknown is when the source is not known. - * Local is when the close was initiated by the proxy. - * Remote is when the close was received from the peer. - */ - enum class CloseType : uint32_t { - Unknown = 0, - Local = 1, - Remote = 2, - }; - - /** - * Call on a stream context to indicate that the downstream connection has closed. - * @close_type is the source of the close. - */ - virtual void onDownstreamConnectionClose(CloseType close_type); - - /** - * Call on a stream context to indicate that the upstream connection has closed. - * @close_type is the source of the close. - */ - virtual void onUpstreamConnectionClose(CloseType close_type); - - /* - * HTTP - * Note: headers and trailers are obtained by the code in the VM via the XXXHeaderMapXXX set of - * functions. Body data is obtained by the code in the VM via calls implemented by the - * proxy-independent host code using the getBuffer() call. - */ - - /** - * Call on a stream context to indicate that the request headers have arrived. Calls onCreate(). - */ - virtual ProxyAction onRequestHeaders(); - - /** - * Call on a stream context to indicate that body data has arrived. - * @param body_buffer_length the amount of data in the body buffer. - * @param end_of_stream is true if no more body data will be arriving. - */ - virtual ProxyAction onRequestBody(uint32_t body_buffer_length, bool end_of_stream); - - /** - * Call on a stream context to indicate that the request trailers have arrived. - */ - virtual ProxyAction onRequestTrailers(); - - /** - * Call on a stream context to indicate that the request metadata has arrived. - */ - virtual ProxyAction onRequestMetadata(); - - /** - * Call on a stream context to indicate that the request trailers have arrived. - */ - virtual ProxyAction onResponseHeaders(); - - /** - * Call on a stream context to indicate that body data has arrived. - * @param body_buffer_length the amount of data in the body buffer. - * @param end_of_stream is true if no more body data will be arriving. - */ - virtual ProxyAction onResponseBody(uint32_t body_buffer_length, bool end_of_stream); - - /** - * Call on a stream context to indicate that the request trailers have arrived. - */ - virtual ProxyAction onResponseTrailers(); - - /** - * Call on a stream context to indicate that the request metadata has arrived. + * HTTP - see http_interface.h */ - virtual ProxyAction onResponseMetadata(); + ProxyAction onRequestHeaders() override; + ProxyAction onRequestBody(uint32_t body_buffer_length, bool end_of_stream) override; + ProxyAction onRequestTrailers() override; + ProxyAction onRequestMetadata() override; + ProxyAction onResponseHeaders() override; + ProxyAction onResponseBody(uint32_t body_buffer_length, bool end_of_stream) override; + ProxyAction onResponseTrailers() override; + ProxyAction onResponseMetadata() override; // Root Context async events @@ -293,7 +204,7 @@ class ContextBase { /** * Call when a stream should log the final status of the stream. Occurs after onDone(). */ - virtual void onLog(); + void onLog() override; /** * Will be called on sever Wasm errors. Callees may report and handle the error (e.g. via an @@ -416,7 +327,7 @@ class ContextBase { virtual WasmResult grpcCall(string_view /* grpc_service */, string_view /* service_name */, string_view /* method_name */, string_view /* request */, const Pairs & /* initial_metadata */, - const optional & /* timeout */, + std::chrono::milliseconds & /* timeout */, uint32_t * /* token_ptr */) { unimplemented(); return WasmResult::Unimplemented; diff --git a/include/proxy-wasm/http_interface.h b/include/proxy-wasm/http_interface.h new file mode 100644 index 00000000..8e71b14b --- /dev/null +++ b/include/proxy-wasm/http_interface.h @@ -0,0 +1,101 @@ +// 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 "include/proxy-wasm/compat.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/proxy-wasm/proxy_action.h" + +namespace proxy_wasm { + +/** + * HttpInterface is the interface between the VM host and the VM for HTTP streams. + */ +class HttpInterface { +public: + /** + * Calls into the VM. + * These are implemented by the proxy-independent host code. They are virtual to support some + * types of testing. + */ + + /* + * HTTP + * Note: headers and trailers are obtained by the code in the VM via the XXXHeaderMapXXX set of + * functions. Body data is obtained by the code in the VM via calls implemented by the + * proxy-independent host code using the getBuffer() call. + */ + + /** + * Call on a stream context to indicate that the request headers have arrived. Calls onCreate(). + */ + virtual ProxyAction onRequestHeaders() = 0; + + /** + * Call on a stream context to indicate that body data has arrived. + * @param body_buffer_length the amount of data in the body buffer. + * @param end_of_stream is true if no more body data will be arriving. + */ + virtual ProxyAction onRequestBody(uint32_t body_buffer_length, bool end_of_stream) = 0; + + /** + * Call on a stream context to indicate that the request trailers have arrived. + */ + virtual ProxyAction onRequestTrailers() = 0; + + /** + * Call on a stream context to indicate that the request metadata has arrived. + */ + virtual ProxyAction onRequestMetadata() = 0; + + /** + * Call on a stream context to indicate that the request trailers have arrived. + */ + virtual ProxyAction onResponseHeaders() = 0; + + /** + * Call on a stream context to indicate that body data has arrived. + * @param body_buffer_length the amount of data in the body buffer. + * @param end_of_stream is true if no more body data will be arriving. + */ + virtual ProxyAction onResponseBody(uint32_t body_buffer_length, bool end_of_stream) = 0; + + /** + * Call on a stream context to indicate that the request trailers have arrived. + */ + virtual ProxyAction onResponseTrailers() = 0; + + /** + * Call on a stream context to indicate that the request metadata has arrived. + */ + virtual ProxyAction onResponseMetadata() = 0; + + /** + * Call when a stream should log the final status of the stream. Occurs after onDone(). + */ + virtual void onLog() = 0; +}; + +} // namespace proxy_wasm diff --git a/include/proxy-wasm/proxy_action.h b/include/proxy-wasm/proxy_action.h new file mode 100644 index 00000000..abd2aa7e --- /dev/null +++ b/include/proxy-wasm/proxy_action.h @@ -0,0 +1,27 @@ +// 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 + +namespace proxy_wasm { + +// TODO: use the SDK version when it is updated. +enum class ProxyAction : uint32_t { + Illegal = 0, + Continue = 1, + Pause = 2, +}; + +} // namespace proxy_wasm From 47106fc51487ec50e2ae6c34238e5e8aa627eb27 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Tue, 17 Mar 2020 17:26:41 +0000 Subject: [PATCH 09/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/network_interface.h | 95 ++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 include/proxy-wasm/network_interface.h diff --git a/include/proxy-wasm/network_interface.h b/include/proxy-wasm/network_interface.h new file mode 100644 index 00000000..12e086e0 --- /dev/null +++ b/include/proxy-wasm/network_interface.h @@ -0,0 +1,95 @@ +// 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 "include/proxy-wasm/compat.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/proxy-wasm/proxy_action.h" + +namespace proxy_wasm { + +/** + * NetworkInterface is the interface between the VM host and the VM for network streams. + */ +class NetworkInterface { +public: + /** + * Network + * Note: Body data is obtained by the code in the VM via calls implemented by the + * proxy-independent host code using the getBuffer() call. + */ + + /** + * Call on a stream Context to indicate that a new network connection has been been created. + * Calls onStart(). + */ + virtual ProxyAction onNetworkNewConnection() = 0; + + /** + * Call on a stream Context to indicate that data has arrived from downstream (e.g. on the + * incoming port that was accepted and for which the proxy is acting as a server). + * @param data_length the amount of data in the buffer. + * @param end_of_stream is true if no more data will be arriving. + * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause + * proxying. + */ + virtual ProxyAction onDownstreamData(uint32_t data_length, bool end_of_stream) = 0; + + /** + * Call on a stream Context to indicate that data has arrived from upstream (e.g. on the outgoing + * port that the proxy connected and for which the proxy is acting as a client). + * @param data_length the amount of data in the buffer. + * @param end_of_stream is true if no more data will be arriving. + * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause + * proxying. + */ + virtual ProxyAction onUpstreamData(uint32_t data_length, bool end_of_stream) = 0; + + /* + * The source of the close event. + * Unknown is when the source is not known. + * Local is when the close was initiated by the proxy. + * Remote is when the close was received from the peer. + */ + enum class CloseType : uint32_t { + Unknown = 0, + Local = 1, + Remote = 2, + }; + + /** + * Call on a stream context to indicate that the downstream connection has closed. + * @close_type is the source of the close. + */ + virtual void onDownstreamConnectionClose(CloseType close_type) = 0; + + /** + * Call on a stream context to indicate that the upstream connection has closed. + * @close_type is the source of the close. + */ + virtual void onUpstreamConnectionClose(CloseType close_type) = 0; +}; + +} // namespace proxy_wasm From 313e675dff9ef63fd7d04f37d5124e6869ba8a77 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Tue, 17 Mar 2020 17:42:18 +0000 Subject: [PATCH 10/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index 4a91ee13..ce0dfd17 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -479,10 +479,12 @@ class ContextBase : public HttpInterface, NetworkInterface { * Get proxy-wide key-value data shared between VMs. * @param key is a proxy-wide key mapping to the shared data value. * @param cas is a number which will be incremented when a data value has been changed. - * @param data is a location to store the returned value. + * @param data is a location to store the returned stored 'value' and the corresponding 'cas' + * compare-and-swap value which can be used with setSharedData for safe concurrent updates. */ - virtual WasmResult getSharedData(string_view /* key */, - std::pair * /* data */); + virtual WasmResult + getSharedData(string_view /* key */, + std::pair * /* data */); /** * Set a key-value data shared between VMs. From e01f43a0625d497ad38bbfdd1c94cccd27fa4d9c Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Thu, 19 Mar 2020 22:11:34 +0000 Subject: [PATCH 11/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context.h | 27 ++--- ...etwork_interface.h => context_interface.h} | 70 +++++++++++- include/proxy-wasm/http_interface.h | 101 ------------------ include/proxy-wasm/proxy_action.h | 4 +- 4 files changed, 80 insertions(+), 122 deletions(-) rename include/proxy-wasm/{network_interface.h => context_interface.h} (60%) delete mode 100644 include/proxy-wasm/http_interface.h diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index ce0dfd17..01a05c81 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -26,8 +26,7 @@ #include #include -#include "include/proxy-wasm/http_interface.h" -#include "include/proxy-wasm/network_interface.h" +#include "include/proxy-wasm/context_interface.h" namespace proxy_wasm { @@ -150,24 +149,24 @@ class ContextBase : public HttpInterface, NetworkInterface { virtual void onCreate(uint32_t parent_context_id); /** - * Network - see network_interface.h + * Network - see NetworkInterface in context_interface.h */ ProxyAction onNetworkNewConnection() override; - ProxyAction onDownstreamData(uint32_t data_length, bool end_of_stream) override; - ProxyAction onUpstreamData(uint32_t data_length, bool end_of_stream) override; + ProxyAction onDownstreamData() override; + ProxyAction onUpstreamData() override; using CloseType = NetworkInterface::CloseType; void onDownstreamConnectionClose(CloseType close_type) override; void onUpstreamConnectionClose(CloseType close_type) override; /* - * HTTP - see http_interface.h + * HTTP - see HttpInterface in context_interface.h */ ProxyAction onRequestHeaders() override; - ProxyAction onRequestBody(uint32_t body_buffer_length, bool end_of_stream) override; + ProxyAction onRequestBody() override; ProxyAction onRequestTrailers() override; ProxyAction onRequestMetadata() override; ProxyAction onResponseHeaders() override; - ProxyAction onResponseBody(uint32_t body_buffer_length, bool end_of_stream) override; + ProxyAction onResponseBody() override; ProxyAction onResponseTrailers() override; ProxyAction onResponseMetadata() override; @@ -176,12 +175,8 @@ class ContextBase : public HttpInterface, NetworkInterface { /** * Called on a Root Context when a response arrives for an outstanding httpCall(). * @param token is the token returned by the corresponding httpCall(). - * @param headers are the number of headers in the response. - * @param body_size is the size in bytes of the response body. - * @param trailers is the number of trailers in the response. */ - virtual void onHttpCallResponse(uint32_t token, uint32_t headers, uint32_t body_size, - uint32_t trailers); + virtual void onHttpCallResponse(uint32_t token); /** * Called on a Root Context to indicate that an Inter-VM shared queue message has arrived. @@ -201,10 +196,10 @@ class ContextBase : public HttpInterface, NetworkInterface { */ virtual bool onDone(); - /** - * Call when a stream should log the final status of the stream. Occurs after onDone(). + /* + * Any Stream see context_interface.hh */ - void onLog() override; + void onFinalize() override; /** * Will be called on sever Wasm errors. Callees may report and handle the error (e.g. via an diff --git a/include/proxy-wasm/network_interface.h b/include/proxy-wasm/context_interface.h similarity index 60% rename from include/proxy-wasm/network_interface.h rename to include/proxy-wasm/context_interface.h index 12e086e0..43a31649 100644 --- a/include/proxy-wasm/network_interface.h +++ b/include/proxy-wasm/context_interface.h @@ -30,6 +30,70 @@ namespace proxy_wasm { +/** + * HttpInterface is the interface between the VM host and the VM for HTTP streams. + */ +class HttpInterface { +public: + /** + * Calls into the VM. + * These are implemented by the proxy-independent host code. They are virtual to support some + * types of testing. + */ + + /* + * HTTP + * Note: headers and trailers are obtained by the code in the VM via the XXXHeaderMapXXX set of + * functions. Body data is obtained by the code in the VM via calls implemented by the + * proxy-independent host code using the getBuffer() call. + */ + + /** + * Call on a stream context to indicate that the request headers have arrived. Calls onCreate(). + */ + virtual ProxyAction onRequestHeaders() = 0; + + /** + * Call on a stream context to indicate that body data has arrived. + */ + virtual ProxyAction onRequestBody() = 0; + + /** + * Call on a stream context to indicate that the request trailers have arrived. + */ + virtual ProxyAction onRequestTrailers() = 0; + + /** + * Call on a stream context to indicate that the request metadata has arrived. + */ + virtual ProxyAction onRequestMetadata() = 0; + + /** + * Call on a stream context to indicate that the request trailers have arrived. + */ + virtual ProxyAction onResponseHeaders() = 0; + + /** + * Call on a stream context to indicate that body data has arrived. + */ + virtual ProxyAction onResponseBody() = 0; + + /** + * Call on a stream context to indicate that the request trailers have arrived. + */ + virtual ProxyAction onResponseTrailers() = 0; + + /** + * Call on a stream context to indicate that the request metadata has arrived. + */ + virtual ProxyAction onResponseMetadata() = 0; + + /** + * Call when the final status of the stream is available e.g. for logging. Occurs after onDone(). + */ + virtual void onFinalize() = 0; +}; + /** * NetworkInterface is the interface between the VM host and the VM for network streams. */ @@ -50,12 +114,10 @@ class NetworkInterface { /** * Call on a stream Context to indicate that data has arrived from downstream (e.g. on the * incoming port that was accepted and for which the proxy is acting as a server). - * @param data_length the amount of data in the buffer. - * @param end_of_stream is true if no more data will be arriving. * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause * proxying. */ - virtual ProxyAction onDownstreamData(uint32_t data_length, bool end_of_stream) = 0; + virtual ProxyAction onDownstreamData() = 0; /** * Call on a stream Context to indicate that data has arrived from upstream (e.g. on the outgoing @@ -65,7 +127,7 @@ class NetworkInterface { * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause * proxying. */ - virtual ProxyAction onUpstreamData(uint32_t data_length, bool end_of_stream) = 0; + virtual ProxyAction onUpstreamData() = 0; /* * The source of the close event. diff --git a/include/proxy-wasm/http_interface.h b/include/proxy-wasm/http_interface.h deleted file mode 100644 index 8e71b14b..00000000 --- a/include/proxy-wasm/http_interface.h +++ /dev/null @@ -1,101 +0,0 @@ -// 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 "include/proxy-wasm/compat.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "include/proxy-wasm/proxy_action.h" - -namespace proxy_wasm { - -/** - * HttpInterface is the interface between the VM host and the VM for HTTP streams. - */ -class HttpInterface { -public: - /** - * Calls into the VM. - * These are implemented by the proxy-independent host code. They are virtual to support some - * types of testing. - */ - - /* - * HTTP - * Note: headers and trailers are obtained by the code in the VM via the XXXHeaderMapXXX set of - * functions. Body data is obtained by the code in the VM via calls implemented by the - * proxy-independent host code using the getBuffer() call. - */ - - /** - * Call on a stream context to indicate that the request headers have arrived. Calls onCreate(). - */ - virtual ProxyAction onRequestHeaders() = 0; - - /** - * Call on a stream context to indicate that body data has arrived. - * @param body_buffer_length the amount of data in the body buffer. - * @param end_of_stream is true if no more body data will be arriving. - */ - virtual ProxyAction onRequestBody(uint32_t body_buffer_length, bool end_of_stream) = 0; - - /** - * Call on a stream context to indicate that the request trailers have arrived. - */ - virtual ProxyAction onRequestTrailers() = 0; - - /** - * Call on a stream context to indicate that the request metadata has arrived. - */ - virtual ProxyAction onRequestMetadata() = 0; - - /** - * Call on a stream context to indicate that the request trailers have arrived. - */ - virtual ProxyAction onResponseHeaders() = 0; - - /** - * Call on a stream context to indicate that body data has arrived. - * @param body_buffer_length the amount of data in the body buffer. - * @param end_of_stream is true if no more body data will be arriving. - */ - virtual ProxyAction onResponseBody(uint32_t body_buffer_length, bool end_of_stream) = 0; - - /** - * Call on a stream context to indicate that the request trailers have arrived. - */ - virtual ProxyAction onResponseTrailers() = 0; - - /** - * Call on a stream context to indicate that the request metadata has arrived. - */ - virtual ProxyAction onResponseMetadata() = 0; - - /** - * Call when a stream should log the final status of the stream. Occurs after onDone(). - */ - virtual void onLog() = 0; -}; - -} // namespace proxy_wasm diff --git a/include/proxy-wasm/proxy_action.h b/include/proxy-wasm/proxy_action.h index abd2aa7e..51d6df20 100644 --- a/include/proxy-wasm/proxy_action.h +++ b/include/proxy-wasm/proxy_action.h @@ -17,7 +17,9 @@ namespace proxy_wasm { -// TODO: use the SDK version when it is updated. +// TODO: use the SDK version when it is updated. This is a placeholder. When the spec review +// completes the SDK will be updated with the final version and we will use that instead of this +// file. enum class ProxyAction : uint32_t { Illegal = 0, Continue = 1, From 5bde54226dfe8f60fb9f051ce992c1b85fda89b9 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Tue, 24 Mar 2020 22:12:03 +0000 Subject: [PATCH 12/19] Checkpoint. Signed-off-by: John Plevyak --- include/proxy-wasm/context.h | 259 ++++----------------- include/proxy-wasm/context_interface.h | 302 ++++++++++++++++++++++--- 2 files changed, 320 insertions(+), 241 deletions(-) diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index 01a05c81..fc562b1e 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -30,38 +30,8 @@ namespace proxy_wasm { -#include "proxy_wasm_common.h" -#include "proxy_wasm_enums.h" - -class WasmBase; class WasmVm; -using Pairs = std::vector>; -using PairsWithStringValues = std::vector>; -using CallOnThreadFunction = std::function)>; - -/** - * BufferInterface provides a interface between proxy-specific buffers and the proxy-independent ABI - * implementation. Embedders should subclass BufferInterface to enable the proxy-independent code to - * implement ABI calls which use buffers (e.g. the HTTP body). - */ -struct BufferInterface { - virtual ~BufferInterface() {} - virtual size_t size() const = 0; - /** - * Copy bytes from the buffer into the Wasm VM corresponding to 'wasm'. - * @param start is the first buffer byte to copy. - * @param length is the length of sequence of buffer bytes to copy. - * @param ptr_ptr is the location in the VM address space to place the address of the newly - * allocated memory block which contains the copied bytes. - * @param size_ptr is the location in the VM address space to place the size of the newly - * allocated memory block which contains the copied bytes (i.e. length). - * @return a WasmResult with any error or WasmResult::Ok. - */ - virtual WasmResult copyTo(WasmBase *wasm, size_t start, size_t length, uint64_t ptr_ptr, - uint64_t size_ptr) const = 0; -}; - /** * PluginBase is container to hold plugin information which is shared with all Context(s) created * for a given plugin. Embedders may extend this class with additional host-specific plugin @@ -104,7 +74,7 @@ struct PluginBase { * * 3) For testing and instrumentation the methods of ContextBase can be replaces or augmented. */ -class ContextBase : public HttpInterface, NetworkInterface { +class ContextBase : public ContextInterface { public: ContextBase(); // Testing. ContextBase(WasmBase *wasm); // Vm Context. @@ -130,37 +100,25 @@ class ContextBase : public HttpInterface, NetworkInterface { * types of testing. */ - // Root Context - - /** - * Call on a Root Context when a plugin is configured or reconfigured dynamically. - * @param plugin is the plugin which is being configured or reconfigured. - */ - virtual bool onConfigure(std::shared_ptr plugin); - // Context + void onCreate(uint32_t parent_context_id) override; + bool onDone() override; + void onDelete() override; + + // Root + bool onStart(std::shared_ptr plugin) override; + bool onConfigure(std::shared_ptr plugin) override; + void onHttpCallResponse(HttpCallToken token) override; + void onQueueReady(uint32_t SharedQueueDequeueToken) override; + void onGrpcReceiveInitialMetadata(GrpcToken token) override; + void onGrpcReceive(GrpcToken token) override; + void onGrpcReceiveTrailingMetadata(GrpcToken token) override; + void onGrpcClose(GrpcToken token, const GrpcStatus &status, const string_view message) override; + + // Stream (e.g. HTTP, Network) + void onFinalized() override; - /** - * Call on a host Context to create a corresponding Context in the VM. Note: - * onNetworkNewConnection and onRequestHeaders() call onCreate(). - * @param parent_context_id is the parent Context id for the context being created. For a Network - * stream Context, this will be a Root Context id. - */ - virtual void onCreate(uint32_t parent_context_id); - - /** - * Network - see NetworkInterface in context_interface.h - */ - ProxyAction onNetworkNewConnection() override; - ProxyAction onDownstreamData() override; - ProxyAction onUpstreamData() override; - using CloseType = NetworkInterface::CloseType; - void onDownstreamConnectionClose(CloseType close_type) override; - void onUpstreamConnectionClose(CloseType close_type) override; - - /* - * HTTP - see HttpInterface in context_interface.h - */ + // HTTP ProxyAction onRequestHeaders() override; ProxyAction onRequestBody() override; ProxyAction onRequestTrailers() override; @@ -170,36 +128,13 @@ class ContextBase : public HttpInterface, NetworkInterface { ProxyAction onResponseTrailers() override; ProxyAction onResponseMetadata() override; - // Root Context async events - - /** - * Called on a Root Context when a response arrives for an outstanding httpCall(). - * @param token is the token returned by the corresponding httpCall(). - */ - virtual void onHttpCallResponse(uint32_t token); - - /** - * Called on a Root Context to indicate that an Inter-VM shared queue message has arrived. - * @token is the token returned by registerSharedQueue(). - */ - virtual void onQueueReady(uint32_t token); - - // Context - - /** - * Call when a stream has completed (both sides have closed) or on a Root Context when the VM is - * shutting down. - * @return true for stream contexts or for Root Context(s) if the VM can shutdown, false for Root - * Context(s) if the VM should wait until the Root Context calls the proxy_done() ABI call. Note: - * the VM may (optionally) shutdown after some configured timeout even if the Root Context does - * not call proxy_done(). - */ - virtual bool onDone(); - - /* - * Any Stream see context_interface.hh - */ - void onFinalize() override; + // Network + ProxyAction onNetworkNewConnection() override; + ProxyAction onDownstreamData() override; + ProxyAction onUpstreamData() override; + using CloseType = NetworkInterface::CloseType; + void onDownstreamConnectionClose(CloseType close_type) override; + void onUpstreamConnectionClose(CloseType close_type) override; /** * Will be called on sever Wasm errors. Callees may report and handle the error (e.g. via an @@ -287,133 +222,55 @@ class ContextBase : public HttpInterface, NetworkInterface { } // HTTP - - /** - * Make an outgoing HTTP request. - * @param target specifies the proxy-specific target of the call (e.g. a cluster, peer, or host). - * @param request_headers are the request headers. - * @param request_body is the request body. - * @param request_trailers are the request trailers. - * @param timeout_milliseconds is a timeout after which the request will be considered to have - * failed. - * @param token_ptr contains a pointer to a location to store the token which will be used with - * the corresponding onHttpCallResponse. - */ - virtual WasmResult httpCall(string_view /* target */, const Pairs & /*request_headers */, - string_view /* request_body */, const Pairs & /* request_trailers */, - int /* timeout_milliseconds */, uint32_t * /* token_ptr */) { + WasmResult httpCall(string_view /* target */, const Pairs & /*request_headers */, + string_view /* request_body */, const Pairs & /* request_trailers */, + int /* timeout_milliseconds */, HttpCallToken * /* token_ptr */) override { unimplemented(); return WasmResult::Unimplemented; } // gRPC - - /** - * Make a gRPC call. - * @param grpc_service is proxy-specific metadata describing the service (e.g. security certs). - * @param service_name the name of the gRPC service. - * @param method_name the gRPC method name. - * @param request the serialized request. - * @param initial_metadata the initial metadata. - * @param timeout a timeout in milliseconds. - * @param token_ptr contains a pointer to a location to store the token which will be used with - * the corresponding onGrpc and grpc calls. - */ - virtual WasmResult grpcCall(string_view /* grpc_service */, string_view /* service_name */, - string_view /* method_name */, string_view /* request */, - const Pairs & /* initial_metadata */, - std::chrono::milliseconds & /* timeout */, - uint32_t * /* token_ptr */) { + WasmResult grpcCall(string_view, string_view /* service_name */, string_view /* method_name */, + string_view /* request */, const Pairs & /* initial_metadata */, + std::chrono::milliseconds & /* timeout */, + GrpcToken * /* token_ptr */) override { unimplemented(); return WasmResult::Unimplemented; } - - /** - * Open a gRPC stream. - * @param grpc_service is proxy-specific metadata describing the service (e.g. security certs). - * @param service_name the name of the gRPC service. - * @param method_name the gRPC method name. - * @param token_ptr contains a pointer to a location to store the token which will be used with - * the corresponding onGrpc and grpc calls. - */ - virtual WasmResult grpcStream(string_view /* grpc_service */, string_view /* service_name */, - string_view /* method_name */, uint32_t * /* token_ptr */) { + WasmResult grpcStream(string_view /* grpc_service */, string_view /* service_name */, + string_view /* method_name */, GrpcToken * /* token_ptr */) override { unimplemented(); return WasmResult::Unimplemented; } - - /** - * Close a gRPC stream. In flight data may still result in calls into the VM. - * @param token is a token returned from grpcStream. - */ - virtual WasmResult grpcClose(uint32_t /* token */) { // cancel on call, close on stream. + WasmResult grpcClose(GrpcToken /* token */) override { unimplemented(); return WasmResult::Unimplemented; } - - /** - * Cancel a gRPC stream or call. No more calls will occur. - * @param token is a token returned from grpcSream or grpcCall. - */ - virtual WasmResult grpcCancel(uint32_t /* token */) { // cancel on call, reset on stream. + WasmResult grpcCancel(GrpcToken /* token */) override { unimplemented(); return WasmResult::Unimplemented; } - - /** - * Close a gRPC stream. In flight data may still result in calls into the VM. - * @param token is a token returned from grpcSream. - * @param message is a (serialized) message to be sent. - * @param end_stream indicates that the stream is now end_of_stream (e.g. WriteLast() or - * WritesDone). - */ - virtual WasmResult grpcSend(uint32_t /* token */, string_view /* message */, - bool /* end_stream */) { // stream only + WasmResult grpcSend(GrpcToken /* token */, string_view /* message */, + bool /* end_stream */) override { // stream only unimplemented(); return WasmResult::Unimplemented; } // Metrics - - /** - * Define a metric (Stat). - * @param type is the type of metric (e.g. Counter). - * @param name is a string uniquely identifying the metric. - * @param metric_id_ptr is a location to store a token used for subsequent operations on the - * metric. - */ - virtual WasmResult defineMetric(MetricType /* type */, string_view /* name */, - uint32_t * /* metric_id_ptr */) { + WasmResult defineMetric(MetricType /* type */, string_view /* name */, + uint32_t * /* metric_id_ptr */) override { unimplemented(); return WasmResult::Unimplemented; } - - /** - * Increment a metric. - * @param metric_id is a token returned by defineMetric() identifying the metric to operate on. - * @param offset is the offset to apply to the Counter. - */ - virtual WasmResult incrementMetric(uint32_t /* metric_id */, int64_t /* offset */) { + WasmResult incrementMetric(uint32_t /* metric_id */, int64_t /* offset */) override { unimplemented(); return WasmResult::Unimplemented; } - - /** - * Record a metric. - * @param metric_id is a token returned by defineMetric() identifying the metric to operate on. - * @param value is the value to store for a Gauge or increment for a histogram or Counter. - */ - virtual WasmResult recordMetric(uint32_t /* metric_id */, uint64_t /* value */) { + WasmResult recordMetric(uint32_t /* metric_id */, uint64_t /* value */) override { unimplemented(); return WasmResult::Unimplemented; } - - /** - * Get the current value of a metric. - * @param metric_id is a token returned by defineMetric() identifying the metric to operate on. - * @param value_ptr is a location to store the value of the metric. - */ - virtual WasmResult getMetric(uint32_t /* metric_id */, uint64_t * /* value_ptr */) { + WasmResult getMetric(uint32_t /* metric_id */, uint64_t * /* value_ptr */) override { unimplemented(); return WasmResult::Unimplemented; } @@ -499,7 +356,8 @@ class ContextBase : public HttpInterface, NetworkInterface { * to make a unique identifier for the queue. * @param token_ptr a location to store a token corresponding to the queue. */ - virtual WasmResult registerSharedQueue(string_view /* queue_name */, uint32_t *token_ptr); + virtual WasmResult registerSharedQueue(string_view /* queue_name */, + SharedQueueDequeueToken *token_ptr); /** * Get the token for a queue. @@ -508,6 +366,7 @@ class ContextBase : public HttpInterface, NetworkInterface { * to make a unique identifier for the queue. * @param token_ptr a location to store a token corresponding to the queue. */ + using SharedQueueEnqueueToken = uint32_t; virtual WasmResult resolveSharedQueue(string_view /* vm_id */, string_view /* queue_name */, uint32_t * /* token_ptr */); @@ -516,14 +375,16 @@ class ContextBase : public HttpInterface, NetworkInterface { * @param token is a token returned by registerSharedQueue(); * @param data_ptr is a location to store the data dequeued. */ - virtual WasmResult dequeueSharedQueue(uint32_t /* token */, std::string * /* data_ptr */); + virtual WasmResult dequeueSharedQueue(SharedQueueDequeueToken /* token */, + std::string * /* data_ptr */); /** * Enqueue a message on a shared queue. * @param token is a token returned by resolveSharedQueue(); * @param data is the data to be queued. */ - virtual WasmResult enqueueSharedQueue(uint32_t /* token */, string_view /* value */); + virtual WasmResult enqueueSharedQueue(SharedQueueEnqueueToken /* token */, + string_view /* data */); // Header/Trailer/Metadata Maps @@ -606,26 +467,6 @@ class ContextBase : public HttpInterface, NetworkInterface { protected: friend class WasmBase; - /** - * Calls into the VM. - * These are implemented and called by the proxy-independent host code. They are virtual to - * support some types of testing. - */ - - /** - * Call on a Root Context when a VM first starts up. - * @param plugin is the plugin which caused the VM to be started. - * Called by the host code. - */ - bool onStart(std::shared_ptr plugin); - - /** - * Call when no further stream calls will occur. This will cause the corresponding Context in the - * VM to be deleted. - * Called by the host code. - */ - virtual void onDelete(); - virtual void initializeRoot(WasmBase *wasm, std::shared_ptr plugin); std::string makeRootLogPrefix(string_view vm_id) const; diff --git a/include/proxy-wasm/context_interface.h b/include/proxy-wasm/context_interface.h index 43a31649..2b5001ed 100644 --- a/include/proxy-wasm/context_interface.h +++ b/include/proxy-wasm/context_interface.h @@ -30,74 +30,183 @@ namespace proxy_wasm { +#include "proxy_wasm_common.h" +#include "proxy_wasm_enums.h" + +using Pairs = std::vector>; +using PairsWithStringValues = std::vector>; +using HttpCallToken = uint32_t; +using GrpcToken = uint32_t; + +struct PluginBase; +class WasmBase; + /** - * HttpInterface is the interface between the VM host and the VM for HTTP streams. + * BufferInterface provides a interface between proxy-specific buffers and the proxy-independent ABI + * implementation. Embedders should subclass BufferInterface to enable the proxy-independent code to + * implement ABI calls which use buffers (e.g. the HTTP body). */ -class HttpInterface { -public: +struct BufferInterface { + virtual ~BufferInterface() {} + virtual size_t size() const = 0; /** - * Calls into the VM. - * These are implemented by the proxy-independent host code. They are virtual to support some - * types of testing. + * Copy bytes from the buffer into the Wasm VM corresponding to 'wasm'. + * @param start is the first buffer byte to copy. + * @param length is the length of sequence of buffer bytes to copy. + * @param ptr_ptr is the location in the VM address space to place the address of the newly + * allocated memory block which contains the copied bytes. + * @param size_ptr is the location in the VM address space to place the size of the newly + * allocated memory block which contains the copied bytes (i.e. length). + * @return a WasmResult with any error or WasmResult::Ok. */ + virtual WasmResult copyTo(WasmBase *wasm, size_t start, size_t length, uint64_t ptr_ptr, + uint64_t size_ptr) const = 0; +}; - /* - * HTTP - * Note: headers and trailers are obtained by the code in the VM via the XXXHeaderMapXXX set of - * functions. Body data is obtained by the code in the VM via calls implemented by the - * proxy-independent host code using the getBuffer() call. +/** + * RootGrpcInterface is the interface for gRPC events arriving at RootContext(s). + */ +struct RootGrpcInterface { + /** + * Called on Root Context to with the initial metadata of a grpcStream. + * @token is the token returned by grpcStream. + * @metadata is the metadata received. */ + virtual void onGrpcReceiveInitialMetadata(GrpcToken token) = 0; /** - * Call on a stream context to indicate that the request headers have arrived. Calls onCreate(). + * Called on Root Context when gRPC data has arrived. + * @token is the token returned by grpcCall or grpcStream. + * For Call this implies OK close. For Stream may be called repeatedly. */ - virtual ProxyAction onRequestHeaders() = 0; + virtual void onGrpcReceive(GrpcToken token) = 0; /** - * Call on a stream context to indicate that body data has arrived. + * Called on Root Context to with the initial metadata of a grpcStream. + * @token is the token returned by grpcStream. + * @metadata is the metadata received. */ - virtual ProxyAction onRequestBody() = 0; + virtual void onGrpcReceiveTrailingMetadata(GrpcToken token) = 0; /** - * Call on a stream context to indicate that the request trailers have arrived. + * Called on Root Context when a gRPC call has closed prematurely or a gRPC stream has closed. + * @token is the token returned by grpcStream. + * @status is status of the stream. + * @message is any status message. + * For Call only used when not Ok. For stream indicates the peer has closed. */ - virtual ProxyAction onRequestTrailers() = 0; + virtual void onGrpcClose(GrpcToken token, const GrpcStatus &status, + const string_view message) = 0; +}; +/** + * RootInterface is the interface specific to RootContexts. + * A RootContext is associated with one more more plugins and is the parent of all stream Context(s) + * created for that plugin. It can be used to store data shared between stream Context(s) in the + * same VM. + */ +struct RootInterface : public RootGrpcInterface { /** - * Call on a stream context to indicate that the request metadata has arrived. + * Call on a host Context to create a corresponding Context in the VM. Note: + * onNetworkNewConnection and onRequestHeaders() call onCreate(). + * @param parent_context_id is the parent Context id for the context being created. For a + * stream Context this will be a Root Context id (or sub-Context thereof). */ - virtual ProxyAction onRequestMetadata() = 0; + virtual void onCreate(uint32_t parent_context_id); /** - * Call on a stream context to indicate that the request trailers have arrived. + * Call on a Root Context when a VM first starts up. + * @param plugin is the plugin which caused the VM to be started. + * Called by the host code. */ - virtual ProxyAction onResponseHeaders() = 0; + virtual bool onStart(std::shared_ptr plugin) = 0; /** - * Call on a stream context to indicate that body data has arrived. + * Call on a Root Context when a plugin is configured or reconfigured dynamically. + * @param plugin is the plugin which is being configured or reconfigured. */ - virtual ProxyAction onResponseBody() = 0; + virtual bool onConfigure(std::shared_ptr plugin) = 0; /** - * Call on a stream context to indicate that the request trailers have arrived. + * Called on a Root Context when a response arrives for an outstanding httpCall(). + * @param token is the token returned by the corresponding httpCall(). */ - virtual ProxyAction onResponseTrailers() = 0; + virtual void onHttpCallResponse(HttpCallToken token) = 0; /** - * Call on a stream context to indicate that the request metadata has arrived. + * Called on a Root Context when an Inter-VM shared queue message has arrived. + * @token is the token returned by registerSharedQueue(). */ - virtual ProxyAction onResponseMetadata() = 0; + using SharedQueueDequeueToken = uint32_t; + virtual void onQueueReady(uint32_t SharedQueueDequeueToken) = 0; + + /** + * Call when a stream has completed (both sides have closed) or on a Root Context when the VM is + * shutting down. + * @return true for stream contexts or for Root Context(s) if the VM can shutdown, false for Root + * Context(s) if the VM should wait until the Root Context calls the proxy_done() ABI call. Note: + * the VM may (optionally) shutdown after some configured timeout even if the Root Context does + * not call proxy_done(). + */ + virtual bool onDone() = 0; /** - * Call when the final status of the stream is available e.g. for logging. Occurs after onDone(). + * Call when no further stream calls will occur. This will cause the corresponding Context in the + * VM to be deleted. + * Called by the host code. */ - virtual void onFinalize() = 0; + virtual void onDelete(); +}; + +/** + * HttpInterface is the interface between the VM host and the VM for HTTP streams. Note: headers and + * trailers are obtained by the code in the VM via the XXXHeaderMapXXX set of functions. Body data + * is obtained by the code in the VM via calls implemented by the proxy-independent host code using + * the getBuffer() call. + */ +struct HttpInterface { +public: + /** + * Call on a stream context to indicate that the request headers have arrived. Calls + * onCreate(). + */ + virtual ProxyAction onRequestHeaders() = 0; + + // Call on a stream context to indicate that body data has arrived. + virtual ProxyAction onRequestBody() = 0; + + // Call on a stream context to indicate that the request trailers have arrived. + virtual ProxyAction onRequestTrailers() = 0; + + // Call on a stream context to indicate that the request metadata has arrived. + virtual ProxyAction onRequestMetadata() = 0; + + // Call on a stream context to indicate that the request trailers have arrived. + virtual ProxyAction onResponseHeaders() = 0; + + // Call on a stream context to indicate that body data has arrived. + virtual ProxyAction onResponseBody() = 0; + + // Call on a stream context to indicate that the request trailers have arrived. + virtual ProxyAction onResponseTrailers() = 0; + + // Call on a stream context to indicate that the request metadata has arrived. + virtual ProxyAction onResponseMetadata() = 0; + + // Call when the stream closes. See RootInterface. + virtual bool onDone() = 0; + + // Call when the stream status has finalized, e.g. for logging. See RootInterface. + virtual void onFinalized() = 0; + + // Call just before the Context is deleted. See RootInterface. + virtual void onDelete() = 0; }; /** * NetworkInterface is the interface between the VM host and the VM for network streams. */ -class NetworkInterface { +struct NetworkInterface { public: /** * Network @@ -120,8 +229,8 @@ class NetworkInterface { virtual ProxyAction onDownstreamData() = 0; /** - * Call on a stream Context to indicate that data has arrived from upstream (e.g. on the outgoing - * port that the proxy connected and for which the proxy is acting as a client). + * Call on a stream Context to indicate that data has arrived from upstream (e.g. on the + * outgoing port that the proxy connected and for which the proxy is acting as a client). * @param data_length the amount of data in the buffer. * @param end_of_stream is true if no more data will be arriving. * @return indicates the subsequent behavior of this stream, e.g. continue proxying or pause @@ -152,6 +261,135 @@ class NetworkInterface { * @close_type is the source of the close. */ virtual void onUpstreamConnectionClose(CloseType close_type) = 0; + + // Call when the stream closes. See RootInterface. + virtual bool onDone() = 0; + + // Call when the stream status has finalized, e.g. for logging. See RootInterface. + virtual void onFinalized() = 0; +}; + +struct HttpCallInterface { + /** + * Make an outgoing HTTP request. + * @param target specifies the proxy-specific target of the call (e.g. a cluster, peer, or + * host). + * @param request_headers are the request headers. + * @param request_body is the request body. + * @param request_trailers are the request trailers. + * @param timeout_milliseconds is a timeout after which the request will be considered to have + * failed. + * @param token_ptr contains a pointer to a location to store the token which will be used with + * the corresponding onHttpCallResponse. + * Note: the response arrives on the ancestor RootContext as this call may outlive any stream. + * Plugin writers should use the VM SDK setEffectiveContext() to switch to any waiting streams. + */ + virtual WasmResult httpCall(string_view target, const Pairs &request_headers, + string_view request_body, const Pairs &request_trailers, + int timeout_milliseconds, HttpCallToken *token_ptr) = 0; +}; + +struct GrpcCallInterface { + /** + * Make a gRPC call. + * @param grpc_service is proxy-specific metadata describing the service (e.g. security certs). + * @param service_name the name of the gRPC service. + * @param method_name the gRPC method name. + * @param request the serialized request. + * @param initial_metadata the initial metadata. + * @param timeout a timeout in milliseconds. + * @param token_ptr contains a pointer to a location to store the token which will be used with + * the corresponding onGrpc and grpc calls. + */ + virtual WasmResult grpcCall(string_view /* grpc_service */, string_view /* service_name */, + string_view /* method_name */, string_view /* request */, + const Pairs & /* initial_metadata */, + std::chrono::milliseconds & /* timeout */, + GrpcToken * /* token_ptr */) = 0; + + /** + * Close a gRPC stream. In flight data may still result in calls into the VM. + * @param token is a token returned from grpcStream. + * For call the same as grpcCancel. For Stream, close the stream: outstanding peer messages may + * still arrive. + */ + virtual WasmResult grpcClose(GrpcToken /* token */) = 0; + + /** + * Cancel a gRPC stream or call. No more calls will occur. + * @param token is a token returned from grpcSream or grpcCall. + * For Call, cancel on call. For Strea, reset the stream: no further callbacks will arrive. + */ + virtual WasmResult grpcCancel(GrpcToken /* token */) = 0; +}; + +struct GrpcStreamInterface { + /** + * Open a gRPC stream. + * @param grpc_service is proxy-specific metadata describing the service (e.g. security certs). + * @param service_name the name of the gRPC service. + * @param method_name the gRPC method name. + * @param token_ptr contains a pointer to a location to store the token which will be used with + * the corresponding onGrpc and grpc calls. + */ + virtual WasmResult grpcStream(string_view grpc_service, string_view service_name, + string_view method_name, GrpcToken *token_ptr) = 0; + + /** + * Close a gRPC stream. In flight data may still result in calls into the VM. + * @param token is a token returned from grpcSream. + * @param message is a (serialized) message to be sent. + * @param end_stream indicates that the stream is now end_of_stream (e.g. WriteLast() or + * WritesDone). + */ + virtual WasmResult grpcSend(GrpcToken token, string_view message, bool end_stream) = 0; + + // See GrpcCallInterface. + virtual WasmResult grpcClose(GrpcToken token) = 0; + + // See GrpcCallInterface. + virtual WasmResult grpcCancel(GrpcToken token) = 0; +}; + +struct MetricsInterface { + /** + * Define a metric (Stat). + * @param type is the type of metric (e.g. Counter). + * @param name is a string uniquely identifying the metric. + * @param metric_id_ptr is a location to store a token used for subsequent operations on the + * metric. + */ + virtual WasmResult defineMetric(MetricType /* type */, string_view /* name */, + uint32_t * /* metric_id_ptr */) = 0; + + /** + * Increment a metric. + * @param metric_id is a token returned by defineMetric() identifying the metric to operate on. + * @param offset is the offset to apply to the Counter. + */ + virtual WasmResult incrementMetric(uint32_t /* metric_id */, int64_t /* offset */) = 0; + + /** + * Record a metric. + * @param metric_id is a token returned by defineMetric() identifying the metric to operate on. + * @param value is the value to store for a Gauge or increment for a histogram or Counter. + */ + virtual WasmResult recordMetric(uint32_t /* metric_id */, uint64_t /* value */) = 0; + + /** + * Get the current value of a metric. + * @param metric_id is a token returned by defineMetric() identifying the metric to operate on. + * @param value_ptr is a location to store the value of the metric. + */ + virtual WasmResult getMetric(uint32_t /* metric_id */, uint64_t * /* value_ptr */) = 0; }; +struct ContextInterface : RootInterface, + HttpInterface, + NetworkInterface, + HttpCallInterface, + GrpcCallInterface, + GrpcStreamInterface, + MetricsInterface {}; + } // namespace proxy_wasm From 1693953faba4006fe045be2a12706a3abdd7f39b Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Tue, 24 Mar 2020 23:28:41 +0000 Subject: [PATCH 13/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context.h | 351 ++++++------------------- include/proxy-wasm/context_interface.h | 230 +++++++++++++++- include/proxy-wasm/proxy_action.h | 29 -- 3 files changed, 311 insertions(+), 299 deletions(-) delete mode 100644 include/proxy-wasm/proxy_action.h diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index fc562b1e..5642f39b 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -117,6 +117,15 @@ class ContextBase : public ContextInterface { // Stream (e.g. HTTP, Network) void onFinalized() override; + const BufferInterface *getBuffer(WasmBufferType /* type */) override { + unimplemented(); + return nullptr; + } + bool end_of_stream(WasmStreamType /* type */) override { + unimplemented(); + return true; + } + void continueStream(WasmStreamType /* type */) override { unimplemented(); } // HTTP ProxyAction onRequestHeaders() override; @@ -127,6 +136,11 @@ class ContextBase : public ContextInterface { ProxyAction onResponseBody() override; ProxyAction onResponseTrailers() override; ProxyAction onResponseMetadata() override; + void sendLocalResponse(uint64_t /* response_code */, string_view /* body */, + Pairs /* additional_headers */, uint64_t /* grpc_status */, + string_view /* details */) override { + unimplemented(); + } // Network ProxyAction onNetworkNewConnection() override; @@ -136,55 +150,28 @@ class ContextBase : public ContextInterface { void onDownstreamConnectionClose(CloseType close_type) override; void onUpstreamConnectionClose(CloseType close_type) override; - /** - * Will be called on sever Wasm errors. Callees may report and handle the error (e.g. via an - * Exception) to prevent the proxy from crashing. - */ - virtual void error(string_view message) { + // General + void error(string_view message) override { std::cerr << message << "\n"; abort(); } - - /** - * Called by all functions which are not overridden with a proxy-specific implementation. - */ - virtual void unimplemented() { error("unimplemented proxy-wasm API"); } - - /** - * Calls from the VM> - * This collection represents all the calls into the VM in the ABI - * (https://github.com/proxy-wasm/spec). They are not broken into separate interfaces because - * doing so would result in duplication since calls into the VM must be overriden by the - * implementations in the ContextBase. - * - * Note: most of these return a WasmResult, assume: - * @return a WasmResult with the status of the call. - */ - - /** - * Log a message. Note: log_prefix() is *not* auto-prepended end may be useful to provide some - * context. - */ - virtual WasmResult log(uint64_t /* level */, string_view /* message */) { - unimplemented(); + WasmResult unimplemented() override { + error("unimplemented proxy-wasm API"); return WasmResult::Unimplemented; } - - /** - * Enables a periodic timer with the given period or sets the period of an existing timer. Note: - * the timer is associated with the Root Context of whatever Context this call was made on and - * there is only one timer available per Root Context. - * @param period is the period of the periodic timer in milliseconds. - */ - virtual WasmResult setTimerPeriod(std::chrono::milliseconds /* period */) { - unimplemented(); - return WasmResult::Unimplemented; + WasmResult log(uint64_t level, string_view message) override { + if (level >= static_cast(LogLevel::error)) { + std::cerr << log_prefix() << message << "\n"; + } else { + std::cout << log_prefix() << message << "\n"; + } + return WasmResult::Ok; } - - /** - * Provides the current time in nanoseconds. - */ - virtual uint64_t getCurrentTimeNanoseconds() { + virtual WasmResult setTimerPeriod(std::chrono::milliseconds /* period */, + uint32_t * /* timer_token_ptr */) override { + return unimplemented(); + } + uint64_t getCurrentTimeNanoseconds() override { struct timespec tpe; clock_gettime(CLOCK_REALTIME, &tpe); uint64_t t = tpe.tv_sec; @@ -192,41 +179,22 @@ class ContextBase : public ContextInterface { t += tpe.tv_nsec; return t; } - - /** - * Provides the status of the last call into the VM or out of the VM, similar to errno. - * @return the status code and a descriptive string. - */ - virtual std::pair getStatus() { + std::pair getStatus() override { unimplemented(); return std::make_pair(1, "unimplemented"); } - - // Buffer - - /** - * Provides a BufferInterface to be used to return buffered data to the VM. - * @param type is the type of buffer to provide. - */ - virtual const BufferInterface *getBuffer(WasmBufferType /* type */) { - unimplemented(); - return nullptr; + WasmResult getProperty(string_view /* path */, std::string * /* result */) override { + return unimplemented(); } - - /** - * Provides the end-of-stream status of the current stream (if any) or false. - */ - virtual bool end_of_stream() { - unimplemented(); - return true; + WasmResult setProperty(string_view /* key */, string_view /* value */) override { + return unimplemented(); } // HTTP WasmResult httpCall(string_view /* target */, const Pairs & /*request_headers */, string_view /* request_body */, const Pairs & /* request_trailers */, int /* timeout_milliseconds */, HttpCallToken * /* token_ptr */) override { - unimplemented(); - return WasmResult::Unimplemented; + return unimplemented(); } // gRPC @@ -234,234 +202,87 @@ class ContextBase : public ContextInterface { string_view /* request */, const Pairs & /* initial_metadata */, std::chrono::milliseconds & /* timeout */, GrpcToken * /* token_ptr */) override { - unimplemented(); - return WasmResult::Unimplemented; + return unimplemented(); } WasmResult grpcStream(string_view /* grpc_service */, string_view /* service_name */, string_view /* method_name */, GrpcToken * /* token_ptr */) override { - unimplemented(); - return WasmResult::Unimplemented; - } - WasmResult grpcClose(GrpcToken /* token */) override { - unimplemented(); - return WasmResult::Unimplemented; - } - WasmResult grpcCancel(GrpcToken /* token */) override { - unimplemented(); - return WasmResult::Unimplemented; + return unimplemented(); } + WasmResult grpcClose(GrpcToken /* token */) override { return unimplemented(); } + WasmResult grpcCancel(GrpcToken /* token */) override { return unimplemented(); } WasmResult grpcSend(GrpcToken /* token */, string_view /* message */, bool /* end_stream */) override { // stream only - unimplemented(); - return WasmResult::Unimplemented; + return unimplemented(); } // Metrics WasmResult defineMetric(MetricType /* type */, string_view /* name */, uint32_t * /* metric_id_ptr */) override { - unimplemented(); - return WasmResult::Unimplemented; + return unimplemented(); } WasmResult incrementMetric(uint32_t /* metric_id */, int64_t /* offset */) override { - unimplemented(); - return WasmResult::Unimplemented; + return unimplemented(); } WasmResult recordMetric(uint32_t /* metric_id */, uint64_t /* value */) override { - unimplemented(); - return WasmResult::Unimplemented; + return unimplemented(); } WasmResult getMetric(uint32_t /* metric_id */, uint64_t * /* value_ptr */) override { - unimplemented(); - return WasmResult::Unimplemented; - } - - // Properties - - /** - * Get the value of a property. Some properties are proxy-independent (e.g. ["plugin_root_id"]) - * while others can be proxy-specific. - * @param path is a sequence of strings describing a path to a property. - * @param result is a location to write the value of the property. - */ - virtual WasmResult getProperty(string_view /* path */, std::string * /* result */) { - unimplemented(); - return WasmResult::Unimplemented; - } - - /** - * Set the value of a property. - * @param path is a sequence of strings describing a path to a property. - * @param value the value to set. For non-string, non-integral types, the value may be - * serialized.. - */ - virtual WasmResult setProperty(string_view /* key */, string_view /* value */) { - unimplemented(); - return WasmResult::Unimplemented; - } - - // Continue - - /** - * Continue processing a request e.g. after returning ProxyAction::Pause. - */ - virtual void continueRequest() { unimplemented(); } - - /** - * Continue processing a response e.g. after returning ProxyAction::Pause. - */ - virtual void continueResponse() { unimplemented(); } - - /** - * Respond directly to an HTTP request. - * @param response_code is the response code to send. - * @param body is the body of the response. - * @param additional_headers are additional headers to send in the response. - * @param grpc_status is an optional gRPC status if the connection is a gRPC connection. - * @param details are details of any (gRPC) error. - */ - virtual void sendLocalResponse(uint64_t /* response_code */, string_view /* body */, - Pairs /* additional_headers */, uint64_t /* grpc_status */, - string_view /* details */) { - unimplemented(); + return unimplemented(); } // Shared Data - - /** - * Get proxy-wide key-value data shared between VMs. - * @param key is a proxy-wide key mapping to the shared data value. - * @param cas is a number which will be incremented when a data value has been changed. - * @param data is a location to store the returned stored 'value' and the corresponding 'cas' - * compare-and-swap value which can be used with setSharedData for safe concurrent updates. - */ - virtual WasmResult + WasmResult getSharedData(string_view /* key */, - std::pair * /* data */); - - /** - * Set a key-value data shared between VMs. - * @param key is a proxy-wide key mapping to the shared data value. - * @param cas is a compare-and-swap value. If it is zero it is ignored, otherwise it must match - * the cas associated with the value. - * @param data is a location to store the returned value. - */ - virtual WasmResult setSharedData(string_view /* key */, string_view /* value */, - uint32_t /* cas */); + std::pair * /* data */) override { + return unimplemented(); + } + WasmResult setSharedData(string_view /* key */, string_view /* value */, + uint32_t /* cas */) override { + return unimplemented(); + } // Shared Queue - - /** - * Register a proxy-wide queue. - * @param queue_name is a name for the queue. The queue_name is combined with the vm_id (if any) - * to make a unique identifier for the queue. - * @param token_ptr a location to store a token corresponding to the queue. - */ - virtual WasmResult registerSharedQueue(string_view /* queue_name */, - SharedQueueDequeueToken *token_ptr); - - /** - * Get the token for a queue. - * @param vm_id is the vm_id of the Plugin of the Root Context which registered the queue. - * @param queue_name is a name for the queue. The queue_name is combined with the vm_id (if any) - * to make a unique identifier for the queue. - * @param token_ptr a location to store a token corresponding to the queue. - */ - using SharedQueueEnqueueToken = uint32_t; - virtual WasmResult resolveSharedQueue(string_view /* vm_id */, string_view /* queue_name */, - uint32_t * /* token_ptr */); - - /** - * Dequeue a message from a shared queue. - * @param token is a token returned by registerSharedQueue(); - * @param data_ptr is a location to store the data dequeued. - */ - virtual WasmResult dequeueSharedQueue(SharedQueueDequeueToken /* token */, - std::string * /* data_ptr */); - - /** - * Enqueue a message on a shared queue. - * @param token is a token returned by resolveSharedQueue(); - * @param data is the data to be queued. - */ - virtual WasmResult enqueueSharedQueue(SharedQueueEnqueueToken /* token */, - string_view /* data */); + WasmResult registerSharedQueue(string_view /* queue_name */, + SharedQueueDequeueToken *token_ptr) override { + return unimplemented(); + } + WasmResult resolveSharedQueue(string_view /* vm_id */, string_view /* queue_name */, + uint32_t * /* token_ptr */) override { + return unimplemented(); + } + WasmResult dequeueSharedQueue(SharedQueueDequeueToken /* token */, + std::string * /* data_ptr */) override { + return unimplemented(); + } + WasmResult enqueueSharedQueue(SharedQueueEnqueueToken /* token */, + string_view /* data */) override { + return unimplemented(); + } // Header/Trailer/Metadata Maps - - /** - * Add a key-value pair to a header map. - * @param type of the header map. - * @param key is the key (header). - * @param value is the value (header value). - */ - virtual WasmResult addHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, - string_view /* value */) { - unimplemented(); - return WasmResult::Unimplemented; + WasmResult addHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, + string_view /* value */) override { + return unimplemented(); } - - /** - * Get a value from to a header map. - * @param type of the header map. - * @param key is the key (header). - * @param result is a pointer to the returned header value. - */ - virtual WasmResult getHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, - string_view *result) { - unimplemented(); - return WasmResult::Unimplemented; + WasmResult getHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, + string_view *result) override { + return unimplemented(); } - - /** - * Get all the key-value pairs in a header map. - * @param type of the header map. - * @param result is a pointer to the pairs. - */ - virtual WasmResult getHeaderMapPairs(WasmHeaderMapType /* type */, Pairs * /* result */) { - unimplemented(); - return WasmResult::Unimplemented; + WasmResult getHeaderMapPairs(WasmHeaderMapType /* type */, Pairs * /* result */) override { + return unimplemented(); } - - /** - * Set a header map so that it contains the given pairs (does not merge with existing data). - * @param type of the header map. - * @param the pairs to set the header map to. - */ - virtual WasmResult setHeaderMapPairs(WasmHeaderMapType /* type */, const Pairs & /* pairs */) { - unimplemented(); - return WasmResult::Unimplemented; + WasmResult setHeaderMapPairs(WasmHeaderMapType /* type */, const Pairs & /* pairs */) override { + return unimplemented(); } - - /** - * Remove a key-value pair from a header map. - * @param type of the header map. - * @param key of the header map. - */ - virtual WasmResult removeHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */) { - unimplemented(); - return WasmResult::Unimplemented; + WasmResult removeHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */) override { + return unimplemented(); } - - /** - * Replace (or set) a value in a header map. - * @param type of the header map. - * @param key of the header map. - * @param value to set in the header map. - */ - virtual WasmResult replaceHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, - string_view /* value */) { - unimplemented(); - return WasmResult::Unimplemented; + WasmResult replaceHeaderMapValue(WasmHeaderMapType /* type */, string_view /* key */, + string_view /* value */) override { + return unimplemented(); } - - /** - * Returns the number of entries in a header map. - * @param type of the header map. - * @param result is a pointer to the result. - */ - virtual WasmResult getHeaderMapSize(WasmHeaderMapType /* type */, uint32_t * /* result */) { - unimplemented(); - return WasmResult::Unimplemented; + WasmResult getHeaderMapSize(WasmHeaderMapType /* type */, uint32_t * /* result */) override { + return unimplemented(); } protected: diff --git a/include/proxy-wasm/context_interface.h b/include/proxy-wasm/context_interface.h index 2b5001ed..7286c59e 100644 --- a/include/proxy-wasm/context_interface.h +++ b/include/proxy-wasm/context_interface.h @@ -26,8 +26,6 @@ #include #include -#include "include/proxy-wasm/proxy_action.h" - namespace proxy_wasm { #include "proxy_wasm_common.h" @@ -37,6 +35,23 @@ using Pairs = std::vector>; using PairsWithStringValues = std::vector>; using HttpCallToken = uint32_t; using GrpcToken = uint32_t; +using SharedQueueDequeueToken = uint32_t; +using SharedQueueEnqueueToken = uint32_t; + +// TODO: move to SDK. +enum WasmStreamType { + Request, + Response, + Downstream, + Upstream, +}; + +// TODO: update SDK. +enum class ProxyAction : uint32_t { + Illegal = 0, + Continue = 1, + Pause = 2, +}; struct PluginBase; class WasmBase; @@ -137,7 +152,6 @@ struct RootInterface : public RootGrpcInterface { * Called on a Root Context when an Inter-VM shared queue message has arrived. * @token is the token returned by registerSharedQueue(). */ - using SharedQueueDequeueToken = uint32_t; virtual void onQueueReady(uint32_t SharedQueueDequeueToken) = 0; /** @@ -168,7 +182,7 @@ struct HttpInterface { public: /** * Call on a stream context to indicate that the request headers have arrived. Calls - * onCreate(). + * onCreate() to create a Context in the VM first. */ virtual ProxyAction onRequestHeaders() = 0; @@ -193,6 +207,17 @@ struct HttpInterface { // Call on a stream context to indicate that the request metadata has arrived. virtual ProxyAction onResponseMetadata() = 0; + /** + * Respond directly to an HTTP request. + * @param response_code is the response code to send. + * @param body is the body of the response. + * @param additional_headers are additional headers to send in the response. + * @param grpc_status is an optional gRPC status if the connection is a gRPC connection. + * @param details are details of any (gRPC) error. + */ + virtual void sendLocalResponse(uint64_t response_code, string_view body, Pairs additional_headers, + uint64_t grpc_status, string_view details) = 0; + // Call when the stream closes. See RootInterface. virtual bool onDone() = 0; @@ -269,6 +294,85 @@ struct NetworkInterface { virtual void onFinalized() = 0; }; +/** + * General Stream interface (e.g. HTTP, Network). + **/ +struct StreamInterface { + + // Continue processing a request e.g. after returning ProxyAction::Pause. + virtual void continueStream(WasmStreamType type) = 0; + + /** + * Provides a BufferInterface to be used to return buffered data to the VM. + * @param type is the type of buffer to provide. + */ + virtual const BufferInterface *getBuffer(WasmBufferType type) = 0; + + /** + * Provides the end-of-stream status of the given flow (if any) or false. + * @param stream_type is the flow + */ + virtual bool end_of_stream(WasmStreamType type) = 0; +}; + +// Header/Trailer/Metadata Maps +struct HeaderInterface { + /** + * Add a key-value pair to a header map. + * @param type of the header map. + * @param key is the key (header). + * @param value is the value (header value). + */ + virtual WasmResult addHeaderMapValue(WasmHeaderMapType type, string_view key, + string_view value) = 0; + + /** + * Get a value from to a header map. + * @param type of the header map. + * @param key is the key (header). + * @param result is a pointer to the returned header value. + */ + virtual WasmResult getHeaderMapValue(WasmHeaderMapType type, string_view key, + string_view *result) = 0; + + /** + * Get all the key-value pairs in a header map. + * @param type of the header map. + * @param result is a pointer to the pairs. + */ + virtual WasmResult getHeaderMapPairs(WasmHeaderMapType type, Pairs *result) = 0; + + /** + * Set a header map so that it contains the given pairs (does not merge with existing data). + * @param type of the header map. + * @param the pairs to set the header map to. + */ + virtual WasmResult setHeaderMapPairs(WasmHeaderMapType type, const Pairs &pairs) = 0; + + /** + * Remove a key-value pair from a header map. + * @param type of the header map. + * @param key of the header map. + */ + virtual WasmResult removeHeaderMapValue(WasmHeaderMapType type, string_view key) = 0; + + /** + * Replace (or set) a value in a header map. + * @param type of the header map. + * @param key of the header map. + * @param value to set in the header map. + */ + virtual WasmResult replaceHeaderMapValue(WasmHeaderMapType type, string_view key, + string_view value) = 0; + + /** + * Returns the number of entries in a header map. + * @param type of the header map. + * @param result is a pointer to the result. + */ + virtual WasmResult getHeaderMapSize(WasmHeaderMapType type, uint32_t *result) = 0; +}; + struct HttpCallInterface { /** * Make an outgoing HTTP request. @@ -384,12 +488,128 @@ struct MetricsInterface { virtual WasmResult getMetric(uint32_t /* metric_id */, uint64_t * /* value_ptr */) = 0; }; +struct GeneralInterface { + /** + * Will be called on severe Wasm errors. Callees may report and handle the error (e.g. via an + * Exception) to prevent the proxy from crashing. + */ + virtual void error(string_view message) = 0; + + /** + * Called by all functions which are not overridden with a proxy-specific implementation. + * @return WasmResult::Unimplemented. + */ + virtual WasmResult unimplemented() = 0; + + // Log a message. + virtual WasmResult log(uint64_t level, string_view message) = 0; + + /** + * Enables a periodic timer with the given period or sets the period of an existing timer. Note: + * the timer is associated with the Root Context of whatever Context this call was made on and + * there is only one timer available per Root Context. + * @param period is the period of the periodic timer in milliseconds. If the period is 0 the + * timer is reset/deleted and will not call onTick. + * @param timer_token_ptr is a pointer to the timer_token. If the target of timer_token_ptr is + * zero, a new timer will be allocated its token will be set. If the target is non-zero, then + * that timer will have the new period (or be reset/deleted if period is zero). + */ + virtual WasmResult setTimerPeriod(std::chrono::milliseconds period, + uint32_t *timer_token_ptr) = 0; + + // Provides the current time in nanoseconds. + virtual uint64_t getCurrentTimeNanoseconds() = 0; + + /** + * Provides the status of the last call into the VM or out of the VM, similar to errno. + * @return the status code and a descriptive string. + */ + virtual std::pair getStatus() = 0; + + /** + * Get the value of a property. Some properties are proxy-independent (e.g. ["plugin_root_id"]) + * while others can be proxy-specific. + * @param path is a sequence of strings describing a path to a property. + * @param result is a location to write the value of the property. + */ + virtual WasmResult getProperty(string_view path, std::string *result) = 0; + + /** + * Set the value of a property. + * @param path is a sequence of strings describing a path to a property. + * @param value the value to set. For non-string, non-integral types, the value may be + * serialized.. + */ + virtual WasmResult setProperty(string_view key, string_view value) = 0; +}; + +struct SharedDataInterface { + /** + * Get proxy-wide key-value data shared between VMs. + * @param key is a proxy-wide key mapping to the shared data value. + * @param cas is a number which will be incremented when a data value has been changed. + * @param data is a location to store the returned stored 'value' and the corresponding 'cas' + * compare-and-swap value which can be used with setSharedData for safe concurrent updates. + */ + virtual WasmResult + getSharedData(string_view key, std::pair *data) = 0; + + /** + * Set a key-value data shared between VMs. + * @param key is a proxy-wide key mapping to the shared data value. + * @param cas is a compare-and-swap value. If it is zero it is ignored, otherwise it must match + * the cas associated with the value. + * @param data is a location to store the returned value. + */ + virtual WasmResult setSharedData(string_view key, string_view value, uint32_t cas) = 0; +}; + +struct SharedQueueInterface { + /** + * Register a proxy-wide queue. + * @param queue_name is a name for the queue. The queue_name is combined with the vm_id (if any) + * to make a unique identifier for the queue. + * @param token_ptr a location to store a token corresponding to the queue. + */ + virtual WasmResult registerSharedQueue(string_view queue_name, + SharedQueueDequeueToken *token_ptr) = 0; + + /** + * Get the token for a queue. + * @param vm_id is the vm_id of the Plugin of the Root Context which registered the queue. + * @param queue_name is a name for the queue. The queue_name is combined with the vm_id (if any) + * to make a unique identifier for the queue. + * @param token_ptr a location to store a token corresponding to the queue. + */ + virtual WasmResult resolveSharedQueue(string_view vm_id, string_view queue_name, + SharedQueueEnqueueToken *token_ptr) = 0; + + /** + * Dequeue a message from a shared queue. + * @param token is a token returned by registerSharedQueue(); + * @param data_ptr is a location to store the data dequeued. + */ + virtual WasmResult dequeueSharedQueue(SharedQueueDequeueToken token, std::string *data_ptr) = 0; + + /** + * Enqueue a message on a shared queue. + * @param token is a token returned by resolveSharedQueue(); + * @param data is the data to be queued. + */ + virtual WasmResult enqueueSharedQueue(SharedQueueEnqueueToken token, string_view data) = 0; +}; + struct ContextInterface : RootInterface, HttpInterface, NetworkInterface, + StreamInterface, + HeaderInterface, HttpCallInterface, GrpcCallInterface, GrpcStreamInterface, - MetricsInterface {}; + MetricsInterface, + SharedDataInterface, + SharedQueueInterface, + GeneralInterface {}; } // namespace proxy_wasm diff --git a/include/proxy-wasm/proxy_action.h b/include/proxy-wasm/proxy_action.h deleted file mode 100644 index 51d6df20..00000000 --- a/include/proxy-wasm/proxy_action.h +++ /dev/null @@ -1,29 +0,0 @@ -// 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 - -namespace proxy_wasm { - -// TODO: use the SDK version when it is updated. This is a placeholder. When the spec review -// completes the SDK will be updated with the final version and we will use that instead of this -// file. -enum class ProxyAction : uint32_t { - Illegal = 0, - Continue = 1, - Pause = 2, -}; - -} // namespace proxy_wasm From bf4675bd5a98e50e0d2c5af6b1e1a8ac1cc1fc70 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Tue, 24 Mar 2020 23:38:05 +0000 Subject: [PATCH 14/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context_interface.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/proxy-wasm/context_interface.h b/include/proxy-wasm/context_interface.h index 7286c59e..26f22941 100644 --- a/include/proxy-wasm/context_interface.h +++ b/include/proxy-wasm/context_interface.h @@ -309,7 +309,8 @@ struct StreamInterface { virtual const BufferInterface *getBuffer(WasmBufferType type) = 0; /** - * Provides the end-of-stream status of the given flow (if any) or false. + * Provides the end-of-stream status of the given flow (if any) or false. End of stream occurs + * when a connection is closed (or half-closed) either locally or remotely. * @param stream_type is the flow */ virtual bool end_of_stream(WasmStreamType type) = 0; @@ -543,6 +544,11 @@ struct GeneralInterface { virtual WasmResult setProperty(string_view key, string_view value) = 0; }; +/** + * SharedDataInterface is for shaing data between VMs. In general the VMs may be on different + * threads. Keys can have any format, but good practice would use reverse DNS and namespacing + * prefixes to avoid conflicts. + */ struct SharedDataInterface { /** * Get proxy-wide key-value data shared between VMs. @@ -562,7 +568,7 @@ struct SharedDataInterface { * @param data is a location to store the returned value. */ virtual WasmResult setSharedData(string_view key, string_view value, uint32_t cas) = 0; -}; +}; // namespace proxy_wasm struct SharedQueueInterface { /** From 9ca095c760c526b2129d4689233d016785bac84b Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Tue, 24 Mar 2020 23:41:57 +0000 Subject: [PATCH 15/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context.h | 10 +++++----- include/proxy-wasm/context_interface.h | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index 5642f39b..a6a55965 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -125,7 +125,7 @@ class ContextBase : public ContextInterface { unimplemented(); return true; } - void continueStream(WasmStreamType /* type */) override { unimplemented(); } + WasmResult continueStream(WasmStreamType /* type */) override { return unimplemented(); } // HTTP ProxyAction onRequestHeaders() override; @@ -136,10 +136,10 @@ class ContextBase : public ContextInterface { ProxyAction onResponseBody() override; ProxyAction onResponseTrailers() override; ProxyAction onResponseMetadata() override; - void sendLocalResponse(uint64_t /* response_code */, string_view /* body */, - Pairs /* additional_headers */, uint64_t /* grpc_status */, - string_view /* details */) override { - unimplemented(); + WasmResult sendLocalResponse(uint64_t /* response_code */, string_view /* body */, + Pairs /* additional_headers */, uint64_t /* grpc_status */, + string_view /* details */) override { + return unimplemented(); } // Network diff --git a/include/proxy-wasm/context_interface.h b/include/proxy-wasm/context_interface.h index 26f22941..71b3d2bf 100644 --- a/include/proxy-wasm/context_interface.h +++ b/include/proxy-wasm/context_interface.h @@ -215,8 +215,9 @@ struct HttpInterface { * @param grpc_status is an optional gRPC status if the connection is a gRPC connection. * @param details are details of any (gRPC) error. */ - virtual void sendLocalResponse(uint64_t response_code, string_view body, Pairs additional_headers, - uint64_t grpc_status, string_view details) = 0; + virtual WasmResult sendLocalResponse(uint64_t response_code, string_view body, + Pairs additional_headers, uint64_t grpc_status, + string_view details) = 0; // Call when the stream closes. See RootInterface. virtual bool onDone() = 0; @@ -300,7 +301,7 @@ struct NetworkInterface { struct StreamInterface { // Continue processing a request e.g. after returning ProxyAction::Pause. - virtual void continueStream(WasmStreamType type) = 0; + virtual WasmResult continueStream(WasmStreamType type) = 0; /** * Provides a BufferInterface to be used to return buffered data to the VM. From 897fe8d68c37d68ae8734669aec9428e666293c7 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Thu, 26 Mar 2020 23:51:05 +0000 Subject: [PATCH 16/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context_interface.h | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/include/proxy-wasm/context_interface.h b/include/proxy-wasm/context_interface.h index 71b3d2bf..db54b90b 100644 --- a/include/proxy-wasm/context_interface.h +++ b/include/proxy-wasm/context_interface.h @@ -85,7 +85,8 @@ struct RootGrpcInterface { /** * Called on Root Context to with the initial metadata of a grpcStream. * @token is the token returned by grpcStream. - * @metadata is the metadata received. + * The metadata can be retrieved via the HeaderInterface functions with + * WasmHeaderMapType::GrpcReceiveInitialMetadata as the type. */ virtual void onGrpcReceiveInitialMetadata(GrpcToken token) = 0; @@ -93,13 +94,16 @@ struct RootGrpcInterface { * Called on Root Context when gRPC data has arrived. * @token is the token returned by grpcCall or grpcStream. * For Call this implies OK close. For Stream may be called repeatedly. + * The data can be retrieved via the getBuffer function with + * WasmBufferType::GrpcReceiveBuffer as the type. */ virtual void onGrpcReceive(GrpcToken token) = 0; /** - * Called on Root Context to with the initial metadata of a grpcStream. + * Called on Root Context to with the trailing metadata of a grpcStream. * @token is the token returned by grpcStream. - * @metadata is the metadata received. + * The trailers can be retrieved via the HeaderInterface functions with + * WasmHeaderMapType::GrpcReceiveTrailingMetadata as the type. */ virtual void onGrpcReceiveTrailingMetadata(GrpcToken token) = 0; @@ -424,7 +428,7 @@ struct GrpcCallInterface { /** * Cancel a gRPC stream or call. No more calls will occur. * @param token is a token returned from grpcSream or grpcCall. - * For Call, cancel on call. For Strea, reset the stream: no further callbacks will arrive. + * For Call, cancel on call. For Stream, reset the stream: no further callbacks will arrive. */ virtual WasmResult grpcCancel(GrpcToken /* token */) = 0; }; @@ -457,6 +461,9 @@ struct GrpcStreamInterface { virtual WasmResult grpcCancel(GrpcToken token) = 0; }; +/** + * Metrics/Stats interface. See the proxy-wasm spec for details of the host ABI contract. + */ struct MetricsInterface { /** * Define a metric (Stat). @@ -508,8 +515,7 @@ struct GeneralInterface { /** * Enables a periodic timer with the given period or sets the period of an existing timer. Note: - * the timer is associated with the Root Context of whatever Context this call was made on and - * there is only one timer available per Root Context. + * the timer is associated with the Root Context of whatever Context this call was made on. * @param period is the period of the periodic timer in milliseconds. If the period is 0 the * timer is reset/deleted and will not call onTick. * @param timer_token_ptr is a pointer to the timer_token. If the target of timer_token_ptr is @@ -519,7 +525,7 @@ struct GeneralInterface { virtual WasmResult setTimerPeriod(std::chrono::milliseconds period, uint32_t *timer_token_ptr) = 0; - // Provides the current time in nanoseconds. + // Provides the current time in nanoseconds since the Unix epoch. virtual uint64_t getCurrentTimeNanoseconds() = 0; /** @@ -588,8 +594,8 @@ struct SharedQueueInterface { * to make a unique identifier for the queue. * @param token_ptr a location to store a token corresponding to the queue. */ - virtual WasmResult resolveSharedQueue(string_view vm_id, string_view queue_name, - SharedQueueEnqueueToken *token_ptr) = 0; + virtual WasmResult lookupSharedQueue(string_view vm_id, string_view queue_name, + SharedQueueEnqueueToken *token_ptr) = 0; /** * Dequeue a message from a shared queue. From 69ed17e3577e985d2bda4a754673bdf476a0056e Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Mon, 30 Mar 2020 16:42:21 +0000 Subject: [PATCH 17/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index a6a55965..89312166 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -109,7 +109,7 @@ class ContextBase : public ContextInterface { bool onStart(std::shared_ptr plugin) override; bool onConfigure(std::shared_ptr plugin) override; void onHttpCallResponse(HttpCallToken token) override; - void onQueueReady(uint32_t SharedQueueDequeueToken) override; + void onQueueReady(SharedQueueDequeueToken token) override; void onGrpcReceiveInitialMetadata(GrpcToken token) override; void onGrpcReceive(GrpcToken token) override; void onGrpcReceiveTrailingMetadata(GrpcToken token) override; @@ -246,8 +246,8 @@ class ContextBase : public ContextInterface { SharedQueueDequeueToken *token_ptr) override { return unimplemented(); } - WasmResult resolveSharedQueue(string_view /* vm_id */, string_view /* queue_name */, - uint32_t * /* token_ptr */) override { + WasmResult lookupSharedQueue(string_view /* vm_id */, string_view /* queue_name */, + uint32_t * /* token_ptr */) override { return unimplemented(); } WasmResult dequeueSharedQueue(SharedQueueDequeueToken /* token */, From 75e2a7e4c7c1af62871e678cf7f8b62aa9934da8 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Mon, 30 Mar 2020 16:45:16 +0000 Subject: [PATCH 18/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context.h | 6 +++--- include/proxy-wasm/context_interface.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index 89312166..6277bd61 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -136,8 +136,8 @@ class ContextBase : public ContextInterface { ProxyAction onResponseBody() override; ProxyAction onResponseTrailers() override; ProxyAction onResponseMetadata() override; - WasmResult sendLocalResponse(uint64_t /* response_code */, string_view /* body */, - Pairs /* additional_headers */, uint64_t /* grpc_status */, + WasmResult sendLocalResponse(uint32_t /* response_code */, string_view /* body */, + Pairs /* additional_headers */, uint32_t /* grpc_status */, string_view /* details */) override { return unimplemented(); } @@ -159,7 +159,7 @@ class ContextBase : public ContextInterface { error("unimplemented proxy-wasm API"); return WasmResult::Unimplemented; } - WasmResult log(uint64_t level, string_view message) override { + WasmResult log(uint32_t level, string_view message) override { if (level >= static_cast(LogLevel::error)) { std::cerr << log_prefix() << message << "\n"; } else { diff --git a/include/proxy-wasm/context_interface.h b/include/proxy-wasm/context_interface.h index db54b90b..16ba2896 100644 --- a/include/proxy-wasm/context_interface.h +++ b/include/proxy-wasm/context_interface.h @@ -156,7 +156,7 @@ struct RootInterface : public RootGrpcInterface { * Called on a Root Context when an Inter-VM shared queue message has arrived. * @token is the token returned by registerSharedQueue(). */ - virtual void onQueueReady(uint32_t SharedQueueDequeueToken) = 0; + virtual void onQueueReady(SharedQueueDequeueToken token) = 0; /** * Call when a stream has completed (both sides have closed) or on a Root Context when the VM is @@ -219,8 +219,8 @@ struct HttpInterface { * @param grpc_status is an optional gRPC status if the connection is a gRPC connection. * @param details are details of any (gRPC) error. */ - virtual WasmResult sendLocalResponse(uint64_t response_code, string_view body, - Pairs additional_headers, uint64_t grpc_status, + virtual WasmResult sendLocalResponse(uint32_t response_code, string_view body, + Pairs additional_headers, uint32_t grpc_status, string_view details) = 0; // Call when the stream closes. See RootInterface. @@ -511,7 +511,7 @@ struct GeneralInterface { virtual WasmResult unimplemented() = 0; // Log a message. - virtual WasmResult log(uint64_t level, string_view message) = 0; + virtual WasmResult log(uint32_t level, string_view message) = 0; /** * Enables a periodic timer with the given period or sets the period of an existing timer. Note: From bcad2d9950479a93c084f7dce4ecafa791597289 Mon Sep 17 00:00:00 2001 From: John Plevyak Date: Mon, 30 Mar 2020 16:50:00 +0000 Subject: [PATCH 19/19] Address comments. Signed-off-by: John Plevyak --- include/proxy-wasm/context_interface.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/proxy-wasm/context_interface.h b/include/proxy-wasm/context_interface.h index 16ba2896..c4fd4caf 100644 --- a/include/proxy-wasm/context_interface.h +++ b/include/proxy-wasm/context_interface.h @@ -73,6 +73,8 @@ struct BufferInterface { * @param size_ptr is the location in the VM address space to place the size of the newly * allocated memory block which contains the copied bytes (i.e. length). * @return a WasmResult with any error or WasmResult::Ok. + * NB: in order to support (future) 64-bit VMs and the NullVM we need 64-bits worth of resolution + * for addresses. */ virtual WasmResult copyTo(WasmBase *wasm, size_t start, size_t length, uint64_t ptr_ptr, uint64_t size_ptr) const = 0; @@ -131,7 +133,7 @@ struct RootInterface : public RootGrpcInterface { * @param parent_context_id is the parent Context id for the context being created. For a * stream Context this will be a Root Context id (or sub-Context thereof). */ - virtual void onCreate(uint32_t parent_context_id); + virtual void onCreate(uint32_t parent_context_id) = 0; /** * Call on a Root Context when a VM first starts up. @@ -173,7 +175,7 @@ struct RootInterface : public RootGrpcInterface { * VM to be deleted. * Called by the host code. */ - virtual void onDelete(); + virtual void onDelete() = 0; }; /** @@ -297,6 +299,9 @@ struct NetworkInterface { // Call when the stream status has finalized, e.g. for logging. See RootInterface. virtual void onFinalized() = 0; + + // Call just before the Context is deleted. See RootInterface. + virtual void onDelete() = 0; }; /**