Skip to content
This repository has been archived by the owner on Dec 16, 2020. It is now read-only.

Add support for onForeignFunction and proxy-specific extensions. #538

Merged
merged 23 commits into from
Jun 26, 2020
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d0fed58
Add support for onForeignFunction and proxy-specific extensions.
jplevyak May 28, 2020
c078e5a
Fix tests.
jplevyak May 28, 2020
346bff2
Fix formating.
jplevyak May 28, 2020
b1553f4
Add comments.
jplevyak May 28, 2020
2a7c6d1
Add missing file.
jplevyak May 28, 2020
7dd6e92
Format.
jplevyak Jun 1, 2020
54132ca
Update test.
jplevyak Jun 1, 2020
055f674
Fix asan.
jplevyak Jun 1, 2020
19c7be8
s/cc_library/envoy_cc_library/
jplevyak Jun 3, 2020
2c73954
Update SDK.
jplevyak Jun 3, 2020
90b2e5d
Merge branch 'master' of github.com:envoyproxy/envoy-wasm into extending
jplevyak Jun 3, 2020
3f81739
Switch Wasm coverage fix.
jplevyak Jun 4, 2020
6c08032
Update tests.
jplevyak Jun 5, 2020
be8eef1
Merge branch 'master' of github.com:envoyproxy/envoy-wasm into extending
jplevyak Jun 8, 2020
87cd432
Format.
jplevyak Jun 8, 2020
d7f36ac
Fix formatting.
jplevyak Jun 8, 2020
47d6e1a
Merge branch 'master' of github.com:envoyproxy/envoy-wasm into extending
jplevyak Jun 10, 2020
9a88f25
Fix sig mismatch trap.
jplevyak Jun 12, 2020
5765009
Merge branch 'master' of github.com:envoyproxy/envoy-wasm into extending
jplevyak Jun 15, 2020
cf65a7e
Address comments.
jplevyak Jun 25, 2020
cce6e6c
Merge branch 'master' of github.com:envoyproxy/envoy-wasm into extending
jplevyak Jun 25, 2020
3317417
Merge branch 'master' of github.com:envoyproxy/envoy-wasm into extending
jplevyak Jun 25, 2020
1c4abba
Merge branch 'extending' of github.com:jplevyak/envoy-wasm into exten…
jplevyak Jun 25, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bazel/external/wee8.genrule_cmd
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@ fi
# Debug/release build.
if [[ $(COMPILATION_MODE) == "dbg" && $${ENVOY_UBSAN_VPTR-} != "1" && $${ENVOY_MSAN-} != "1" && $${ENVOY_TSAN-} != "1" ]]; then
WEE8_BUILD_ARGS+=" is_debug=true"
WEE8_BUILD_ARGS+=" v8_symbol_level=2"
WEE8_BUILD_ARGS+=" symbol_level=2"
jplevyak marked this conversation as resolved.
Show resolved Hide resolved
WEE8_BUILD_ARGS+=" v8_optimized_debug=false"
else
WEE8_BUILD_ARGS+=" is_debug=false"
WEE8_BUILD_ARGS+=" v8_symbol_level=1"
WEE8_BUILD_ARGS+=" symbol_level=1"
WEE8_BUILD_ARGS+=" v8_enable_handle_zapping=false"
fi
Expand Down
12 changes: 6 additions & 6 deletions bazel/repository_locations.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -498,16 +498,16 @@ DEPENDENCY_REPOSITORIES = dict(
use_category = ["test"],
),
proxy_wasm_cpp_sdk = dict(
sha256 = "0e5b0d3c17c0737e5b48408bda6060a4057f7508a38afa8e0174ad410d370a6f",
strip_prefix = "proxy-wasm-cpp-sdk-f750d1f5da6a2f20cc55da75dd9772b7ba1650ca",
urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/archive/f750d1f5da6a2f20cc55da75dd9772b7ba1650ca.tar.gz"],
sha256 = "f3f6d10243aa42c6ade5a5e46adead3a3ff38efeffce6c4fd17ca0a9fe441222",
strip_prefix = "proxy-wasm-cpp-sdk-246314dc6cf6faee4ade26d614ecbf98f6036e3c",
urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/archive/246314dc6cf6faee4ade26d614ecbf98f6036e3c.tar.gz"],
use_category = ["dataplane"],
cpe = "N/A",
),
proxy_wasm_cpp_host = dict(
sha256 = "2bee3e13bf86c2df13f4dadd056d19d4e04fc584b485191d871429cef4613683",
strip_prefix = "proxy-wasm-cpp-host-366f64b2a028bea761a5c3da82536c31d45cc63d",
urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-host/archive/366f64b2a028bea761a5c3da82536c31d45cc63d.tar.gz"],
sha256 = "0eb4164f2d777d2a65c254f3901aa00461e9e50c592e8dfac793bc3d2a76fb21",
strip_prefix = "proxy-wasm-cpp-host-2523cfb1968aff039fa08703b20c701824a165c3",
urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-host/archive/2523cfb1968aff039fa08703b20c701824a165c3.tar.gz"],
use_category = ["dataplane"],
cpe = "N/A",
),
Expand Down
1 change: 1 addition & 0 deletions source/extensions/common/wasm/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ envoy_cc_library(
"//source/common/http:message_lib",
"//source/common/http:utility_lib",
"//source/common/tracing:http_tracer_lib",
"//source/extensions/common/wasm/ext:envoy_null_vm_wasm_api",
"//source/extensions/filters/common/expr:context_lib",
"@com_google_cel_cpp//eval/eval:field_access",
"@com_google_cel_cpp//eval/eval:field_backed_list_impl",
Expand Down
92 changes: 58 additions & 34 deletions source/extensions/common/wasm/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ template <typename P> static uint32_t headerSize(const P& p) { return p ? p->siz
// Test support.

size_t Buffer::size() const {
if (buffer_instance_) {
return buffer_instance_->length();
if (const_buffer_instance_) {
return const_buffer_instance_->length();
}
return data_.size();
return proxy_wasm::BufferBase::size();
}

WasmResult Buffer::copyTo(WasmBase* wasm, size_t start, size_t length, uint64_t ptr_ptr,
Expand All @@ -103,11 +103,7 @@ WasmResult Buffer::copyTo(WasmBase* wasm, size_t start, size_t length, uint64_t
}
return WasmResult::Ok;
}
absl::string_view s = data_.substr(start, length);
if (!wasm->copyToPointerSize(s, ptr_ptr, size_ptr)) {
return WasmResult::InvalidMemoryAccess;
}
return WasmResult::Ok;
return proxy_wasm::BufferBase::copyTo(wasm, start, length, ptr_ptr, size_ptr);
}

WasmResult Buffer::copyFrom(size_t start, size_t length, absl::string_view data) {
Expand All @@ -133,8 +129,7 @@ WasmResult Buffer::copyFrom(size_t start, size_t length, absl::string_view data)
if (const_buffer_instance_) { // This buffer is immutable.
return WasmResult::BadArgument;
}
// Setting a string buffer not supported (no use case).
return WasmResult::BadArgument;
return proxy_wasm::BufferBase::copyFrom(start, length, data);
}

Context::Context() = default;
Expand All @@ -157,11 +152,6 @@ void Context::initializeRoot(WasmBase* wasm, std::shared_ptr<PluginBase> plugin)
root_local_info_ = &std::static_pointer_cast<Plugin>(plugin)->local_info_;
}

WasmResult Context::setTimerPeriod(std::chrono::milliseconds tick_period, uint32_t*) {
wasm()->setTimerPeriod(root_context_id_ ? root_context_id_ : id_, tick_period);
return WasmResult::Ok;
}

uint64_t Context::getCurrentTimeNanoseconds() {
return std::chrono::duration_cast<std::chrono::nanoseconds>(
wasm()->time_source_.systemTime().time_since_epoch())
Expand All @@ -178,6 +168,45 @@ void Context::onCloseTCP() {
onDelete();
}

void Context::onResolveDns(uint32_t token, Envoy::Network::DnsResolver::ResolutionStatus status,
std::list<Envoy::Network::DnsResponse>&& response) {
proxy_wasm::DeferAfterCallActions actions(this);
if (!wasm()->on_resolve_dns_) {
return;
}
if (status != Network::DnsResolver::ResolutionStatus::Success) {
buffer_.set("");
wasm()->on_resolve_dns_(this, id_, token, 0);
return;
}
// buffer format:
// 4 bytes number of entries = N
// N * 4 bytes TTL for each entry
// N * null-terminated addresses
uint32_t s = 4; // length
for (auto& e : response) {
s += 4; // for TTL
s += e.address_->asStringView().size() + 1; // null terminated.
}
auto buffer = std::unique_ptr<char[]>(new char[s]);
char* b = buffer.get();
uint32_t n = response.size();
memcpy(b, &n, sizeof(uint32_t));
b += sizeof(uint32_t);
for (auto& e : response) {
uint32_t ttl = e.ttl_.count();
memcpy(b, &ttl, sizeof(uint32_t));
b += sizeof(uint32_t);
};
for (auto& e : response) {
memcpy(b, e.address_->asStringView().data(), e.address_->asStringView().size());
b += e.address_->asStringView().size();
*b++ = 0;
};
buffer_.set(std::move(buffer), s);
wasm()->on_resolve_dns_(this, id_, token, s);
}

// Native serializer carrying over bit representation from CEL value to the extension
WasmResult serializeValue(Filters::Common::Expr::CelValue value, std::string* result) {
using Filters::Common::Expr::CelValue;
Expand Down Expand Up @@ -638,6 +667,9 @@ WasmResult Context::getHeaderMapSize(WasmHeaderMapType type, uint32_t* result) {

BufferInterface* Context::getBuffer(WasmBufferType type) {
switch (type) {
case WasmBufferType::CallData:
// Set before the call.
return &buffer_;
case WasmBufferType::VmConfiguration:
return buffer_.set(wasm()->vm_configuration());
case WasmBufferType::PluginConfiguration:
Expand Down Expand Up @@ -1189,9 +1221,7 @@ Http::FilterDataStatus convertFilterDataStatus(proxy_wasm::FilterDataStatus stat
};

Network::FilterStatus Context::onNewConnection() {
if (!in_vm_context_created_) {
onCreate(root_context_id_);
}
onCreate();
return convertNetworkFilterStatus(onNetworkNewConnection());
};

Expand Down Expand Up @@ -1255,7 +1285,7 @@ void Context::log(const Http::RequestHeaderMap* request_headers,
const Http::ResponseHeaderMap* response_headers,
const Http::ResponseTrailerMap* response_trailers,
const StreamInfo::StreamInfo& stream_info) {
if (!in_vm_context_created_) {
if (!http_request_started_) {
return;
}
access_log_request_headers_ = request_headers;
Expand Down Expand Up @@ -1323,9 +1353,8 @@ WasmResult Context::sendLocalResponse(uint32_t response_code, absl::string_view
}

Http::FilterHeadersStatus Context::decodeHeaders(Http::RequestHeaderMap& headers, bool end_stream) {
if (!in_vm_context_created_) {
onCreate(root_context_id_);
}
onCreate();
http_request_started_ = true;
request_headers_ = &headers;
end_of_stream_ = end_stream;
auto result = convertFilterHeadersStatus(onRequestHeaders(headerSize(&headers), end_stream));
Expand All @@ -1336,7 +1365,7 @@ Http::FilterHeadersStatus Context::decodeHeaders(Http::RequestHeaderMap& headers
}

Http::FilterDataStatus Context::decodeData(::Envoy::Buffer::Instance& data, bool end_stream) {
if (!in_vm_context_created_) {
if (!http_request_started_) {
return Http::FilterDataStatus::Continue;
}
request_body_buffer_ = &data;
Expand All @@ -1358,7 +1387,7 @@ Http::FilterDataStatus Context::decodeData(::Envoy::Buffer::Instance& data, bool
}

Http::FilterTrailersStatus Context::decodeTrailers(Http::RequestTrailerMap& trailers) {
if (!in_vm_context_created_) {
if (!http_request_started_) {
return Http::FilterTrailersStatus::Continue;
}
request_trailers_ = &trailers;
Expand All @@ -1370,7 +1399,7 @@ Http::FilterTrailersStatus Context::decodeTrailers(Http::RequestTrailerMap& trai
}

Http::FilterMetadataStatus Context::decodeMetadata(Http::MetadataMap& request_metadata) {
if (!in_vm_context_created_) {
if (!http_request_started_) {
return Http::FilterMetadataStatus::Continue;
}
request_metadata_ = &request_metadata;
Expand All @@ -1391,12 +1420,7 @@ Http::FilterHeadersStatus Context::encode100ContinueHeaders(Http::ResponseHeader

Http::FilterHeadersStatus Context::encodeHeaders(Http::ResponseHeaderMap& headers,
bool end_stream) {
if (!in_vm_context_created_) {
// If the request is invalid then onRequestHeaders() will not be called and neither will
// onCreate() then sendLocalReply be called which will call this function. We have two choices,
// we can call onCreate() so that the Context inside the VM is created before the
// onResponseHeaders() call or we can just return. Since the Filter has not seen the request it
// makes more sense to just return here.
if (!http_request_started_) {
return Http::FilterHeadersStatus::Continue;
}
response_headers_ = &headers;
Expand All @@ -1409,7 +1433,7 @@ Http::FilterHeadersStatus Context::encodeHeaders(Http::ResponseHeaderMap& header
}

Http::FilterDataStatus Context::encodeData(::Envoy::Buffer::Instance& data, bool end_stream) {
if (!in_vm_context_created_) {
if (!http_request_started_) {
return Http::FilterDataStatus::Continue;
}
response_body_buffer_ = &data;
Expand All @@ -1431,7 +1455,7 @@ Http::FilterDataStatus Context::encodeData(::Envoy::Buffer::Instance& data, bool
}

Http::FilterTrailersStatus Context::encodeTrailers(Http::ResponseTrailerMap& trailers) {
if (!in_vm_context_created_) {
if (!http_request_started_) {
return Http::FilterTrailersStatus::Continue;
}
response_trailers_ = &trailers;
Expand All @@ -1443,7 +1467,7 @@ Http::FilterTrailersStatus Context::encodeTrailers(Http::ResponseTrailerMap& tra
}

Http::FilterMetadataStatus Context::encodeMetadata(Http::MetadataMap& response_metadata) {
if (!in_vm_context_created_) {
if (!http_request_started_) {
return Http::FilterMetadataStatus::Continue;
}
response_metadata_ = &response_metadata;
Expand Down
47 changes: 32 additions & 15 deletions source/extensions/common/wasm/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,16 @@
#include "extensions/filters/common/expr/evaluator.h"

#include "eval/public/activation.h"
#include "include/proxy-wasm/context.h"
#include "include/proxy-wasm/wasm.h"

namespace Envoy {
namespace Extensions {
namespace Common {
namespace Wasm {

#include "proxy_wasm_common.h"

using proxy_wasm::BufferInterface;
using proxy_wasm::CloseType;
using proxy_wasm::ContextBase;
using proxy_wasm::MetricType;
using proxy_wasm::Pairs;
using proxy_wasm::PairsWithStringValues;
Expand All @@ -40,6 +38,7 @@ using proxy_wasm::WasmBufferType;
using proxy_wasm::WasmHandleBase;
using proxy_wasm::WasmHeaderMapType;
using proxy_wasm::WasmResult;
using proxy_wasm::Word;

using GrpcService = envoy::config::core::v3::GrpcService;

Expand All @@ -53,30 +52,43 @@ class StorageObject {
virtual ~StorageObject() = default;
};

class Buffer : public proxy_wasm::BufferInterface {
class Buffer : public proxy_wasm::BufferBase {
public:
Buffer() = default;

Buffer* set(absl::string_view data) {
data_ = data;
// proxy_wasm::BufferInterface
size_t size() const override;
WasmResult copyTo(WasmBase* wasm, size_t start, size_t length, uint64_t ptr_ptr,
uint64_t size_ptr) const override;
WasmResult copyFrom(size_t start, size_t length, absl::string_view data) override;

// proxy_wasm::BufferBase
void clear() override {
proxy_wasm::BufferBase::clear();
const_buffer_instance_ = nullptr;
buffer_instance_ = nullptr;
return this;
}
Buffer* set(absl::string_view data) {
return static_cast<Buffer*>(proxy_wasm::BufferBase::set(data));
}
Buffer* set(std::unique_ptr<char[]> owned_data, uint32_t owned_data_size) {
return static_cast<Buffer*>(
proxy_wasm::BufferBase::set(std::move(owned_data), owned_data_size));
}

Buffer* set(::Envoy::Buffer::Instance* buffer_instance) {
data_ = "";
clear();
buffer_instance_ = buffer_instance;
const_buffer_instance_ = buffer_instance;
return this;
}

size_t size() const override;
WasmResult copyTo(WasmBase* wasm, size_t start, size_t length, uint64_t ptr_ptr,
uint64_t size_ptr) const override;
WasmResult copyFrom(size_t start, size_t length, absl::string_view data) override;
Buffer* set(const ::Envoy::Buffer::Instance* buffer_instance) {
clear();
const_buffer_instance_ = buffer_instance;
return this;
}

private:
absl::string_view data_;
const ::Envoy::Buffer::Instance* const_buffer_instance_{};
::Envoy::Buffer::Instance* buffer_instance_{};
};
Expand Down Expand Up @@ -118,6 +130,7 @@ class Context : public proxy_wasm::ContextBase,
Plugin* plugin() const;
Context* rootContext() const;
Upstream::ClusterManager& clusterManager() const;
Buffer& buffer() { return buffer_; }

// proxy_wasm::ContextBase
void error(absl::string_view message) override;
Expand Down Expand Up @@ -191,7 +204,6 @@ class Context : public proxy_wasm::ContextBase,

// General
WasmResult log(uint32_t level, absl::string_view message) override;
WasmResult setTimerPeriod(std::chrono::milliseconds tick_period, uint32_t* token) override;
uint64_t getCurrentTimeNanoseconds() override;
std::pair<uint32_t, absl::string_view> getStatus() override;

Expand Down Expand Up @@ -251,6 +263,10 @@ class Context : public proxy_wasm::ContextBase,
WasmResult grpcCancel(uint32_t token) override;
WasmResult grpcSend(uint32_t token, absl::string_view message, bool end_stream) override;

// Envoy specific ABI
void onResolveDns(uint32_t token, Envoy::Network::DnsResolver::ResolutionStatus status,
std::list<Envoy::Network::DnsResponse>&& response);

// CEL evaluation
std::vector<const google::api::expr::runtime::CelFunction*>
FindFunctionOverloads(absl::string_view) const override {
Expand Down Expand Up @@ -398,6 +414,7 @@ class Context : public proxy_wasm::ContextBase,
::Envoy::Buffer::Instance* network_upstream_data_buffer_{};

// HTTP filter state.
bool http_request_started_ = false; // When decodeHeaders() is called the rquest is "started".
jplevyak marked this conversation as resolved.
Show resolved Hide resolved
Http::RequestHeaderMap* request_headers_{};
Http::ResponseHeaderMap* response_headers_{};
::Envoy::Buffer::Instance* request_body_buffer_{};
Expand Down
Loading