aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/surface/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/surface/channel.c')
-rw-r--r--src/core/surface/channel.c152
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;
+}