diff options
author | 2017-03-28 10:13:07 -0700 | |
---|---|---|
committer | 2017-03-28 10:13:07 -0700 | |
commit | b6090a697b6559155ef8ac80d4343204183571d7 (patch) | |
tree | 1fffa6968d3ee46476a1106e70f3730144412bdb /src/core/lib/channel/http_client_filter.c | |
parent | 306efc787a8a224b4fc5b523fd551f402932d14e (diff) | |
parent | 739cecb0bc1f1ba3b2e0b390795cbaf429ec81c2 (diff) |
Merge github.com:grpc/grpc into new_transport_op
Diffstat (limited to 'src/core/lib/channel/http_client_filter.c')
-rw-r--r-- | src/core/lib/channel/http_client_filter.c | 125 |
1 files changed, 82 insertions, 43 deletions
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c index a0cbeaabf3..e43b97335c 100644 --- a/src/core/lib/channel/http_client_filter.c +++ b/src/core/lib/channel/http_client_filter.c @@ -36,6 +36,7 @@ #include <grpc/support/string_util.h> #include <string.h> #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/security/util/b64.h" #include "src/core/lib/slice/percent_encoding.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" @@ -56,7 +57,6 @@ typedef struct call_data { grpc_linked_mdelem te_trailers; grpc_linked_mdelem content_type; grpc_linked_mdelem user_agent; - grpc_linked_mdelem payload_bin; grpc_metadata_batch *recv_initial_metadata; grpc_metadata_batch *recv_trailing_metadata; @@ -108,11 +108,11 @@ static grpc_error *client_filter_incoming_metadata(grpc_exec_ctx *exec_ctx, grpc_error *e = grpc_error_set_str( grpc_error_set_int( grpc_error_set_str( - GRPC_ERROR_CREATE( + GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Received http2 :status header with non-200 OK status"), - GRPC_ERROR_STR_VALUE, val), + GRPC_ERROR_STR_VALUE, grpc_slice_from_copied_string(val)), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED), - GRPC_ERROR_STR_GRPC_MESSAGE, msg); + GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_copied_string(msg)); gpr_free(val); gpr_free(msg); return e; @@ -252,18 +252,13 @@ static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { } } -typedef struct hc_mutate_op_result { - grpc_error *error; - bool op_stalled; -} hc_mutate_op_result; - -static hc_mutate_op_result hc_mutate_op(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - grpc_transport_stream_op *op) { +static grpc_error *hc_mutate_op(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_transport_stream_op *op) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; - hc_mutate_op_result result = {.error = GRPC_ERROR_NONE, .op_stalled = false}; + grpc_error *error; if (op->send_initial_metadata) { /* Decide which HTTP VERB to use. We use GET if the request is marked @@ -298,23 +293,63 @@ static hc_mutate_op_result hc_mutate_op(grpc_exec_ctx *exec_ctx, calld->send_length = op->payload->send_message.send_message->length; calld->send_flags = op->payload->send_message.send_message->flags; continue_send_message(exec_ctx, elem); - result.op_stalled = true; if (calld->send_message_blocked == false) { - /* when all the send_message data is available, then create a MDELEM and - append to headers */ - grpc_mdelem payload_bin = grpc_mdelem_from_slices( - exec_ctx, GRPC_MDSTR_GRPC_PAYLOAD_BIN, - grpc_slice_from_copied_buffer( - (const char *)calld->payload_bytes, - op->payload->send_message.send_message->length)); - result.error = grpc_metadata_batch_add_tail( - exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, - &calld->payload_bin, payload_bin); - if (result.error != GRPC_ERROR_NONE) return result; + /* when all the send_message data is available, then modify the path + * MDELEM by appending base64 encoded query to the path */ + const int k_url_safe = 1; + const int k_multi_line = 0; + const unsigned char k_query_separator = '?'; + + grpc_slice path_slice = + GRPC_MDVALUE(op->payload->send_initial_metadata + .send_initial_metadata->idx.named.path->md); + /* sum up individual component's lengths and allocate enough memory to + * hold combined path+query */ + size_t estimated_len = GRPC_SLICE_LENGTH(path_slice); + estimated_len++; /* for the '?' */ + estimated_len += grpc_base64_estimate_encoded_size( + op->payload->send_message.send_message->length, k_url_safe, + k_multi_line); + estimated_len += 1; /* for the trailing 0 */ + grpc_slice path_with_query_slice = grpc_slice_malloc(estimated_len); + + /* memcopy individual pieces into this slice */ + uint8_t *write_ptr = + (uint8_t *)GRPC_SLICE_START_PTR(path_with_query_slice); + uint8_t *original_path = (uint8_t *)GRPC_SLICE_START_PTR(path_slice); + memcpy(write_ptr, original_path, GRPC_SLICE_LENGTH(path_slice)); + write_ptr += GRPC_SLICE_LENGTH(path_slice); + + *write_ptr = k_query_separator; + write_ptr++; /* for the '?' */ + + grpc_base64_encode_core((char *)write_ptr, calld->payload_bytes, + op->payload->send_message.send_message->length, + k_url_safe, k_multi_line); + + /* remove trailing unused memory and add trailing 0 to terminate string + */ + char *t = (char *)GRPC_SLICE_START_PTR(path_with_query_slice); + /* safe to use strlen since base64_encode will always add '\0' */ + size_t path_length = strlen(t) + 1; + *(t + path_length) = '\0'; + path_with_query_slice = + grpc_slice_sub(path_with_query_slice, 0, path_length); + + /* substitute previous path with the new path+query */ + grpc_mdelem mdelem_path_and_query = grpc_mdelem_from_slices( + exec_ctx, GRPC_MDSTR_PATH, path_with_query_slice); + grpc_metadata_batch *b = + op->payload->send_initial_metadata.send_initial_metadata; + error = grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path, + mdelem_path_and_query); + if (error != GRPC_ERROR_NONE) return error; + calld->on_complete = op->on_complete; op->on_complete = &calld->hc_on_complete; op->send_message = NULL; + grpc_slice_unref_internal(exec_ctx, path_with_query_slice); } else { /* Not all data is available. Fall back to POST. */ gpr_log(GPR_DEBUG, @@ -342,26 +377,26 @@ static hc_mutate_op_result hc_mutate_op(grpc_exec_ctx *exec_ctx, /* Send : prefixed headers, which have to be before any application layer headers. */ - result.error = grpc_metadata_batch_add_head( + error = grpc_metadata_batch_add_head( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->method, method); - if (result.error != GRPC_ERROR_NONE) return result; - result.error = grpc_metadata_batch_add_head( + if (error != GRPC_ERROR_NONE) return error; + error = grpc_metadata_batch_add_head( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->scheme, channeld->static_scheme); - if (result.error != GRPC_ERROR_NONE) return result; - result.error = grpc_metadata_batch_add_tail( + if (error != GRPC_ERROR_NONE) return error; + error = grpc_metadata_batch_add_tail( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->te_trailers, GRPC_MDELEM_TE_TRAILERS); - if (result.error != GRPC_ERROR_NONE) return result; - result.error = grpc_metadata_batch_add_tail( + if (error != GRPC_ERROR_NONE) return error; + error = grpc_metadata_batch_add_tail( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC); - if (result.error != GRPC_ERROR_NONE) return result; - result.error = grpc_metadata_batch_add_tail( + if (error != GRPC_ERROR_NONE) return error; + error = grpc_metadata_batch_add_tail( exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, &calld->user_agent, GRPC_MDELEM_REF(channeld->user_agent)); - if (result.error != GRPC_ERROR_NONE) return result; + if (error != GRPC_ERROR_NONE) return error; } if (op->recv_initial_metadata) { @@ -382,7 +417,7 @@ static hc_mutate_op_result hc_mutate_op(grpc_exec_ctx *exec_ctx, op->on_complete = &calld->hc_on_recv_trailing_metadata; } - return result; + return GRPC_ERROR_NONE; } static void hc_start_transport_op(grpc_exec_ctx *exec_ctx, @@ -390,14 +425,18 @@ static void hc_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op) { GPR_TIMER_BEGIN("hc_start_transport_op", 0); GRPC_CALL_LOG_OP(GPR_INFO, elem, op); - hc_mutate_op_result result = hc_mutate_op(exec_ctx, elem, op); - if (result.error != GRPC_ERROR_NONE) { - grpc_transport_stream_op_finish_with_failure(exec_ctx, op, result.error); - } else if (result.op_stalled) { - /* Don't forward the op. send_message contains slices that aren't ready yet. - The call will be forwarded by the op_complete of slice read call. */ + grpc_error *error = hc_mutate_op(exec_ctx, elem, op); + if (error != GRPC_ERROR_NONE) { + grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error); } else { - grpc_call_next_op(exec_ctx, elem, op); + call_data *calld = elem->call_data; + if (op->send_message && calld->send_message_blocked) { + /* Don't forward the op. send_message contains slices that aren't ready + yet. The call will be forwarded by the op_complete of slice read call. + */ + } else { + grpc_call_next_op(exec_ctx, elem, op); + } } GPR_TIMER_END("hc_start_transport_op", 0); } |