Skip to content

Commit e73c498

Browse files
authored
Support multiple versions of the Proxy-Wasm ABI. (#42)
Signed-off-by: Piotr Sikora <[email protected]>
1 parent c15a8ff commit e73c498

File tree

15 files changed

+160
-23
lines changed

15 files changed

+160
-23
lines changed

include/proxy-wasm/context.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,10 @@ class ContextBase : public RootInterface,
238238
t += tpe.tv_nsec;
239239
return t;
240240
}
241+
std::string_view getConfiguration() override {
242+
unimplemented();
243+
return "";
244+
}
241245
std::pair<uint32_t, std::string_view> getStatus() override {
242246
unimplemented();
243247
return std::make_pair(1, "unimplmemented");
@@ -316,6 +320,7 @@ class ContextBase : public RootInterface,
316320
std::string_view /* details */) override {
317321
return unimplemented();
318322
}
323+
void clearRouteCache() override { unimplemented(); }
319324
void failStream(WasmStreamType stream_type) override { closeStream(stream_type); }
320325

321326
// Shared Data

include/proxy-wasm/context_interface.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ struct HttpInterface {
235235
Pairs additional_headers, uint32_t grpc_status,
236236
std::string_view details) = 0;
237237

238+
// Clears the route cache for the current request.
239+
virtual void clearRouteCache() = 0;
240+
238241
// Call when the stream closes. See RootInterface.
239242
virtual bool onDone() = 0;
240243

@@ -551,6 +554,9 @@ struct GeneralInterface {
551554
// Provides the current time in nanoseconds since the Unix epoch.
552555
virtual uint64_t getCurrentTimeNanoseconds() = 0;
553556

557+
// Returns plugin configuration.
558+
virtual std::string_view getConfiguration() = 0;
559+
554560
/**
555561
* Provides the status of the last call into the VM or out of the VM, similar to errno.
556562
* @return the status code and a descriptive string.

include/proxy-wasm/exports.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,22 @@ namespace exports {
2929

3030
// ABI functions exported from envoy to wasm.
3131

32+
Word get_configuration(void *raw_context, Word address, Word size);
3233
Word get_status(void *raw_context, Word status_code, Word address, Word size);
3334
Word log(void *raw_context, Word level, Word address, Word size);
3435
Word get_log_level(void *raw_context, Word result_level_uint32_ptr);
3536
Word get_property(void *raw_context, Word path_ptr, Word path_size, Word value_ptr_ptr,
3637
Word value_size_ptr);
3738
Word set_property(void *raw_context, Word key_ptr, Word key_size, Word value_ptr, Word value_size);
39+
Word continue_request(void *raw_context);
40+
Word continue_response(void *raw_context);
3841
Word continue_stream(void *raw_context, Word stream_type);
3942
Word close_stream(void *raw_context, Word stream_type);
4043
Word send_local_response(void *raw_context, Word response_code, Word response_code_details_ptr,
4144
Word response_code_details_size, Word body_ptr, Word body_size,
4245
Word additional_response_header_pairs_ptr,
4346
Word additional_response_header_pairs_size, Word grpc_status);
47+
Word clear_route_cache(void *raw_context);
4448
Word get_shared_data(void *raw_context, Word key_ptr, Word key_size, Word value_ptr_ptr,
4549
Word value_size_ptr, Word cas_ptr);
4650
Word set_shared_data(void *raw_context, Word key_ptr, Word key_size, Word value_ptr,

include/proxy-wasm/null_plugin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ namespace proxy_wasm {
3737
*/
3838
struct NullPluginRegistry {
3939
void (*proxy_abi_version_0_1_0_)() = nullptr;
40+
void (*proxy_abi_version_0_2_0_)() = nullptr;
4041
void (*proxy_on_log_)(uint32_t context_id) = nullptr;
4142
uint32_t (*proxy_validate_configuration_)(uint32_t root_context_id,
4243
uint32_t plugin_configuration_size) = nullptr;

include/proxy-wasm/null_vm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct NullVm : public WasmVm {
3636
Cloneable cloneable() override { return Cloneable::InstantiatedModule; };
3737
std::unique_ptr<WasmVm> clone() override;
3838
bool load(const std::string &code, bool allow_precompiled) override;
39+
AbiVersion getAbiVersion() override;
3940
bool link(std::string_view debug_name) override;
4041
uint64_t getMemorySize() override;
4142
std::optional<std::string_view> getMemory(uint64_t pointer, uint64_t size) override;

include/proxy-wasm/wasm.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
122122
virtual void error(std::string_view message) { std::cerr << message << "\n"; }
123123
virtual void unimplemented() { error("unimplemented proxy-wasm API"); }
124124

125+
AbiVersion abiVersion() { return abi_version_; }
126+
125127
bool getEmscriptenVersion(uint32_t *emscripten_metadata_major_version,
126128
uint32_t *emscripten_metadata_minor_version,
127129
uint32_t *emscripten_abi_major_version,
@@ -184,8 +186,6 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
184186
std::unique_ptr<ShutdownHandle> shutdown_handle_;
185187
std::unordered_set<ContextBase *> pending_done_; // Root contexts not done during shutdown.
186188

187-
WasmCallVoid<0> abi_version_0_1_0_;
188-
189189
WasmCallVoid<0> _start_; /* Emscripten v1.39.0+ */
190190
WasmCallVoid<0> __wasm_call_ctors_;
191191

@@ -205,12 +205,14 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
205205
WasmCallVoid<2> on_downstream_connection_close_;
206206
WasmCallVoid<2> on_upstream_connection_close_;
207207

208-
WasmCallWord<3> on_request_headers_;
208+
WasmCallWord<2> on_request_headers_abi_01_;
209+
WasmCallWord<3> on_request_headers_abi_02_;
209210
WasmCallWord<3> on_request_body_;
210211
WasmCallWord<2> on_request_trailers_;
211212
WasmCallWord<2> on_request_metadata_;
212213

213-
WasmCallWord<3> on_response_headers_;
214+
WasmCallWord<2> on_response_headers_abi_01_;
215+
WasmCallWord<3> on_response_headers_abi_02_;
214216
WasmCallWord<3> on_response_body_;
215217
WasmCallWord<2> on_response_trailers_;
216218
WasmCallWord<2> on_response_metadata_;
@@ -238,6 +240,9 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
238240
bool allow_precompiled_ = false;
239241
FailState failed_ = FailState::Ok; // Wasm VM fatal error.
240242

243+
// ABI version.
244+
AbiVersion abi_version_ = AbiVersion::Unknown;
245+
241246
bool is_emscripten_ = false;
242247
uint32_t emscripten_metadata_major_version_ = 0;
243248
uint32_t emscripten_metadata_minor_version_ = 0;

include/proxy-wasm/wasm_api_impl.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ namespace null_plugin {
2323

2424
inline WasmResult wordToWasmResult(Word w) { return static_cast<WasmResult>(w.u64_); }
2525

26+
// Configuration and Status
27+
inline WasmResult proxy_get_configuration(const char **configuration_ptr,
28+
size_t *configuration_size) {
29+
return wordToWasmResult(
30+
exports::get_configuration(current_context_, WR(configuration_ptr), WR(configuration_size)));
31+
}
32+
2633
inline WasmResult proxy_get_status(uint32_t *code_ptr, const char **ptr, size_t *size) {
2734
return wordToWasmResult(exports::get_status(current_context_, WR(code_ptr), WR(ptr), WR(size)));
2835
}
@@ -58,6 +65,12 @@ inline WasmResult proxy_set_property(const char *key_ptr, size_t key_size, const
5865
}
5966

6067
// Continue
68+
inline WasmResult proxy_continue_request() {
69+
return wordToWasmResult(exports::continue_request(current_context_));
70+
}
71+
inline WasmResult proxy_continue_response() {
72+
return wordToWasmResult(exports::continue_response(current_context_));
73+
}
6174
inline WasmResult proxy_continue_stream(WasmStreamType stream_type) {
6275
return wordToWasmResult(exports::continue_stream(current_context_, WS(stream_type)));
6376
}
@@ -76,6 +89,10 @@ proxy_send_local_response(uint32_t response_code, const char *response_code_deta
7689
WS(grpc_status)));
7790
}
7891

92+
inline WasmResult proxy_clear_route_cache() {
93+
return wordToWasmResult(exports::clear_route_cache(current_context_));
94+
}
95+
7996
// SharedData
8097
inline WasmResult proxy_get_shared_data(const char *key_ptr, size_t key_size,
8198
const char **value_ptr, size_t *value_size, uint32_t *cas) {

include/proxy-wasm/wasm_vm.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ enum class Cloneable {
101101
InstantiatedModule // VMs can be cloned from an instantiated module.
102102
};
103103

104+
enum class AbiVersion { ProxyWasm_0_1_0, ProxyWasm_0_2_0, Unknown };
105+
104106
class NullPlugin;
105107

106108
// Integrator specific WasmVm operations.
@@ -185,6 +187,12 @@ class WasmVm {
185187
*/
186188
virtual bool link(std::string_view debug_name) = 0;
187189

190+
/**
191+
* Get ABI version of the module.
192+
* @return the ABI version.
193+
*/
194+
virtual AbiVersion getAbiVersion() = 0;
195+
188196
/**
189197
* Get size of the currently allocated memory in the VM.
190198
* @return the size of memory in bytes.

src/context.cc

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,24 @@
3737
} \
3838
}
3939

40+
#define CHECK_FAIL2(_call1, _call2, _stream_type, _return_open, _return_closed) \
41+
if (isFailed()) { \
42+
if (plugin_->fail_open_) { \
43+
return _return_open; \
44+
} else { \
45+
failStream(_stream_type); \
46+
return _return_closed; \
47+
} \
48+
} else { \
49+
if (!wasm_->_call1 && !wasm_->_call2) { \
50+
return _return_open; \
51+
} \
52+
}
53+
4054
#define CHECK_HTTP(_call, _return_open, _return_closed) \
4155
CHECK_FAIL(_call, WasmStreamType::Request, _return_open, _return_closed)
56+
#define CHECK_HTTP2(_call1, _call2, _return_open, _return_closed) \
57+
CHECK_FAIL2(_call1, _call2, WasmStreamType::Request, _return_open, _return_closed)
4258
#define CHECK_NET(_call, _return_open, _return_closed) \
4359
CHECK_FAIL(_call, WasmStreamType::Downstream, _return_open, _return_closed)
4460

@@ -443,11 +459,15 @@ void ContextBase::onUpstreamConnectionClose(CloseType close_type) {
443459
template <typename P> static uint32_t headerSize(const P &p) { return p ? p->size() : 0; }
444460

445461
FilterHeadersStatus ContextBase::onRequestHeaders(uint32_t headers, bool end_of_stream) {
446-
CHECK_HTTP(on_request_headers_, FilterHeadersStatus::Continue,
447-
FilterHeadersStatus::StopIteration);
462+
CHECK_HTTP2(on_request_headers_abi_01_, on_request_headers_abi_02_, FilterHeadersStatus::Continue,
463+
FilterHeadersStatus::StopIteration);
448464
DeferAfterCallActions actions(this);
449-
auto result =
450-
wasm_->on_request_headers_(this, id_, headers, static_cast<uint32_t>(end_of_stream)).u64_;
465+
auto result = wasm_->on_request_headers_abi_01_
466+
? wasm_->on_request_headers_abi_01_(this, id_, headers).u64_
467+
: wasm_
468+
->on_request_headers_abi_02_(this, id_, headers,
469+
static_cast<uint32_t>(end_of_stream))
470+
.u64_;
451471
if (result > static_cast<uint64_t>(FilterHeadersStatus::StopAllIterationAndWatermark))
452472
return FilterHeadersStatus::StopAllIterationAndWatermark;
453473
return static_cast<FilterHeadersStatus>(result);
@@ -485,11 +505,15 @@ FilterMetadataStatus ContextBase::onRequestMetadata(uint32_t elements) {
485505
}
486506

487507
FilterHeadersStatus ContextBase::onResponseHeaders(uint32_t headers, bool end_of_stream) {
488-
CHECK_HTTP(on_response_headers_, FilterHeadersStatus::Continue,
489-
FilterHeadersStatus::StopIteration);
508+
CHECK_HTTP2(on_response_headers_abi_01_, on_response_headers_abi_02_,
509+
FilterHeadersStatus::Continue, FilterHeadersStatus::StopIteration);
490510
DeferAfterCallActions actions(this);
491-
auto result =
492-
wasm_->on_response_headers_(this, id_, headers, static_cast<uint32_t>(end_of_stream)).u64_;
511+
auto result = wasm_->on_response_headers_abi_01_
512+
? wasm_->on_response_headers_abi_01_(this, id_, headers).u64_
513+
: wasm_
514+
->on_response_headers_abi_02_(this, id_, headers,
515+
static_cast<uint32_t>(end_of_stream))
516+
.u64_;
493517
if (result > static_cast<uint64_t>(FilterHeadersStatus::StopAllIterationAndWatermark))
494518
return FilterHeadersStatus::StopAllIterationAndWatermark;
495519
return static_cast<FilterHeadersStatus>(result);

src/exports.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ Word get_property(void *raw_context, Word path_ptr, Word path_size, Word value_p
148148
return WasmResult::Ok;
149149
}
150150

151+
Word get_configuration(void *raw_context, Word value_ptr_ptr, Word value_size_ptr) {
152+
auto context = WASM_CONTEXT(raw_context);
153+
auto value = context->getConfiguration();
154+
if (!context->wasm()->copyToPointerSize(value, value_ptr_ptr, value_size_ptr)) {
155+
return WasmResult::InvalidMemoryAccess;
156+
}
157+
return WasmResult::Ok;
158+
}
159+
151160
Word get_status(void *raw_context, Word code_ptr, Word value_ptr_ptr, Word value_size_ptr) {
152161
auto context = WASM_CONTEXT(raw_context);
153162
auto status = context->getStatus();
@@ -163,6 +172,16 @@ Word get_status(void *raw_context, Word code_ptr, Word value_ptr_ptr, Word value
163172
// HTTP
164173

165174
// Continue/Reply/Route
175+
Word continue_request(void *raw_context) {
176+
auto context = WASM_CONTEXT(raw_context);
177+
return context->continueStream(WasmStreamType::Request);
178+
}
179+
180+
Word continue_response(void *raw_context) {
181+
auto context = WASM_CONTEXT(raw_context);
182+
return context->continueStream(WasmStreamType::Response);
183+
}
184+
166185
Word continue_stream(void *raw_context, Word type) {
167186
auto context = WASM_CONTEXT(raw_context);
168187
if (type > static_cast<uint64_t>(WasmStreamType::MAX)) {
@@ -198,6 +217,12 @@ Word send_local_response(void *raw_context, Word response_code, Word response_co
198217
return WasmResult::Ok;
199218
}
200219

220+
Word clear_route_cache(void *raw_context) {
221+
auto context = WASM_CONTEXT(raw_context);
222+
context->clearRouteCache();
223+
return WasmResult::Ok;
224+
}
225+
201226
Word set_effective_context(void *raw_context, Word context_id) {
202227
auto context = WASM_CONTEXT(raw_context);
203228
uint32_t cid = static_cast<uint32_t>(context_id);

0 commit comments

Comments
 (0)