diff options
author | Nicolas Noble <nnoble@google.com> | 2014-11-26 16:33:03 -0800 |
---|---|---|
committer | Nicolas Noble <nnoble@google.com> | 2014-11-26 16:33:03 -0800 |
commit | b7ebd3b8c6fe39f99c40b10c1b563e4adb607b6c (patch) | |
tree | c1decf819492d455ec81cd471942c5516138f825 /src/core/surface/channel.c | |
parent | 0e905e63db21bcdd85d3d1af051fcdc5bb5caa38 (diff) |
Initial import.
Diffstat (limited to 'src/core/surface/channel.c')
-rw-r--r-- | src/core/surface/channel.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c new file mode 100644 index 0000000000..ff994257f4 --- /dev/null +++ b/src/core/surface/channel.c @@ -0,0 +1,152 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/surface/channel.h" + +#include <stdlib.h> +#include <string.h> + +#include "src/core/surface/call.h" +#include "src/core/surface/client.h" +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> + +struct grpc_channel { + int is_client; + gpr_refcount refs; + grpc_mdctx *metadata_context; + grpc_mdstr *grpc_status_string; + grpc_mdstr *grpc_message_string; +}; + +#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c)+1)) + +grpc_channel *grpc_channel_create_from_filters( + const grpc_channel_filter **filters, size_t num_filters, + const grpc_channel_args *args, grpc_mdctx *mdctx, int is_client) { + size_t size = + sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters); + grpc_channel *channel = gpr_malloc(size); + channel->is_client = is_client; + /* decremented by grpc_channel_destroy */ + gpr_ref_init(&channel->refs, 1); + channel->metadata_context = mdctx; + channel->grpc_status_string = grpc_mdstr_from_string(mdctx, "grpc-status"); + channel->grpc_message_string = grpc_mdstr_from_string(mdctx, "grpc-message"); + grpc_channel_stack_init(filters, num_filters, args, channel->metadata_context, + CHANNEL_STACK_FROM_CHANNEL(channel)); + return channel; +} + +static void do_nothing(void *ignored, grpc_op_error error) {} + +grpc_call *grpc_channel_create_call(grpc_channel *channel, const char *method, + const char *host, + gpr_timespec absolute_deadline) { + grpc_call *call; + grpc_metadata md; + + if (!channel->is_client) { + gpr_log(GPR_ERROR, "Cannot create a call on the server."); + return NULL; + } + + call = grpc_call_create(channel, NULL); + +#define ADDMD(k, v) \ + do { \ + md.key = (k); \ + md.value = (char *)(v); \ + md.value_length = strlen((v)); \ + grpc_call_add_metadata(call, &md, 0); \ + } while (0) + ADDMD(":method", "POST"); + ADDMD(":scheme", "grpc"); + ADDMD(":path", method); + ADDMD(":authority", host); + ADDMD("content-type", "application/grpc"); + if (0 != gpr_time_cmp(absolute_deadline, gpr_inf_future)) { + grpc_call_op op; + op.type = GRPC_SEND_DEADLINE; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.data.deadline = absolute_deadline; + op.done_cb = do_nothing; + op.user_data = NULL; + grpc_call_execute_op(call, &op); + } + + return call; +} + +void grpc_channel_internal_ref(grpc_channel *channel) { + gpr_ref(&channel->refs); +} + +void grpc_channel_internal_unref(grpc_channel *channel) { + if (gpr_unref(&channel->refs)) { + grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel)); + grpc_mdstr_unref(channel->grpc_status_string); + grpc_mdstr_unref(channel->grpc_message_string); + grpc_mdctx_orphan(channel->metadata_context); + gpr_free(channel); + } +} + +void grpc_channel_destroy(grpc_channel *channel) { + grpc_channel_op op; + grpc_channel_element *elem; + + op.type = GRPC_CHANNEL_SHUTDOWN; + op.dir = GRPC_CALL_DOWN; + elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); + elem->filter->channel_op(elem, &op); + + grpc_channel_internal_unref(channel); +} + +grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel) { + return CHANNEL_STACK_FROM_CHANNEL(channel); +} + +grpc_mdctx *grpc_channel_get_metadata_context(grpc_channel *channel) { + return channel->metadata_context; +} + +grpc_mdstr *grpc_channel_get_status_string(grpc_channel *channel) { + return channel->grpc_status_string; +} + +grpc_mdstr *grpc_channel_get_message_string(grpc_channel *channel) { + return channel->grpc_message_string; +} |