aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/surface/call.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/surface/call.c')
-rw-r--r--src/core/surface/call.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 6a1a6cbf30..f3012d0c59 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -39,6 +39,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
#include "src/core/channel/channel_stack.h"
#include "src/core/iomgr/alarm.h"
@@ -242,6 +243,9 @@ struct grpc_call {
/* Compression algorithm for the call */
grpc_compression_algorithm compression_algorithm;
+ /* Supported encodings (compression algorithms), a bitset */
+ gpr_uint32 encodings_accepted_by_peer;
+
/* Contexts for various subsystems (security, tracing, ...). */
grpc_call_context_element context[GRPC_CONTEXT_COUNT];
@@ -532,6 +536,46 @@ grpc_compression_algorithm grpc_call_get_compression_algorithm(
return call->compression_algorithm;
}
+
+static void set_encodings_accepted_by_peer(grpc_call *call,
+ const gpr_slice accept_encoding_slice) {
+ size_t i;
+ grpc_compression_algorithm algorithm;
+ gpr_slice_buffer accept_encoding_parts;
+
+ gpr_slice_buffer_init(&accept_encoding_parts);
+ gpr_slice_split(accept_encoding_slice, ", ", &accept_encoding_parts);
+
+ /* No need to zero call->encodings_accepted_by_peer: grpc_call_create already
+ * zeroes the whole grpc_call */
+ /* Always support no compression */
+ GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
+ for (i = 0; i < accept_encoding_parts.count; i++) {
+ const gpr_slice *accept_encoding_entry_slice =
+ &accept_encoding_parts.slices[i];
+ if (grpc_compression_algorithm_parse(
+ (const char *)GPR_SLICE_START_PTR(*accept_encoding_entry_slice),
+ GPR_SLICE_LENGTH(*accept_encoding_entry_slice), &algorithm)) {
+ GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
+ } else {
+ char *accept_encoding_entry_str =
+ gpr_dump_slice(*accept_encoding_entry_slice, GPR_DUMP_ASCII);
+ gpr_log(GPR_ERROR,
+ "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
+ accept_encoding_entry_str);
+ gpr_free(accept_encoding_entry_str);
+ }
+ }
+}
+
+gpr_uint32 grpc_call_get_encodings_accepted_by_peer(grpc_call *call) {
+ return call->encodings_accepted_by_peer;
+}
+
+gpr_uint32 grpc_call_get_message_flags(const grpc_call *call) {
+ return call->incoming_message_flags;
+}
+
static void set_status_details(grpc_call *call, status_source source,
grpc_mdstr *status) {
if (call->status[source].details != NULL) {
@@ -1408,10 +1452,11 @@ static gpr_uint32 decode_compression(grpc_mdelem *md) {
void *user_data = grpc_mdelem_get_user_data(md, destroy_compression);
if (user_data) {
algorithm =
- ((grpc_compression_level)(gpr_intptr)user_data) - COMPRESS_OFFSET;
+ ((grpc_compression_algorithm)(gpr_intptr)user_data) - COMPRESS_OFFSET;
} else {
const char *md_c_str = grpc_mdstr_as_c_string(md->value);
- if (!grpc_compression_algorithm_parse(md_c_str, &algorithm)) {
+ if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
+ &algorithm)) {
gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'", md_c_str);
assert(0);
}
@@ -1440,6 +1485,9 @@ static void recv_metadata(grpc_call *call, grpc_metadata_batch *md) {
} else if (key ==
grpc_channel_get_compression_algorithm_string(call->channel)) {
set_compression_algorithm(call, decode_compression(md));
+ } else if (key == grpc_channel_get_encodings_accepted_by_peer_string(
+ call->channel)) {
+ set_encodings_accepted_by_peer(call, md->value->slice);
} else {
dest = &call->buffered_metadata[is_trailing];
if (dest->count == dest->capacity) {