Skip to content

Commit

Permalink
bridge: rename envoy_headers to envoy_map for generalized usage (#1295)
Browse files Browse the repository at this point in the history
Description: introduce `envoy_data_map_entry` and `envoy_data_map` to be reused. the first and existing use case is `envoy_headers`. this pr updated utility methods to match the newly introduced data structure(s).

Risk Level: medium
Testing: unit, ci
Co-authored-by:Jose Nino <jnino@lyft.com>
Signed-off-by: Jingwei Hao <jingwei.hao@gmail.com>
Signed-off-by: JP Simard <jp@jpsim.com>
  • Loading branch information
jingwei99 authored and jpsim committed Nov 28, 2022
1 parent cdbd4cf commit b485732
Show file tree
Hide file tree
Showing 13 changed files with 154 additions and 147 deletions.
14 changes: 7 additions & 7 deletions mobile/library/cc/bridge_utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,31 @@ envoy_headers raw_header_map_as_envoy_headers(const RawHeaderMap& headers) {
header_count += pair.second.size();
}

envoy_header* headers_list =
static_cast<envoy_header*>(safe_malloc(sizeof(envoy_header) * header_count));
envoy_map_entry* headers_list =
static_cast<envoy_map_entry*>(safe_malloc(sizeof(envoy_map_entry) * header_count));

size_t i = 0;
for (const auto& pair : headers) {
const auto& key = pair.first;
for (const auto& value : pair.second) {
envoy_header& header = headers_list[i++];
envoy_map_entry& header = headers_list[i++];
header.key = string_as_envoy_data(key);
header.value = string_as_envoy_data(value);
}
}

envoy_headers raw_headers{
.length = static_cast<envoy_header_size_t>(header_count),
.headers = headers_list,
.length = static_cast<envoy_map_size_t>(header_count),
.entries = headers_list,
};
return raw_headers;
}

RawHeaderMap envoy_headers_as_raw_headers(envoy_headers raw_headers) {
RawHeaderMap headers;
for (auto i = 0; i < raw_headers.length; i++) {
auto key = envoy_data_as_string(raw_headers.headers[i].key);
auto value = envoy_data_as_string(raw_headers.headers[i].value);
auto key = envoy_data_as_string(raw_headers.entries[i].key);
auto value = envoy_data_as_string(raw_headers.entries[i].value);

if (!headers.contains(key)) {
headers.emplace(key, std::vector<std::string>());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ namespace HttpFilters {
namespace PlatformBridge {

namespace {
// TODO: https://github.com/envoyproxy/envoy-mobile/issues/1287
void replaceHeaders(Http::HeaderMap& headers, envoy_headers c_headers) {
headers.clear();
for (envoy_header_size_t i = 0; i < c_headers.length; i++) {
headers.addCopy(Http::LowerCaseString(Http::Utility::convertToString(c_headers.headers[i].key)),
Http::Utility::convertToString(c_headers.headers[i].value));
for (envoy_map_size_t i = 0; i < c_headers.length; i++) {
headers.addCopy(Http::LowerCaseString(Http::Utility::convertToString(c_headers.entries[i].key)),
Http::Utility::convertToString(c_headers.entries[i].value));
}
// The C envoy_headers struct can be released now because the headers have been copied.
release_envoy_headers(c_headers);
Expand Down Expand Up @@ -172,7 +173,7 @@ Http::FilterHeadersStatus PlatformBridgeFilter::FilterBase::onHeaders(Http::Head
case kEnvoyFilterHeadersStatusStopIteration:
pending_headers_ = &headers;
iteration_state_ = IterationState::Stopped;
ASSERT(result.headers.length == 0 && result.headers.headers == NULL);
ASSERT(result.headers.length == 0 && result.headers.entries == NULL);
return Http::FilterHeadersStatus::StopIteration;

default:
Expand Down Expand Up @@ -298,7 +299,7 @@ Http::FilterTrailersStatus PlatformBridgeFilter::FilterBase::onTrailers(Http::He
case kEnvoyFilterTrailersStatusStopIteration:
pending_trailers_ = &trailers;
iteration_state_ = IterationState::Stopped;
ASSERT(result.trailers.length == 0 && result.trailers.headers == NULL);
ASSERT(result.trailers.length == 0 && result.trailers.entries == NULL);
return Http::FilterTrailersStatus::StopIteration;

// Resume previously-stopped iteration, possibly forwarding headers and data if iteration was
Expand Down
20 changes: 10 additions & 10 deletions mobile/library/common/http/header_utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ std::string convertToString(envoy_data s) {

RequestHeaderMapPtr toRequestHeaders(envoy_headers headers) {
RequestHeaderMapPtr transformed_headers = RequestHeaderMapImpl::create();
for (envoy_header_size_t i = 0; i < headers.length; i++) {
transformed_headers->addCopy(LowerCaseString(convertToString(headers.headers[i].key)),
convertToString(headers.headers[i].value));
for (envoy_map_size_t i = 0; i < headers.length; i++) {
transformed_headers->addCopy(LowerCaseString(convertToString(headers.entries[i].key)),
convertToString(headers.entries[i].value));
}
// The C envoy_headers struct can be released now because the headers have been copied.
release_envoy_headers(headers);
Expand All @@ -23,21 +23,21 @@ RequestHeaderMapPtr toRequestHeaders(envoy_headers headers) {

RequestTrailerMapPtr toRequestTrailers(envoy_headers trailers) {
RequestTrailerMapPtr transformed_trailers = RequestTrailerMapImpl::create();
for (envoy_header_size_t i = 0; i < trailers.length; i++) {
transformed_trailers->addCopy(LowerCaseString(convertToString(trailers.headers[i].key)),
convertToString(trailers.headers[i].value));
for (envoy_map_size_t i = 0; i < trailers.length; i++) {
transformed_trailers->addCopy(LowerCaseString(convertToString(trailers.entries[i].key)),
convertToString(trailers.entries[i].value));
}
// The C envoy_headers struct can be released now because the headers have been copied.
release_envoy_headers(trailers);
return transformed_trailers;
}

envoy_headers toBridgeHeaders(const HeaderMap& header_map) {
envoy_header* headers =
static_cast<envoy_header*>(safe_malloc(sizeof(envoy_header) * header_map.size()));
envoy_map_entry* headers =
static_cast<envoy_map_entry*>(safe_malloc(sizeof(envoy_map_entry) * header_map.size()));
envoy_headers transformed_headers;
transformed_headers.length = 0;
transformed_headers.headers = headers;
transformed_headers.entries = headers;

header_map.iterate([&transformed_headers](const HeaderEntry& header) -> HeaderMap::Iterate {
const absl::string_view header_key = header.key().getStringView();
Expand All @@ -48,7 +48,7 @@ envoy_headers toBridgeHeaders(const HeaderMap& header_map) {
envoy_data value =
copy_envoy_data(header_value.size(), reinterpret_cast<const uint8_t*>(header_value.data()));

transformed_headers.headers[transformed_headers.length] = {key, value};
transformed_headers.entries[transformed_headers.length] = {key, value};
transformed_headers.length++;

return HeaderMap::Iterate::Continue;
Expand Down
10 changes: 5 additions & 5 deletions mobile/library/common/jni/jni_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,29 +144,29 @@ static void pass_headers(const char* method, envoy_headers headers, jobject j_co
jmethodID jmid_passHeader = env->GetMethodID(jcls_JvmCallbackContext, method, "([B[BZ)V");
jboolean start_headers = JNI_TRUE;

for (envoy_header_size_t i = 0; i < headers.length; i++) {
for (envoy_map_size_t i = 0; i < headers.length; i++) {
// Note this is just an initial implementation, and we will pass a more optimized structure in
// the future.

// Note the JNI function NewStringUTF would appear to be an appealing option here, except it
// requires a null-terminated *modified* UTF-8 string.

// Create platform byte array for header key
jbyteArray key = env->NewByteArray(headers.headers[i].key.length);
jbyteArray key = env->NewByteArray(headers.entries[i].key.length);
// TODO: check if copied via isCopy.
// TODO: check for NULL.
// https://github.com/lyft/envoy-mobile/issues/758
void* critical_key = env->GetPrimitiveArrayCritical(key, nullptr);
memcpy(critical_key, headers.headers[i].key.bytes, headers.headers[i].key.length);
memcpy(critical_key, headers.entries[i].key.bytes, headers.entries[i].key.length);
// Here '0' (for which there is no named constant) indicates we want to commit the changes back
// to the JVM and free the c array, where applicable.
env->ReleasePrimitiveArrayCritical(key, critical_key, 0);

// Create platform byte array for header value
jbyteArray value = env->NewByteArray(headers.headers[i].value.length);
jbyteArray value = env->NewByteArray(headers.entries[i].value.length);
// TODO: check for NULL.
void* critical_value = env->GetPrimitiveArrayCritical(value, nullptr);
memcpy(critical_value, headers.headers[i].value.bytes, headers.headers[i].value.length);
memcpy(critical_value, headers.entries[i].value.bytes, headers.entries[i].value.length);
env->ReleasePrimitiveArrayCritical(value, critical_value, 0);

// Pass this header pair to the platform
Expand Down
14 changes: 7 additions & 7 deletions mobile/library/common/jni/jni_utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,23 +94,23 @@ envoy_data* buffer_to_native_data_ptr(JNIEnv* env, jobject j_data) {
return nullptr;
}

envoy_data* native_data = static_cast<envoy_data*>(safe_malloc(sizeof(envoy_header)));
envoy_data* native_data = static_cast<envoy_data*>(safe_malloc(sizeof(envoy_map_entry)));
*native_data = buffer_to_native_data(env, j_data);
return native_data;
}

envoy_headers to_native_headers(JNIEnv* env, jobjectArray headers) {
// Note that headers is a flattened array of key/value pairs.
// Therefore, the length of the native header array is n envoy_data or n/2 envoy_header.
envoy_header_size_t length = env->GetArrayLength(headers);
// Therefore, the length of the native header array is n envoy_data or n/2 envoy_map_entry.
envoy_map_size_t length = env->GetArrayLength(headers);
if (length == 0) {
return envoy_noheaders;
}

envoy_header* header_array =
static_cast<envoy_header*>(safe_malloc(sizeof(envoy_header) * length / 2));
envoy_map_entry* header_array =
static_cast<envoy_map_entry*>(safe_malloc(sizeof(envoy_map_entry) * length / 2));

for (envoy_header_size_t i = 0; i < length; i += 2) {
for (envoy_map_size_t i = 0; i < length; i += 2) {
// Copy native byte array for header key
jbyteArray j_key = static_cast<jbyteArray>(env->GetObjectArrayElement(headers, i));
size_t key_length = env->GetArrayLength(j_key);
Expand Down Expand Up @@ -148,7 +148,7 @@ envoy_headers* to_native_headers_ptr(JNIEnv* env, jobjectArray headers) {
return nullptr;
}

envoy_headers* native_headers = static_cast<envoy_headers*>(safe_malloc(sizeof(envoy_header)));
envoy_headers* native_headers = static_cast<envoy_headers*>(safe_malloc(sizeof(envoy_map_entry)));
*native_headers = to_native_headers(env, headers);
return native_headers;
}
34 changes: 19 additions & 15 deletions mobile/library/common/types/c_types.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,32 @@ void* safe_calloc(size_t count, size_t size) {

void envoy_noop_release(void* context) { (void)context; }

void release_envoy_headers(envoy_headers headers) {
for (envoy_header_size_t i = 0; i < headers.length; i++) {
envoy_header header = headers.headers[i];
header.key.release(header.key.context);
header.value.release(header.value.context);
void release_envoy_data_map(envoy_map map) {
for (envoy_map_size_t i = 0; i < map.length; i++) {
envoy_map_entry entry = map.entries[i];
entry.key.release(entry.key.context);
entry.value.release(entry.value.context);
}
free(headers.headers);
free(map.entries);
}

envoy_headers copy_envoy_headers(envoy_headers src) {
envoy_header* dst_header_array =
static_cast<envoy_header*>(safe_malloc(sizeof(envoy_header) * src.length));
for (envoy_header_size_t i = 0; i < src.length; i++) {
envoy_header new_header = {
copy_envoy_data(src.headers[i].key.length, src.headers[i].key.bytes),
copy_envoy_data(src.headers[i].value.length, src.headers[i].value.bytes)};
dst_header_array[i] = new_header;
void release_envoy_headers(envoy_headers headers) { release_envoy_data_map(headers); }

envoy_map copy_envoy_data_map(envoy_map src) {
envoy_map_entry* dst_entries =
static_cast<envoy_map_entry*>(safe_malloc(sizeof(envoy_map_entry) * src.length));
for (envoy_map_size_t i = 0; i < src.length; i++) {
envoy_map_entry new_entry = {
copy_envoy_data(src.entries[i].key.length, src.entries[i].key.bytes),
copy_envoy_data(src.entries[i].value.length, src.entries[i].value.bytes)};
dst_entries[i] = new_entry;
}
envoy_headers dst = {src.length, dst_header_array};
envoy_map dst = {src.length, dst_entries};
return dst;
}

envoy_headers copy_envoy_headers(envoy_headers src) { return copy_envoy_data_map(src); }

envoy_data copy_envoy_data(size_t length, const uint8_t* src_bytes) {
uint8_t* dst_bytes = static_cast<uint8_t*>(safe_malloc(sizeof(uint8_t) * length));
memcpy(dst_bytes, src_bytes, length);
Expand Down
22 changes: 12 additions & 10 deletions mobile/library/common/types/c_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,28 +87,30 @@ typedef struct {
} envoy_data;

/**
* Holds a single key/value header.
* Holds a single key/value pair.
*/
typedef struct {
envoy_data key;
// Multiple header values for the same header key are supported via a comma-delimited string.
envoy_data value;
} envoy_header;
} envoy_map_entry;

/**
* Consistent type for dealing with encodable/processable header counts.
*/
typedef int envoy_header_size_t;
typedef int envoy_map_size_t;

/**
* Holds an HTTP header map as an array of envoy_header structs.
* Holds a map as an array of envoy_map_entry structs.
*/
typedef struct {
// Number of header elements in the array.
envoy_header_size_t length;
// Array of headers.
envoy_header* headers;
} envoy_headers;
// Number of entries in the array.
envoy_map_size_t length;
// Array of map entries.
envoy_map_entry* entries;
} envoy_map;

// Multiple header values for the same header key are supported via a comma-delimited string.
typedef envoy_map envoy_headers;

#ifdef __cplusplus
extern "C" { // utility functions
Expand Down
14 changes: 7 additions & 7 deletions mobile/library/objective-c/EnvoyBridgeUtility.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ static inline envoy_headers toNativeHeaders(EnvoyHeaders *headers) {
return envoy_noheaders;
}

envoy_header_size_t length = 0;
envoy_map_size_t length = 0;
for (NSString *headerKey in headers) {
length += [headers[headerKey] count];
}
envoy_header *header_array = (envoy_header *)safe_malloc(sizeof(envoy_header) * length);
envoy_header_size_t header_index = 0;
envoy_map_entry *header_array = (envoy_map_entry *)safe_malloc(sizeof(envoy_map_entry) * length);
envoy_map_size_t header_index = 0;
for (id headerKey in headers) {
NSArray *headerList = headers[headerKey];
for (NSString *headerValue in headerList) {
envoy_header new_header = {toManagedNativeString(headerKey),
toManagedNativeString(headerValue)};
envoy_map_entry new_header = {toManagedNativeString(headerKey),
toManagedNativeString(headerValue)};
header_array[header_index++] = new_header;
}
}
Expand Down Expand Up @@ -75,8 +75,8 @@ static inline NSData *to_ios_data(envoy_data data) {

static inline EnvoyHeaders *to_ios_headers(envoy_headers headers) {
NSMutableDictionary *headerDict = [NSMutableDictionary new];
for (envoy_header_size_t i = 0; i < headers.length; i++) {
envoy_header header = headers.headers[i];
for (envoy_map_size_t i = 0; i < headers.length; i++) {
envoy_map_entry header = headers.entries[i];
NSString *headerKey = [[NSString alloc] initWithBytes:header.key.bytes
length:header.key.length
encoding:NSUTF8StringEncoding];
Expand Down
Loading

0 comments on commit b485732

Please sign in to comment.