Skip to content

Commit

Permalink
Merge pull request #141 from kyessenov/wasm_updates
Browse files Browse the repository at this point in the history
implement expression evaluation in Wasm (#345)
  • Loading branch information
kyessenov authored Feb 6, 2020
2 parents e85398d + a0b7cbe commit cde27a5
Show file tree
Hide file tree
Showing 18 changed files with 390 additions and 0 deletions.
4 changes: 4 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ envoy_dependencies()
load("//bazel:dependency_imports.bzl", "envoy_dependency_imports")

envoy_dependency_imports()

load("@rules_antlr//antlr:deps.bzl", "antlr_dependencies")

antlr_dependencies(471)
17 changes: 17 additions & 0 deletions api/wasm/cpp/contrib/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
licenses(["notice"]) # Apache 2

load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_package",
)

envoy_package()

envoy_cc_library(
name = "contrib_lib",
hdrs = [
"proxy_expr.h",
],
)

75 changes: 75 additions & 0 deletions api/wasm/cpp/contrib/proxy_expr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Create an expression using a foreign function call.
inline WasmResult createExpression(StringView expr, uint32_t* token) {
std::string function = "expr_create";
char* out = nullptr;
size_t out_size = 0;
auto result = proxy_call_foreign_function(function.data(), function.size(), expr.data(),
expr.size(), &out, &out_size);
if (result == WasmResult::Ok && out_size == sizeof(uint32_t)) {
*token = *reinterpret_cast<uint32_t*>(out);
}
::free(out);
return result;
}

// Evaluate an expression using an expression token.
inline Optional<WasmDataPtr> exprEvaluate(uint32_t token) {
std::string function = "expr_evaluate";
char* out = nullptr;
size_t out_size = 0;
auto result = proxy_call_foreign_function(function.data(), function.size(),
reinterpret_cast<const char*>(&token), sizeof(uint32_t),
&out, &out_size);
if (result != WasmResult::Ok) {
return {};
}
return std::make_unique<WasmData>(out, out_size);
}

// Delete an expression using an expression token.
inline WasmResult exprDelete(uint32_t token) {
std::string function = "expr_delete";
char* out = nullptr;
size_t out_size = 0;
auto result = proxy_call_foreign_function(function.data(), function.size(),
reinterpret_cast<const char*>(&token), sizeof(uint32_t),
&out, &out_size);
::free(out);
return result;
}

template <typename T>
inline bool evaluateExpression(uint32_t token, T* out) {
auto buf = exprEvaluate(token);
if (!buf.has_value() || buf.value()->size() != sizeof(T)) {
return false;
}
*out = *reinterpret_cast<const T*>(buf.value()->data());
return true;
}

template <>
inline bool evaluateExpression<std::string>(uint32_t token, std::string* out) {
auto buf = exprEvaluate(token);
if (!buf.has_value()) {
return false;
}
out->assign(buf.value()->data(), buf.value()->size());
return true;
}

// Specialization for message types (including struct value for lists and maps)
template <typename T>
inline bool evaluateMessage(uint32_t token,
T* value_ptr) {
auto buf = exprEvaluate(token);
if (!buf.has_value()) {
return false;
}
if (buf.value()->size() == 0) {
// evaluates to null
return true;
}
return value_ptr->ParseFromArray(buf.value()->data(), buf.value()->size());
}

26 changes: 26 additions & 0 deletions bazel/antlr.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
diff --git a/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp b/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp
index c6cceda13..e86533759 100755
--- a/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp
+++ b/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp
@@ -104,7 +104,7 @@ void deserializeSets(

}

-ATNDeserializer::ATNDeserializer(): ATNDeserializer(ATNDeserializationOptions::getDefaultOptions()) {
+ATNDeserializer::ATNDeserializer(): ATNDeserializer(ATNDeserializationOptions()) {
}

ATNDeserializer::ATNDeserializer(const ATNDeserializationOptions& dso): deserializationOptions(dso) {
diff --git a/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp b/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp
index 827c3d59f..62914cf55 100755
--- a/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp
+++ b/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp
@@ -69,7 +69,7 @@ void LexerATNSimulator::copyState(LexerATNSimulator *simulator) {
}

size_t LexerATNSimulator::match(CharStream *input, size_t mode) {
- match_calls++;
+ // match_calls++;
_mode = mode;
ssize_t mark = input->mark();

27 changes: 27 additions & 0 deletions bazel/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,33 @@ def _net_zlib():
def _com_google_cel_cpp():
_repository_impl("com_google_cel_cpp")

# Parser dependencies
http_archive(
name = "rules_antlr",
sha256 = "7249d1569293d9b239e23c65f6b4c81a07da921738bde0dfeb231ed98be40429",
strip_prefix = "rules_antlr-3cc2f9502a54ceb7b79b37383316b23c4da66f9a",
urls = ["https://github.com/marcohu/rules_antlr/archive/3cc2f9502a54ceb7b79b37383316b23c4da66f9a.tar.gz"],
)

http_archive(
name = "antlr4_runtimes",
build_file_content = """
package(default_visibility = ["//visibility:public"])
cc_library(
name = "cpp",
srcs = glob(["runtime/Cpp/runtime/src/**/*.cpp"]),
hdrs = glob(["runtime/Cpp/runtime/src/**/*.h"]),
includes = ["runtime/Cpp/runtime/src"],
)
""",
sha256 = "4d0714f441333a63e50031c9e8e4890c78f3d21e053d46416949803e122a6574",
patch_args = ["-p1"],
# Patches ASAN violation of initialization fiasco
patches = ["@envoy//bazel:antlr.patch"],
strip_prefix = "antlr4-4.7.1",
urls = ["https://github.com/antlr/antlr4/archive/4.7.1.tar.gz"],
)

def _com_github_nghttp2_nghttp2():
location = REPOSITORY_LOCATIONS["com_github_nghttp2_nghttp2"]
http_archive(
Expand Down
4 changes: 4 additions & 0 deletions source/extensions/common/wasm/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ envoy_cc_library(
"//source/common/common:stack_array",
"//source/common/config:datasource_lib",
"//source/common/stats:stats_lib",
"//source/extensions/filters/common/expr:evaluator_lib",
"//source/extensions/filters/http:well_known_names",
"@com_google_cel_cpp//eval/public:activation",
"@envoy_api//envoy/extensions/wasm/v3:pkg_cc_proto",
Expand Down Expand Up @@ -113,8 +114,11 @@ envoy_cc_library(
"@com_google_cel_cpp//eval/eval:field_access",
"@com_google_cel_cpp//eval/eval:field_backed_list_impl",
"@com_google_cel_cpp//eval/eval:field_backed_map_impl",
"@com_google_cel_cpp//eval/public:builtin_func_registrar",
"@com_google_cel_cpp//eval/public:cel_expr_builder_factory",
"@com_google_cel_cpp//eval/public:cel_value",
"@com_google_cel_cpp//eval/public:value_export_util",
"@com_google_cel_cpp//parser",
"@envoy_api//envoy/extensions/wasm/v3:pkg_cc_proto",
],
)
29 changes: 29 additions & 0 deletions source/extensions/common/wasm/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "common/common/assert.h"
#include "common/common/logger.h"

#include "extensions/filters/common/expr/evaluator.h"

#include "eval/public/activation.h"

namespace Envoy {
Expand Down Expand Up @@ -53,6 +55,12 @@ struct Plugin {
};
using PluginSharedPtr = std::shared_ptr<Plugin>;

// Opaque context object.
class StorageObject {
public:
virtual ~StorageObject() = default;
};

// A context which will be the target of callbacks for a particular session
// e.g. a handler of a stream.
class Context : public Logger::Loggable<Logger::Id::wasm>,
Expand Down Expand Up @@ -301,6 +309,21 @@ class Context : public Logger::Loggable<Logger::Id::wasm>,
FindValue(absl::string_view name, Protobuf::Arena* arena) const override;
virtual bool IsPathUnknown(absl::string_view) const override { return false; }

// Foreign function state
virtual void setForeignData(absl::string_view data_name, std::unique_ptr<StorageObject> data) {
data_storage_[data_name] = std::move(data);
}
template <typename T> T* getForeignData(absl::string_view data_name) {
const auto& it = data_storage_.find(data_name);
if (it == data_storage_.end()) {
return nullptr;
}
return dynamic_cast<T*>(it->second.get());
}
bool hasForeignData(absl::string_view data_name) const {
return data_storage_.contains(data_name);
}

// Connection
virtual bool isSsl();

Expand Down Expand Up @@ -457,11 +480,17 @@ class Context : public Logger::Loggable<Logger::Id::wasm>,
std::map<uint32_t, AsyncClientHandler> http_request_;
std::map<uint32_t, GrpcCallClientHandler> grpc_call_request_;
std::map<uint32_t, GrpcStreamClientHandler> grpc_stream_;

// Opaque state
absl::flat_hash_map<std::string, std::unique_ptr<StorageObject>> data_storage_;
};

using ContextSharedPtr = std::shared_ptr<Context>;

uint32_t resolveQueueForTest(absl::string_view vm_id, absl::string_view queue_name);

WasmResult serializeValue(Filters::Common::Expr::CelValue value, std::string* result);

} // namespace Wasm
} // namespace Common
} // namespace Extensions
Expand Down
Loading

0 comments on commit cde27a5

Please sign in to comment.