aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Muxi Yan <mxyan@google.com>2018-02-14 17:17:58 -0800
committerGravatar Muxi Yan <mxyan@google.com>2018-02-14 17:54:09 -0800
commitefc5ae8008d8778d98a98616df5e5367e44babb6 (patch)
tree3ea9e7cd042896d23300b9885f4f77a79327113b /src
parent874f8128cde90bccf5979d49f83f8e8cf2b81bd1 (diff)
Add binary metadata support for cronet transport
Diffstat (limited to 'src')
-rw-r--r--src/core/ext/transport/cronet/transport/cronet_transport.cc65
-rw-r--r--src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm3
2 files changed, 55 insertions, 13 deletions
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc
index 8904c122a7..283417bcbe 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.cc
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc
@@ -24,6 +24,8 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
+#include "src/core/ext/transport/chttp2/transport/bin_decoder.h"
+#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
#include "src/core/ext/transport/cronet/transport/cronet_transport.h"
#include "src/core/lib/gpr/host_port.h"
@@ -214,6 +216,26 @@ void grpc_cronet_stream_unref(stream_obj* s) { grpc_stream_unref(s->refcount); }
static enum e_op_result execute_stream_op(struct op_and_state* oas);
+static const size_t tail_xtra[4] = {0, 0, 1, 2};
+
+static size_t infer_length_after_decode(const grpc_slice& slice) {
+ size_t len = GRPC_SLICE_LENGTH(slice);
+ const uint8_t* bytes = GRPC_SLICE_START_PTR(slice);
+ while (len > 0 && bytes[len - 1] == '=') {
+ len--;
+ }
+ size_t tuples = len / 4;
+ size_t tail_case = len % 4;
+ if (tail_case == 1) {
+ gpr_log(GPR_ERROR,
+ "Base64 decoding failed. Input has a length of %zu (withou "
+ "padding), which is invalid.\n",
+ len);
+ tail_case = 0;
+ }
+ return tuples * 3 + tail_xtra[tail_case];
+}
+
/*
Utility function to translate enum into string for printing
*/
@@ -518,14 +540,21 @@ static void on_response_headers_received(
grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.initial_metadata,
s->arena);
for (size_t i = 0; i < headers->count; i++) {
+ grpc_slice key = grpc_slice_intern(
+ grpc_slice_from_static_string(headers->headers[i].key));
+ grpc_slice value;
+ if (grpc_is_binary_header(key)) {
+ value = grpc_slice_from_static_string(headers->headers[i].value);
+ value = grpc_slice_intern(grpc_chttp2_base64_decode_with_length(
+ value, infer_length_after_decode(value)));
+ } else {
+ value = grpc_slice_intern(
+ grpc_slice_from_static_string(headers->headers[i].value));
+ }
GRPC_LOG_IF_ERROR("on_response_headers_received",
grpc_chttp2_incoming_metadata_buffer_add(
&s->state.rs.initial_metadata,
- grpc_mdelem_from_slices(
- grpc_slice_intern(grpc_slice_from_static_string(
- headers->headers[i].key)),
- grpc_slice_intern(grpc_slice_from_static_string(
- headers->headers[i].value)))));
+ grpc_mdelem_from_slices(key, value)));
}
s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true;
if (!(s->state.state_op_done[OP_CANCEL_ERROR] ||
@@ -624,14 +653,21 @@ static void on_response_trailers_received(
for (size_t i = 0; i < trailers->count; i++) {
CRONET_LOG(GPR_DEBUG, "trailer key=%s, value=%s", trailers->headers[i].key,
trailers->headers[i].value);
+ grpc_slice key = grpc_slice_intern(
+ grpc_slice_from_static_string(trailers->headers[i].key));
+ grpc_slice value;
+ if (grpc_is_binary_header(key)) {
+ value = grpc_slice_from_static_string(trailers->headers[i].value);
+ value = grpc_slice_intern(grpc_chttp2_base64_decode_with_length(
+ value, infer_length_after_decode(value)));
+ } else {
+ value = grpc_slice_intern(
+ grpc_slice_from_static_string(trailers->headers[i].value));
+ }
GRPC_LOG_IF_ERROR("on_response_trailers_received",
grpc_chttp2_incoming_metadata_buffer_add(
&s->state.rs.trailing_metadata,
- grpc_mdelem_from_slices(
- grpc_slice_intern(grpc_slice_from_static_string(
- trailers->headers[i].key)),
- grpc_slice_intern(grpc_slice_from_static_string(
- trailers->headers[i].value)))));
+ grpc_mdelem_from_slices(key, value)));
s->state.rs.trailing_metadata_valid = true;
if (0 == strcmp(trailers->headers[i].key, "grpc-status") &&
0 != strcmp(trailers->headers[i].value, "0")) {
@@ -721,7 +757,14 @@ static void convert_metadata_to_cronet_headers(
grpc_mdelem mdelem = curr->md;
curr = curr->next;
char* key = grpc_slice_to_c_string(GRPC_MDKEY(mdelem));
- char* value = grpc_slice_to_c_string(GRPC_MDVALUE(mdelem));
+ char* value;
+ if (grpc_is_binary_header(GRPC_MDKEY(mdelem))) {
+ grpc_slice wire_value = grpc_chttp2_base64_encode(GRPC_MDVALUE(mdelem));
+ value = grpc_slice_to_c_string(wire_value);
+ grpc_slice_unref(wire_value);
+ } else {
+ value = grpc_slice_to_c_string(GRPC_MDVALUE(mdelem));
+ }
if (grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_SCHEME) ||
grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_AUTHORITY)) {
/* Cronet populates these fields on its own */
diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm
index d91b5cf99e..33ccdb5844 100644
--- a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm
+++ b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm
@@ -224,8 +224,7 @@ static char *roots_filename;
}
- (void)testBinaryMetadata {
- // NOT SUPPORTED
- //[self testIndividualCase:(char *)"binary_metadata"];
+ [self testIndividualCase:(char *)"binary_metadata"];
}
- (void)testCallCreds {