aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/channel/http_client_filter.c
diff options
context:
space:
mode:
authorGravatar Makdharma <makarandd@google.com>2016-08-26 13:34:54 -0700
committerGravatar Makdharma <makarandd@google.com>2016-08-26 13:34:54 -0700
commit7f0abf313f88ca1c3a05c7810614f41855e72734 (patch)
tree19f3a580545ba38cad30823d9ecc446fa51882d6 /src/core/lib/channel/http_client_filter.c
parent6a523f0a0361e7cd9dcdf0ff31f375e306247a1c (diff)
correctly free up memory for payload_bin
Diffstat (limited to 'src/core/lib/channel/http_client_filter.c')
-rw-r--r--src/core/lib/channel/http_client_filter.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
index f127e3a964..fe11fdaf2b 100644
--- a/src/core/lib/channel/http_client_filter.c
+++ b/src/core/lib/channel/http_client_filter.c
@@ -57,10 +57,12 @@ typedef struct call_data {
/** Closure to call when finished with the hc_on_recv hook */
grpc_closure *on_done_recv;
+ grpc_closure *on_complete;
/** Receive closures are chained: we inject this closure as the on_done_recv
up-call on transport_op, and remember to call our on_done_recv member
after handling it. */
grpc_closure hc_on_recv;
+ grpc_closure hc_on_complete;
} call_data;
typedef struct channel_data {
@@ -122,6 +124,17 @@ static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, error);
}
+static void hc_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
+ grpc_error *error) {
+ grpc_call_element *elem = user_data;
+ call_data *calld = elem->call_data;
+ if (calld->payload_bytes) {
+ gpr_free(calld->payload_bytes);
+ calld->payload_bytes = NULL;
+ }
+ calld->on_complete->cb(exec_ctx, calld->on_complete->cb_arg, error);
+}
+
static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {
/* eat the things we'd like to set ourselves */
if (md->key == GRPC_MDSTR_METHOD) return NULL;
@@ -154,9 +167,12 @@ static void hc_mutate_op(grpc_call_element *elem,
gpr_slice slice;
gpr_slice_buffer slices;
gpr_slice_buffer_init(&slices);
+ /* allocate memory to hold the entire payload */
calld->payload_bytes = gpr_malloc(op->send_message->length);
+ GPR_ASSERT(calld->payload_bytes);
uint8_t *wrptr = calld->payload_bytes;
+ /* copy payload from slices into payload_bytes. It gets freed in op_complete*/
while (grpc_byte_stream_next(NULL, op->send_message, &slice, ~(size_t)0, NULL)) {
memcpy(wrptr, GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice));
wrptr += GPR_SLICE_LENGTH(slice);
@@ -197,6 +213,11 @@ static void hc_mutate_op(grpc_call_element *elem,
calld->on_done_recv = op->recv_initial_metadata_ready;
op->recv_initial_metadata_ready = &calld->hc_on_recv;
}
+
+ if (op->on_complete != NULL) {
+ calld->on_complete = op->on_complete;
+ op->on_complete = &calld->hc_on_complete;
+ }
}
static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
@@ -215,7 +236,10 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element_args *args) {
call_data *calld = elem->call_data;
calld->on_done_recv = NULL;
+ calld->on_complete = NULL;
+ calld->payload_bytes = NULL;
grpc_closure_init(&calld->hc_on_recv, hc_on_recv, elem);
+ grpc_closure_init(&calld->hc_on_complete, hc_on_complete, elem);
return GRPC_ERROR_NONE;
}