aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/channel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/channel')
-rw-r--r--src/core/channel/client_channel.c28
-rw-r--r--src/core/channel/compress_filter.c2
-rw-r--r--src/core/channel/http_client_filter.c74
3 files changed, 87 insertions, 17 deletions
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
index 10e01ebbb4..c1aa580b2d 100644
--- a/src/core/channel/client_channel.c
+++ b/src/core/channel/client_channel.c
@@ -236,21 +236,6 @@ static void picked_target(void *arg, int iomgr_success) {
}
}
-static void pick_target(grpc_lb_policy *lb_policy, call_data *calld) {
- grpc_metadata_batch *initial_metadata;
- grpc_transport_stream_op *op = &calld->waiting_op;
-
- GPR_ASSERT(op->bind_pollset);
- GPR_ASSERT(op->send_ops);
- GPR_ASSERT(op->send_ops->nops >= 1);
- GPR_ASSERT(op->send_ops->ops[0].type == GRPC_OP_METADATA);
- initial_metadata = &op->send_ops->ops[0].data.metadata;
-
- grpc_iomgr_closure_init(&calld->async_setup_task, picked_target, calld);
- grpc_lb_policy_pick(lb_policy, op->bind_pollset, initial_metadata,
- &calld->picked_channel, &calld->async_setup_task);
-}
-
static grpc_iomgr_closure *merge_into_waiting_op(
grpc_call_element *elem, grpc_transport_stream_op *new_op) {
call_data *calld = elem->call_data;
@@ -358,12 +343,23 @@ static void perform_transport_stream_op(grpc_call_element *elem,
gpr_mu_lock(&chand->mu_config);
lb_policy = chand->lb_policy;
if (lb_policy) {
+ grpc_transport_stream_op *op = &calld->waiting_op;
+ grpc_pollset *bind_pollset = op->bind_pollset;
+ grpc_metadata_batch *initial_metadata = &op->send_ops->ops[0].data.metadata;
GRPC_LB_POLICY_REF(lb_policy, "pick");
gpr_mu_unlock(&chand->mu_config);
calld->state = CALL_WAITING_FOR_PICK;
+
+ GPR_ASSERT(op->bind_pollset);
+ GPR_ASSERT(op->send_ops);
+ GPR_ASSERT(op->send_ops->nops >= 1);
+ GPR_ASSERT(
+ op->send_ops->ops[0].type == GRPC_OP_METADATA);
gpr_mu_unlock(&calld->mu_state);
- pick_target(lb_policy, calld);
+ grpc_iomgr_closure_init(&calld->async_setup_task, picked_target, calld);
+ grpc_lb_policy_pick(lb_policy, bind_pollset, initial_metadata,
+ &calld->picked_channel, &calld->async_setup_task);
GRPC_LB_POLICY_UNREF(lb_policy, "pick");
} else if (chand->resolver != NULL) {
diff --git a/src/core/channel/compress_filter.c b/src/core/channel/compress_filter.c
index 9ff679df18..f656484fac 100644
--- a/src/core/channel/compress_filter.c
+++ b/src/core/channel/compress_filter.c
@@ -208,7 +208,7 @@ static void process_send_ops(grpc_call_element *elem,
calld->has_compression_algorithm = 1; /* GPR_TRUE */
}
/* hint compression algorithm */
- grpc_metadata_batch_add_head(
+ grpc_metadata_batch_add_tail(
&(sop->data.metadata), &calld->compression_algorithm_storage,
GRPC_MDELEM_REF(channeld->mdelem_compression_algorithms
[calld->compression_algorithm]));
diff --git a/src/core/channel/http_client_filter.c b/src/core/channel/http_client_filter.c
index 63e4912397..6e93103a6a 100644
--- a/src/core/channel/http_client_filter.c
+++ b/src/core/channel/http_client_filter.c
@@ -32,13 +32,17 @@
#include "src/core/channel/http_client_filter.h"
#include <string.h>
+#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include "src/core/support/string.h"
typedef struct call_data {
grpc_linked_mdelem method;
grpc_linked_mdelem scheme;
grpc_linked_mdelem te_trailers;
grpc_linked_mdelem content_type;
+ grpc_linked_mdelem user_agent;
int sent_initial_metadata;
int got_initial_metadata;
@@ -58,6 +62,8 @@ typedef struct channel_data {
grpc_mdelem *scheme;
grpc_mdelem *content_type;
grpc_mdelem *status;
+ /** complete user agent mdelem */
+ grpc_mdelem *user_agent;
} channel_data;
/* used to silence 'variable not used' warnings */
@@ -92,6 +98,18 @@ static void hc_on_recv(void *user_data, int success) {
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
}
+static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {
+ grpc_call_element *elem = user_data;
+ channel_data *channeld = elem->channel_data;
+ /* eat the things we'd like to set ourselves */
+ if (md->key == channeld->method->key) return NULL;
+ if (md->key == channeld->scheme->key) return NULL;
+ if (md->key == channeld->te_trailers->key) return NULL;
+ if (md->key == channeld->content_type->key) return NULL;
+ if (md->key == channeld->user_agent->key) return NULL;
+ return md;
+}
+
static void hc_mutate_op(grpc_call_element *elem,
grpc_transport_stream_op *op) {
/* grab pointers to our data from the call element */
@@ -105,6 +123,7 @@ static void hc_mutate_op(grpc_call_element *elem,
grpc_stream_op *op = &ops[i];
if (op->type != GRPC_OP_METADATA) continue;
calld->sent_initial_metadata = 1;
+ grpc_metadata_batch_filter(&op->data.metadata, client_strip_filter, elem);
/* Send : prefixed headers, which have to be before any application
layer headers. */
grpc_metadata_batch_add_head(&op->data.metadata, &calld->method,
@@ -115,6 +134,8 @@ static void hc_mutate_op(grpc_call_element *elem,
GRPC_MDELEM_REF(channeld->te_trailers));
grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type,
GRPC_MDELEM_REF(channeld->content_type));
+ grpc_metadata_batch_add_tail(&op->data.metadata, &calld->user_agent,
+ GRPC_MDELEM_REF(channeld->user_agent));
break;
}
}
@@ -169,6 +190,55 @@ static const char *scheme_from_args(const grpc_channel_args *args) {
return "http";
}
+static grpc_mdstr *user_agent_from_args(grpc_mdctx *mdctx,
+ const grpc_channel_args *args) {
+ gpr_strvec v;
+ size_t i;
+ int is_first = 1;
+ char *tmp;
+ grpc_mdstr *result;
+
+ gpr_strvec_init(&v);
+
+ for (i = 0; args && i < args->num_args; i++) {
+ if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) {
+ if (args->args[i].type != GRPC_ARG_STRING) {
+ gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
+ GRPC_ARG_PRIMARY_USER_AGENT_STRING);
+ } else {
+ if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
+ is_first = 0;
+ gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
+ }
+ }
+ }
+
+ gpr_asprintf(&tmp, "%sgrpc-c/%s (%s)", is_first ? "" : " ",
+ grpc_version_string(), GPR_PLATFORM_STRING);
+ is_first = 0;
+ gpr_strvec_add(&v, tmp);
+
+ for (i = 0; args && i < args->num_args; i++) {
+ if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) {
+ if (args->args[i].type != GRPC_ARG_STRING) {
+ gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
+ GRPC_ARG_SECONDARY_USER_AGENT_STRING);
+ } else {
+ if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
+ is_first = 0;
+ gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
+ }
+ }
+ }
+
+ tmp = gpr_strvec_flatten(&v, NULL);
+ gpr_strvec_destroy(&v);
+ result = grpc_mdstr_from_string(mdctx, tmp);
+ gpr_free(tmp);
+
+ return result;
+}
+
/* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx,
@@ -189,6 +259,9 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
channeld->content_type =
grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc");
channeld->status = grpc_mdelem_from_strings(mdctx, ":status", "200");
+ channeld->user_agent = grpc_mdelem_from_metadata_strings(
+ mdctx, grpc_mdstr_from_string(mdctx, "user-agent"),
+ user_agent_from_args(mdctx, args));
}
/* Destructor for channel data */
@@ -201,6 +274,7 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
GRPC_MDELEM_UNREF(channeld->scheme);
GRPC_MDELEM_UNREF(channeld->content_type);
GRPC_MDELEM_UNREF(channeld->status);
+ GRPC_MDELEM_UNREF(channeld->user_agent);
}
const grpc_channel_filter grpc_http_client_filter = {