aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2015-05-08 09:41:16 -0700
committerGravatar Craig Tiller <ctiller@google.com>2015-05-08 09:41:16 -0700
commita7af3f8854e132e32d2417bec9d5de1cb4646d72 (patch)
tree171b44f1ec2777334dd1ac000abeb7c10af2e3c5 /src/core
parent0a2bb1d9d6e41ca7e911523baaf4dfb7973487b2 (diff)
parent72a96463f689748c7b63c9f39f92d33e87e87315 (diff)
Merge github.com:grpc/grpc into we-dont-need-no-backup
Diffstat (limited to 'src/core')
-rw-r--r--src/core/surface/call.c41
-rw-r--r--src/core/transport/chttp2_transport.c6
-rw-r--r--src/core/transport/metadata.c16
-rw-r--r--src/core/transport/metadata.h3
4 files changed, 56 insertions, 10 deletions
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 7ab9142947..f3658b56c4 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -711,6 +711,10 @@ static void call_on_done_recv(void *pc, int success) {
break;
}
}
+ if (!success) {
+ grpc_stream_ops_unref_owned_objects(&call->recv_ops.ops[i],
+ call->recv_ops.nops - i);
+ }
if (call->recv_state == GRPC_STREAM_RECV_CLOSED) {
GPR_ASSERT(call->read_state <= READ_STATE_READ_CLOSED);
call->read_state = READ_STATE_READ_CLOSED;
@@ -739,14 +743,9 @@ static void call_on_done_recv(void *pc, int success) {
GRPC_TIMER_BEGIN(GRPC_PTAG_CALL_ON_DONE_RECV, 0);
}
-static grpc_mdelem_list chain_metadata_from_app(grpc_call *call, size_t count,
- grpc_metadata *metadata) {
+static int prepare_application_metadata(grpc_call *call, size_t count,
+ grpc_metadata *metadata) {
size_t i;
- grpc_mdelem_list out;
- if (count == 0) {
- out.head = out.tail = NULL;
- return out;
- }
for (i = 0; i < count; i++) {
grpc_metadata *md = &metadata[i];
grpc_metadata *next_md = (i == count - 1) ? NULL : &metadata[i + 1];
@@ -756,9 +755,27 @@ static grpc_mdelem_list chain_metadata_from_app(grpc_call *call, size_t count,
l->md = grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key,
(const gpr_uint8 *)md->value,
md->value_length);
+ if (!grpc_mdstr_is_legal_header(l->md->key)) {
+ gpr_log(GPR_ERROR, "attempt to send invalid metadata key");
+ return 0;
+ } else if (!grpc_mdstr_is_bin_suffixed(l->md->key) &&
+ !grpc_mdstr_is_legal_header(l->md->value)) {
+ gpr_log(GPR_ERROR, "attempt to send invalid metadata value");
+ return 0;
+ }
l->next = next_md ? (grpc_linked_mdelem *)&next_md->internal_data : NULL;
l->prev = prev_md ? (grpc_linked_mdelem *)&prev_md->internal_data : NULL;
}
+ return 1;
+}
+
+static grpc_mdelem_list chain_metadata_from_app(grpc_call *call, size_t count,
+ grpc_metadata *metadata) {
+ grpc_mdelem_list out;
+ if (count == 0) {
+ out.head = out.tail = NULL;
+ return out;
+ }
out.head = (grpc_linked_mdelem *)&(metadata[0].internal_data);
out.tail = (grpc_linked_mdelem *)&(metadata[count - 1].internal_data);
return out;
@@ -954,8 +971,16 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
} else if (call->request_set[op] == REQSET_DONE) {
return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_ALREADY_INVOKED);
}
- have_ops |= 1u << op;
data = reqs[i].data;
+ if (op == GRPC_IOREQ_SEND_INITIAL_METADATA ||
+ op == GRPC_IOREQ_SEND_TRAILING_METADATA) {
+ if (!prepare_application_metadata(call, data.send_metadata.count,
+ data.send_metadata.metadata)) {
+ return start_ioreq_error(call, have_ops,
+ GRPC_CALL_ERROR_INVALID_METADATA);
+ }
+ }
+ have_ops |= 1u << op;
call->request_data[op] = data;
call->request_set[op] = set;
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index ea24796f35..a6f9f782a1 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -1927,8 +1927,10 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices,
break;
case GRPC_ENDPOINT_CB_OK:
lock(t);
- for (i = 0; i < nslices && process_read(t, slices[i]); i++)
- ;
+ if (t->cb) {
+ for (i = 0; i < nslices && process_read(t, slices[i]); i++)
+ ;
+ }
unlock(t);
keep_reading = 1;
break;
diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c
index 74e94b2c24..c80d67823f 100644
--- a/src/core/transport/metadata.c
+++ b/src/core/transport/metadata.c
@@ -569,3 +569,19 @@ void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, grpc_mdelem *gmd) {
}
void grpc_mdctx_unlock(grpc_mdctx *ctx) { unlock(ctx); }
+
+int grpc_mdstr_is_legal_header(grpc_mdstr *s) {
+ /* TODO(ctiller): consider caching this, or computing it on construction */
+ const gpr_uint8 *p = GPR_SLICE_START_PTR(s->slice);
+ const gpr_uint8 *e = GPR_SLICE_END_PTR(s->slice);
+ for (; p != e; p++) {
+ if (*p < 32 || *p > 126) return 0;
+ }
+ return 1;
+}
+
+int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s) {
+ /* TODO(ctiller): consider caching this */
+ return grpc_is_binary_header((const char *)GPR_SLICE_START_PTR(s->slice),
+ GPR_SLICE_LENGTH(s->slice));
+}
diff --git a/src/core/transport/metadata.h b/src/core/transport/metadata.h
index 21b8ae2b78..e7508718f5 100644
--- a/src/core/transport/metadata.h
+++ b/src/core/transport/metadata.h
@@ -135,6 +135,9 @@ void grpc_mdelem_unref(grpc_mdelem *md);
Does not promise that the returned string has no embedded nulls however. */
const char *grpc_mdstr_as_c_string(grpc_mdstr *s);
+int grpc_mdstr_is_legal_header(grpc_mdstr *s);
+int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s);
+
/* Batch mode metadata functions.
These API's have equivalents above, but allow taking the mdctx just once,
performing a bunch of work, and then leaving the mdctx. */