Skip to content

Commit

Permalink
Return error codes for WebAssembly metadata operations. (istio#99)
Browse files Browse the repository at this point in the history
Signed-off-by: John Plevyak <jplevyak@gmail.com>
  • Loading branch information
jplevyak authored Jul 31, 2019
1 parent eb31a25 commit 73234ef
Show file tree
Hide file tree
Showing 10 changed files with 2,111 additions and 2,939 deletions.
8 changes: 8 additions & 0 deletions api/wasm/cpp/proxy_wasm_enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,11 @@ enum class MetricType : EnumType {
Gauge = 1,
Histogram = 2,
};
enum class MetadataResult : EnumType {
Ok = 0,
StructNotFound = 1,
FieldNotFound = 2,
SerializationFailure = 3,
BadType = 4,
ParseFailure = 5,
};
20 changes: 10 additions & 10 deletions api/wasm/cpp/proxy_wasm_externs.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,16 @@ extern "C" uint32_t proxy_getDestinationPort(StreamType type);
extern "C" uint32_t proxy_getResponseCode(StreamType type);

// Metadata
extern "C" void proxy_getMetadata(MetadataType type, const char* key_ptr, size_t key_size,
const char** value_ptr_ptr, size_t* value_size_ptr);
extern "C" void proxy_setMetadata(MetadataType type, const char* key_ptr, size_t key_size,
const char* value_ptr, size_t value_size);
extern "C" void proxy_getMetadataPairs(MetadataType type, const char** value_ptr,
size_t* value_size);
extern "C" void proxy_getMetadataStruct(MetadataType type, const char* name_ptr, size_t name_size,
const char** value_ptr_ptr, size_t* value_size_ptr);
extern "C" void proxy_setMetadataStruct(MetadataType type, const char* name_ptr, size_t name_size,
const char* value_ptr, size_t value_size);
extern "C" uint32_t proxy_getMetadata(MetadataType type, const char* key_ptr, size_t key_size,
const char** value_ptr_ptr, size_t* value_size_ptr);
extern "C" uint32_t proxy_setMetadata(MetadataType type, const char* key_ptr, size_t key_size,
const char* value_ptr, size_t value_size);
extern "C" uint32_t proxy_getMetadataPairs(MetadataType type, const char** value_ptr,
size_t* value_size);
extern "C" uint32_t proxy_getMetadataStruct(MetadataType type, const char* name_ptr, size_t name_size,
const char** value_ptr_ptr, size_t* value_size_ptr);
extern "C" uint32_t proxy_setMetadataStruct(MetadataType type, const char* name_ptr, size_t name_size,
const char* value_ptr, size_t value_size);

// Continue/Reply/Route
extern "C" void proxy_continueRequest();
Expand Down
284 changes: 164 additions & 120 deletions api/wasm/cpp/proxy_wasm_impl.h

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion source/extensions/common/wasm/null/null.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ using FilterDataStatus = Http::FilterDataStatus;
using GrpcStatus = Envoy::Grpc::Status::GrpcStatus;
using MetricType = Envoy::Extensions::Common::Wasm::Context::MetricType;
using StringView = absl::string_view;
using EnumType = uint32_t;
using EnumType = int32_t;
} // namespace Plugin
} // namespace Null
} // namespace Wasm
Expand Down
45 changes: 23 additions & 22 deletions source/extensions/common/wasm/null/wasm_api_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,29 @@ inline uint32_t proxy_getResponseCode(StreamType type) {
}

// Metadata
inline void proxy_getMetadata(MetadataType type, const char* key_ptr, size_t key_size,
const char** value_ptr_ptr, size_t* value_size_ptr) {
getMetadataHandler(current_context_, WS(type), WR(key_ptr), WS(key_size), WR(value_ptr_ptr),
WR(value_size_ptr));
}
inline void proxy_setMetadata(MetadataType type, const char* key_ptr, size_t key_size,
const char* value_ptr, size_t value_size) {
setMetadataHandler(current_context_, WS(type), WR(key_ptr), WS(key_size), WR(value_ptr),
WS(value_size));
}
inline void proxy_getMetadataPairs(MetadataType type, const char** value_ptr, size_t* value_size) {
getMetadataPairsHandler(current_context_, WS(type), WR(value_ptr), WR(value_size));
}
inline void proxy_getMetadataStruct(MetadataType type, const char* name_ptr, size_t name_size,
const char** value_ptr_ptr, size_t* value_size_ptr) {
getMetadataStructHandler(current_context_, WS(type), WR(name_ptr), WS(name_size),
WR(value_ptr_ptr), WR(value_size_ptr));
}
inline void proxy_setMetadataStruct(MetadataType type, const char* name_ptr, size_t name_size,
const char* value_ptr, size_t value_size) {
setMetadataStructHandler(current_context_, WS(type), WR(name_ptr), WS(name_size), WR(value_ptr),
WS(value_size));
inline uint64_t proxy_getMetadata(MetadataType type, const char* key_ptr, size_t key_size,
const char** value_ptr_ptr, size_t* value_size_ptr) {
return getMetadataHandler(current_context_, WS(type), WR(key_ptr), WS(key_size),
WR(value_ptr_ptr), WR(value_size_ptr));
}
inline uint64_t proxy_setMetadata(MetadataType type, const char* key_ptr, size_t key_size,
const char* value_ptr, size_t value_size) {
return setMetadataHandler(current_context_, WS(type), WR(key_ptr), WS(key_size), WR(value_ptr),
WS(value_size));
}
inline uint64_t proxy_getMetadataPairs(MetadataType type, const char** value_ptr,
size_t* value_size) {
return getMetadataPairsHandler(current_context_, WS(type), WR(value_ptr), WR(value_size));
}
inline uint64_t proxy_getMetadataStruct(MetadataType type, const char* name_ptr, size_t name_size,
const char** value_ptr_ptr, size_t* value_size_ptr) {
return getMetadataStructHandler(current_context_, WS(type), WR(name_ptr), WS(name_size),
WR(value_ptr_ptr), WR(value_size_ptr));
}
inline uint64_t proxy_setMetadataStruct(MetadataType type, const char* name_ptr, size_t name_size,
const char* value_ptr, size_t value_size) {
return setMetadataStructHandler(current_context_, WS(type), WR(name_ptr), WS(name_size),
WR(value_ptr), WS(value_size));
}

// Continue
Expand Down
108 changes: 62 additions & 46 deletions source/extensions/common/wasm/wasm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -365,59 +365,64 @@ uint32_t getResponseCodeHandler(void* raw_context, Word type) {
}

// Metadata
void getMetadataHandler(void* raw_context, Word type, Word key_ptr, Word key_size,
Word getMetadataHandler(void* raw_context, Word type, Word key_ptr, Word key_size,
Word value_ptr_ptr, Word value_size_ptr) {
if (type > static_cast<int>(MetadataType::MAX)) {
return;
return Word(static_cast<uint64_t>(MetadataResult::BadType));
}
auto context = WASM_CONTEXT(raw_context);
context->wasm()->copyToPointerSize(
context->getMetadata(static_cast<MetadataType>(type.u64),
context->wasmVm()->getMemory(key_ptr, key_size)),
value_ptr_ptr, value_size_ptr);
std::string value;
auto result = context->getMetadata(static_cast<MetadataType>(type.u64),
context->wasmVm()->getMemory(key_ptr, key_size), &value);
context->wasm()->copyToPointerSize(value, value_ptr_ptr, value_size_ptr);
return Word(static_cast<uint64_t>(result));
}

void setMetadataHandler(void* raw_context, Word type, Word key_ptr, Word key_size, Word value_ptr,
Word setMetadataHandler(void* raw_context, Word type, Word key_ptr, Word key_size, Word value_ptr,
Word value_size) {
if (type > static_cast<int>(MetadataType::MAX)) {
return;
return Word(static_cast<uint64_t>(MetadataResult::BadType));
}
auto context = WASM_CONTEXT(raw_context);
context->setMetadata(static_cast<MetadataType>(type.u64),
context->wasmVm()->getMemory(key_ptr, key_size),
context->wasmVm()->getMemory(value_ptr, value_size));
return Word(static_cast<uint64_t>(context->setMetadata(
static_cast<MetadataType>(type.u64), context->wasmVm()->getMemory(key_ptr, key_size),
context->wasmVm()->getMemory(value_ptr, value_size))));
}

void getMetadataPairsHandler(void* raw_context, Word type, Word ptr_ptr, Word size_ptr) {
Word getMetadataPairsHandler(void* raw_context, Word type, Word ptr_ptr, Word size_ptr) {
if (type > static_cast<int>(MetadataType::MAX)) {
return;
return Word(static_cast<uint64_t>(MetadataResult::BadType));
}
auto context = WASM_CONTEXT(raw_context);
getPairs(context, context->getMetadataPairs(static_cast<MetadataType>(type.u64)), ptr_ptr,
size_ptr);
PairsWithStringValues pairs;
auto result = context->getMetadataPairs(static_cast<MetadataType>(type.u64), &pairs);
getPairs(context, pairs, ptr_ptr, size_ptr);
return Word(static_cast<uint64_t>(result));
}

void getMetadataStructHandler(void* raw_context, Word type, Word name_ptr, Word name_size,
Word getMetadataStructHandler(void* raw_context, Word type, Word name_ptr, Word name_size,
Word value_ptr_ptr, Word value_size_ptr) {
if (type > static_cast<int>(MetadataType::MAX)) {
return;
return Word(static_cast<uint64_t>(MetadataResult::BadType));
}
auto context = WASM_CONTEXT(raw_context);
context->wasm()->copyToPointerSize(
std::string value;
auto result =
context->getMetadataStruct(static_cast<MetadataType>(type.u64),
context->wasmVm()->getMemory(name_ptr, name_size)),
value_ptr_ptr, value_size_ptr);
context->wasmVm()->getMemory(name_ptr, name_size), &value);
context->wasm()->copyToPointerSize(value, value_ptr_ptr, value_size_ptr);
return Word(static_cast<uint64_t>(result));
}

void setMetadataStructHandler(void* raw_context, Word type, Word name_ptr, Word name_size,
Word setMetadataStructHandler(void* raw_context, Word type, Word name_ptr, Word name_size,
Word value_ptr, Word value_size) {
if (type > static_cast<int>(MetadataType::MAX)) {
return;
return Word(static_cast<uint64_t>(MetadataResult::BadType));
}
auto context = WASM_CONTEXT(raw_context);
context->setMetadataStruct(static_cast<MetadataType>(type.u64),
context->wasmVm()->getMemory(name_ptr, name_size),
context->wasmVm()->getMemory(value_ptr, value_size));
return Word(static_cast<uint64_t>(context->setMetadataStruct(
static_cast<MetadataType>(type.u64), context->wasmVm()->getMemory(name_ptr, name_size),
context->wasmVm()->getMemory(value_ptr, value_size))));
}

// Continue/Reply/Route
Expand Down Expand Up @@ -1305,69 +1310,80 @@ const ProtobufWkt::Struct* Context::getMetadataStructProto(MetadataType type,
}
}

std::string Context::getMetadata(MetadataType type, absl::string_view key) {
MetadataResult Context::getMetadata(MetadataType type, absl::string_view key,
std::string* result_ptr) {
auto proto_struct = getMetadataStructProto(type);
if (!proto_struct) {
return "";
return MetadataResult::StructNotFound;
}
auto it = proto_struct->fields().find(std::string(key));
if (it == proto_struct->fields().end()) {
return "";
return MetadataResult::FieldNotFound;
}
std::string result;
it->second.SerializeToString(&result);
return result;
if (!it->second.SerializeToString(&result)) {
return MetadataResult::SerializationFailure;
}
*result_ptr = result;
return MetadataResult::Ok;
}

void Context::setMetadata(MetadataType type, absl::string_view key,
absl::string_view serialized_proto_struct) {
MetadataResult Context::setMetadata(MetadataType type, absl::string_view key,
absl::string_view serialized_proto_struct) {
auto streamInfo = getStreamInfo(type);
if (!streamInfo) {
return;
return MetadataResult::StructNotFound;
}
streamInfo->setDynamicMetadata(
HttpFilters::HttpFilterNames::get().Wasm,
MessageUtil::keyValueStruct(std::string(key), std::string(serialized_proto_struct)));
return MetadataResult::Ok;
}

PairsWithStringValues Context::getMetadataPairs(MetadataType type) {
MetadataResult Context::getMetadataPairs(MetadataType type, PairsWithStringValues* result_ptr) {
auto proto_struct = getMetadataStructProto(type);
if (!proto_struct) {
return {};
return MetadataResult::StructNotFound;
}
PairsWithStringValues result;
for (auto& p : proto_struct->fields()) {
std::string value;
p.second.SerializeToString(&value);
if (!p.second.SerializeToString(&value)) {
return MetadataResult::SerializationFailure;
}
result.emplace_back(p.first, std::move(value));
}
return result;
*result_ptr = result;
return MetadataResult::Ok;
}

std::string Context::getMetadataStruct(MetadataType type, absl::string_view name) {
MetadataResult Context::getMetadataStruct(MetadataType type, absl::string_view name,
std::string* result_ptr) {
auto proto_struct = getMetadataStructProto(type, name);
if (!proto_struct) {
return "";
return MetadataResult::StructNotFound;
}
std::string result;
if (proto_struct->SerializeToString(&result)) {
return result;
if (!proto_struct->SerializeToString(&result)) {
return MetadataResult::SerializationFailure;
}
return "";
*result_ptr = result;
return MetadataResult::Ok;
}

void Context::setMetadataStruct(MetadataType type, absl::string_view name,
absl::string_view serialized_proto_struct) {
MetadataResult Context::setMetadataStruct(MetadataType type, absl::string_view name,
absl::string_view serialized_proto_struct) {
auto streamInfo = getStreamInfo(type);
if (!streamInfo) {
return;
return MetadataResult::StructNotFound;
}
ProtobufWkt::Struct proto_struct;
if (!proto_struct.ParseFromArray(serialized_proto_struct.data(),
serialized_proto_struct.size())) {
return;
return MetadataResult::ParseFailure;
}
streamInfo->setDynamicMetadata(std::string(name), proto_struct);
return MetadataResult::Ok;
}

void Context::scriptLog(spdlog::level::level_enum level, absl::string_view message) {
Expand Down
41 changes: 25 additions & 16 deletions source/extensions/common/wasm/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ using WasmCallback_m = uint64_t (*)(void*);
using WasmCallback_mW = uint64_t (*)(void*, Word);
using WasmCallback_jW = uint32_t (*)(void*, Word);

// Sadly we don't have enum class inheritance in c++-14.
enum class StreamType : uint32_t { Request = 0, Response = 1, MAX = 1 };
enum class MetadataType : uint32_t {
// These need to match those in api/wasm/cpp/proxy_wasm_enums.h
enum class StreamType : int32_t { Request = 0, Response = 1, MAX = 1 };
enum class MetadataType : int32_t {
Request = 0,
Response = 1,
RequestRoute = 2,
Expand All @@ -158,7 +158,7 @@ enum class MetadataType : uint32_t {
Cluster = 7,
MAX = 7
};
enum class HeaderMapType : uint32_t {
enum class HeaderMapType : int32_t {
RequestHeaders = 0,
RequestTrailers = 1,
ResponseHeaders = 2,
Expand All @@ -168,20 +168,28 @@ enum class HeaderMapType : uint32_t {
GrpcReceiveTrailingMetadata = 6,
MAX = 6,
};
enum class MetadataResult : int32_t {
Ok = 0,
StructNotFound = 1,
FieldNotFound = 2,
SerializationFailure = 3,
BadType = 4,
ParseFailure = 5,
};

// Handlers for functions exported from envoy to wasm.
void logHandler(void* raw_context, Word level, Word address, Word size);
void getProtocolHandler(void* raw_context, Word type, Word value_ptr_ptr, Word value_size_ptr);
uint32_t getDestinationPortHandler(void* raw_context, Word type);
uint32_t getResponseCodeHandler(void* raw_context, Word type);
void getMetadataHandler(void* raw_context, Word type, Word key_ptr, Word key_size,
Word getMetadataHandler(void* raw_context, Word type, Word key_ptr, Word key_size,
Word value_ptr_ptr, Word value_size_ptr);
void setMetadataHandler(void* raw_context, Word type, Word key_ptr, Word key_size, Word value_ptr,
Word setMetadataHandler(void* raw_context, Word type, Word key_ptr, Word key_size, Word value_ptr,
Word value_size);
void getMetadataPairsHandler(void* raw_context, Word type, Word ptr_ptr, Word size_ptr);
void getMetadataStructHandler(void* raw_context, Word type, Word name_ptr, Word name_size,
Word getMetadataPairsHandler(void* raw_context, Word type, Word ptr_ptr, Word size_ptr);
Word getMetadataStructHandler(void* raw_context, Word type, Word name_ptr, Word name_size,
Word value_ptr_ptr, Word value_size_ptr);
void setMetadataStructHandler(void* raw_context, Word type, Word name_ptr, Word name_size,
Word setMetadataStructHandler(void* raw_context, Word type, Word name_ptr, Word name_size,
Word value_ptr, Word value_size);
void continueRequestHandler(void* raw_context);
void continueResponseHandler(void* raw_context);
Expand Down Expand Up @@ -382,15 +390,16 @@ class Context : public Http::StreamFilter,
// Metadata
// When used with MetadataType::Request/Response refers to metadata with name "envoy.wasm": the
// values are serialized ProtobufWkt::Struct Value
virtual std::string getMetadata(MetadataType type, absl::string_view key);
virtual void setMetadata(MetadataType type, absl::string_view key,
absl::string_view serialized_proto_struct);
virtual PairsWithStringValues getMetadataPairs(MetadataType type);
virtual MetadataResult getMetadata(MetadataType type, absl::string_view key, std::string* result);
virtual MetadataResult setMetadata(MetadataType type, absl::string_view key,
absl::string_view serialized_proto_struct);
virtual MetadataResult getMetadataPairs(MetadataType type, PairsWithStringValues* result);
// Name is ignored when the type is not MetadataType::Request/Response: the values are serialized
// ProtobufWkt::Struct
virtual std::string getMetadataStruct(MetadataType type, absl::string_view name);
virtual void setMetadataStruct(MetadataType type, absl::string_view key,
absl::string_view serialized_proto_struct);
virtual MetadataResult getMetadataStruct(MetadataType type, absl::string_view name,
std::string* result);
virtual MetadataResult setMetadataStruct(MetadataType type, absl::string_view key,
absl::string_view serialized_proto_struct);

// Continue
virtual void continueRequest() {
Expand Down
Loading

0 comments on commit 73234ef

Please sign in to comment.