aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c85
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_settings.c45
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_settings.h30
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_encoder.c101
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_encoder.h15
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_parser.c26
-rw-r--r--src/core/ext/transport/chttp2/transport/http2_settings.c75
-rw-r--r--src/core/ext/transport/chttp2/transport/http2_settings.h74
-rw-r--r--src/core/ext/transport/chttp2/transport/writing.c36
-rw-r--r--src/core/ext/transport/cronet/transport/cronet_transport.c3
-rw-r--r--src/core/lib/channel/message_size_filter.c4
-rw-r--r--src/core/lib/iomgr/resolve_address_uv.c3
-rw-r--r--src/core/lib/iomgr/sockaddr_utils.c4
-rw-r--r--src/core/lib/slice/slice.c6
-rw-r--r--src/core/lib/transport/pid_controller.c1
-rw-r--r--src/cpp/util/error_details.cc62
-rw-r--r--src/csharp/Grpc.Auth/project.json35
-rw-r--r--src/csharp/Grpc.Core.Testing/project.json39
-rw-r--r--src/csharp/Grpc.HealthCheck/project.json35
-rw-r--r--src/csharp/Grpc.Reflection/project.json35
-rw-r--r--src/node/ext/call.cc85
-rw-r--r--src/node/ext/call.h9
-rw-r--r--src/node/ext/call_credentials.cc2
-rw-r--r--src/node/ext/channel.cc2
-rw-r--r--src/node/ext/node_grpc.cc12
-rw-r--r--src/node/ext/server.cc4
-rw-r--r--src/node/ext/server_uv.cc3
-rw-r--r--src/objective-c/tests/InteropTests.m9
-rw-r--r--src/proto/grpc/status/BUILD43
-rw-r--r--src/proto/grpc/status/README2
-rw-r--r--src/proto/grpc/status/status.proto92
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py1
32 files changed, 653 insertions, 325 deletions
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index e2816b0e04..a7d047d6e7 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -356,6 +356,8 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
DEFAULT_WINDOW);
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
DEFAULT_MAX_HEADER_LIST_SIZE);
+ push_setting(exec_ctx, t,
+ GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, 1);
t->ping_policy = (grpc_chttp2_repeated_ping_policy){
.max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA,
@@ -486,26 +488,31 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_setting_id setting_id;
grpc_integer_options integer_options;
bool availability[2] /* server, client */;
- } settings_map[] = {{GRPC_ARG_MAX_CONCURRENT_STREAMS,
- GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
- {-1, 0, INT32_MAX},
- {true, false}},
- {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
- GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
- {-1, 0, INT32_MAX},
- {true, true}},
- {GRPC_ARG_MAX_METADATA_SIZE,
- GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
- {-1, 0, INT32_MAX},
- {true, true}},
- {GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
- GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
- {-1, 16384, 16777215},
- {true, true}},
- {GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES,
- GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
- {-1, 5, INT32_MAX},
- {true, true}}};
+ } settings_map[] = {
+ {GRPC_ARG_MAX_CONCURRENT_STREAMS,
+ GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
+ {-1, 0, INT32_MAX},
+ {true, false}},
+ {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
+ GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
+ {-1, 0, INT32_MAX},
+ {true, true}},
+ {GRPC_ARG_MAX_METADATA_SIZE,
+ GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
+ {-1, 0, INT32_MAX},
+ {true, true}},
+ {GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
+ GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
+ {-1, 16384, 16777215},
+ {true, true}},
+ {GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY,
+ GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA,
+ {1, 0, 1},
+ {true, true}},
+ {GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES,
+ GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
+ {-1, 5, INT32_MAX},
+ {true, true}}};
for (j = 0; j < (int)GPR_ARRAY_SIZE(settings_map); j++) {
if (0 == strcmp(channel_args->args[i].key,
settings_map[j].channel_arg_name)) {
@@ -1890,6 +1897,7 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_slice hdr;
grpc_slice status_hdr;
grpc_slice http_status_hdr;
+ grpc_slice content_type_hdr;
grpc_slice message_pfx;
uint8_t *p;
uint32_t len = 0;
@@ -1923,6 +1931,42 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
*p++ = '0';
GPR_ASSERT(p == GRPC_SLICE_END_PTR(http_status_hdr));
len += (uint32_t)GRPC_SLICE_LENGTH(http_status_hdr);
+
+ content_type_hdr = grpc_slice_malloc(31);
+ p = GRPC_SLICE_START_PTR(content_type_hdr);
+ *p++ = 0x00;
+ *p++ = 12;
+ *p++ = 'c';
+ *p++ = 'o';
+ *p++ = 'n';
+ *p++ = 't';
+ *p++ = 'e';
+ *p++ = 'n';
+ *p++ = 't';
+ *p++ = '-';
+ *p++ = 't';
+ *p++ = 'y';
+ *p++ = 'p';
+ *p++ = 'e';
+ *p++ = 16;
+ *p++ = 'a';
+ *p++ = 'p';
+ *p++ = 'p';
+ *p++ = 'l';
+ *p++ = 'i';
+ *p++ = 'c';
+ *p++ = 'a';
+ *p++ = 't';
+ *p++ = 'i';
+ *p++ = 'o';
+ *p++ = 'n';
+ *p++ = '/';
+ *p++ = 'g';
+ *p++ = 'r';
+ *p++ = 'p';
+ *p++ = 'c';
+ GPR_ASSERT(p == GRPC_SLICE_END_PTR(content_type_hdr));
+ len += (uint32_t)GRPC_SLICE_LENGTH(content_type_hdr);
}
status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10));
@@ -1992,6 +2036,7 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_slice_buffer_add(&t->qbuf, hdr);
if (!s->sent_initial_metadata) {
grpc_slice_buffer_add(&t->qbuf, http_status_hdr);
+ grpc_slice_buffer_add(&t->qbuf, content_type_hdr);
}
grpc_slice_buffer_add(&t->qbuf, status_hdr);
grpc_slice_buffer_add(&t->qbuf, message_pfx);
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.c b/src/core/ext/transport/chttp2/transport/frame_settings.c
index 16881c0707..4f2b827832 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.c
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.c
@@ -46,29 +46,6 @@
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/transport/http2_errors.h"
-#define MAX_MAX_HEADER_LIST_SIZE (1024 * 1024 * 1024)
-
-/* HTTP/2 mandated initial connection settings */
-const grpc_chttp2_setting_parameters
- grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = {
- {NULL, 0, 0, 0, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
- GRPC_HTTP2_PROTOCOL_ERROR},
- {"HEADER_TABLE_SIZE", 4096, 0, 0xffffffff,
- GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
- {"ENABLE_PUSH", 1, 0, 1, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
- GRPC_HTTP2_PROTOCOL_ERROR},
- {"MAX_CONCURRENT_STREAMS", 0xffffffffu, 0, 0xffffffffu,
- GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
- {"INITIAL_WINDOW_SIZE", 65535, 0, 0x7fffffffu,
- GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
- GRPC_HTTP2_FLOW_CONTROL_ERROR},
- {"MAX_FRAME_SIZE", 16384, 16384, 16777215,
- GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
- {"MAX_HEADER_LIST_SIZE", MAX_MAX_HEADER_LIST_SIZE, 0,
- MAX_MAX_HEADER_LIST_SIZE, GRPC_CHTTP2_CLAMP_INVALID_VALUE,
- GRPC_HTTP2_PROTOCOL_ERROR},
-};
-
static uint8_t *fill_header(uint8_t *out, uint32_t length, uint8_t flags) {
*out++ = (uint8_t)(length >> 16);
*out++ = (uint8_t)(length >> 8);
@@ -98,9 +75,8 @@ grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new,
for (i = 0; i < count; i++) {
if (new[i] != old[i] || (force_mask & (1u << i)) != 0) {
- GPR_ASSERT(i);
- *p++ = (uint8_t)(i >> 8);
- *p++ = (uint8_t)(i);
+ *p++ = (uint8_t)(grpc_setting_id_to_wire_id[i] >> 8);
+ *p++ = (uint8_t)(grpc_setting_id_to_wire_id[i]);
*p++ = (uint8_t)(new[i] >> 24);
*p++ = (uint8_t)(new[i] >> 16);
*p++ = (uint8_t)(new[i] >> 8);
@@ -154,6 +130,7 @@ grpc_error *grpc_chttp2_settings_parser_parse(grpc_exec_ctx *exec_ctx, void *p,
const uint8_t *cur = GRPC_SLICE_START_PTR(slice);
const uint8_t *end = GRPC_SLICE_END_PTR(slice);
char *msg;
+ grpc_chttp2_setting_id id;
if (parser->is_ack) {
return GRPC_ERROR_NONE;
@@ -216,9 +193,9 @@ grpc_error *grpc_chttp2_settings_parser_parse(grpc_exec_ctx *exec_ctx, void *p,
parser->value |= *cur;
cur++;
- if (parser->id > 0 && parser->id < GRPC_CHTTP2_NUM_SETTINGS) {
+ if (grpc_wire_id_to_setting_id(parser->id, &id)) {
const grpc_chttp2_setting_parameters *sp =
- &grpc_chttp2_settings_parameters[parser->id];
+ &grpc_chttp2_settings_parameters[id];
if (parser->value < sp->min_value || parser->value > sp->max_value) {
switch (sp->invalid_value_behavior) {
case GRPC_CHTTP2_CLAMP_INVALID_VALUE:
@@ -237,19 +214,19 @@ grpc_error *grpc_chttp2_settings_parser_parse(grpc_exec_ctx *exec_ctx, void *p,
return err;
}
}
- if (parser->id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
- parser->incoming_settings[parser->id] != parser->value) {
+ if (id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
+ parser->incoming_settings[id] != parser->value) {
t->initial_window_update +=
- (int64_t)parser->value - parser->incoming_settings[parser->id];
+ (int64_t)parser->value - parser->incoming_settings[id];
if (grpc_http_trace) {
gpr_log(GPR_DEBUG, "adding %d for initial_window change",
(int)t->initial_window_update);
}
}
- parser->incoming_settings[parser->id] = parser->value;
+ parser->incoming_settings[id] = parser->value;
if (grpc_http_trace) {
- gpr_log(GPR_DEBUG, "CHTTP2:%s:%s: got setting %d = %d",
- t->is_client ? "CLI" : "SVR", t->peer_string, parser->id,
+ gpr_log(GPR_DEBUG, "CHTTP2:%s:%s: got setting %s = %d",
+ t->is_client ? "CLI" : "SVR", t->peer_string, sp->name,
parser->value);
}
} else if (grpc_http_trace) {
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.h b/src/core/ext/transport/chttp2/transport/frame_settings.h
index 44137798c0..2a85d0dba7 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.h
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.h
@@ -37,6 +37,7 @@
#include <grpc/slice.h>
#include <grpc/support/port_platform.h>
#include "src/core/ext/transport/chttp2/transport/frame.h"
+#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
#include "src/core/lib/iomgr/exec_ctx.h"
typedef enum {
@@ -48,17 +49,6 @@ typedef enum {
GRPC_CHTTP2_SPS_VAL3
} grpc_chttp2_settings_parse_state;
-/* The things HTTP/2 defines as connection level settings */
-typedef enum {
- GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE = 1,
- GRPC_CHTTP2_SETTINGS_ENABLE_PUSH = 2,
- GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 3,
- GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 4,
- GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE = 5,
- GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 6,
- GRPC_CHTTP2_NUM_SETTINGS
-} grpc_chttp2_setting_id;
-
typedef struct {
grpc_chttp2_settings_parse_state state;
uint32_t *target_settings;
@@ -68,24 +58,6 @@ typedef struct {
uint32_t incoming_settings[GRPC_CHTTP2_NUM_SETTINGS];
} grpc_chttp2_settings_parser;
-typedef enum {
- GRPC_CHTTP2_CLAMP_INVALID_VALUE,
- GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE
-} grpc_chttp2_invalid_value_behavior;
-
-typedef struct {
- const char *name;
- uint32_t default_value;
- uint32_t min_value;
- uint32_t max_value;
- grpc_chttp2_invalid_value_behavior invalid_value_behavior;
- uint32_t error_value;
-} grpc_chttp2_setting_parameters;
-
-/* HTTP/2 mandated connection setting parameters */
-extern const grpc_chttp2_setting_parameters
- grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
-
/* Create a settings frame by diffing old & new, and updating old to be new */
grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *newval,
uint32_t force_mask, size_t count);
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
index 84586cd998..b1bc677a7a 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
@@ -86,6 +86,7 @@ typedef struct {
grpc_transport_one_way_stats *stats;
/* maximum size of a frame */
size_t max_frame_size;
+ bool use_true_binary_metadata;
} framer_state;
/* fills p (which is expected to be 9 bytes long) with a data frame header */
@@ -290,86 +291,113 @@ static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index,
len);
}
-static grpc_slice get_wire_value(grpc_mdelem elem, uint8_t *huffman_prefix) {
+typedef struct {
+ grpc_slice data;
+ uint8_t huffman_prefix;
+ bool insert_null_before_wire_value;
+} wire_value;
+
+static wire_value get_wire_value(grpc_mdelem elem, bool true_binary_enabled) {
if (grpc_is_binary_header(GRPC_MDKEY(elem))) {
- *huffman_prefix = 0x80;
- return grpc_chttp2_base64_encode_and_huffman_compress(GRPC_MDVALUE(elem));
+ if (true_binary_enabled) {
+ return (wire_value){
+ .huffman_prefix = 0x00,
+ .insert_null_before_wire_value = true,
+ .data = grpc_slice_ref_internal(GRPC_MDVALUE(elem)),
+ };
+ } else {
+ return (wire_value){
+ .huffman_prefix = 0x80,
+ .insert_null_before_wire_value = false,
+ .data = grpc_chttp2_base64_encode_and_huffman_compress(
+ GRPC_MDVALUE(elem)),
+ };
+ }
+ } else {
+ /* TODO(ctiller): opportunistically compress non-binary headers */
+ return (wire_value){
+ .huffman_prefix = 0x00,
+ .insert_null_before_wire_value = false,
+ .data = grpc_slice_ref_internal(GRPC_MDVALUE(elem)),
+ };
}
- /* TODO(ctiller): opportunistically compress non-binary headers */
- *huffman_prefix = 0x00;
- return grpc_slice_ref_internal(GRPC_MDVALUE(elem));
+}
+
+static size_t wire_value_length(wire_value v) {
+ return GPR_SLICE_LENGTH(v.data) + v.insert_null_before_wire_value;
+}
+
+static void add_wire_value(framer_state *st, wire_value v) {
+ if (v.insert_null_before_wire_value) *add_tiny_header_data(st, 1) = 0;
+ add_header_data(st, v.data);
}
static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
uint32_t key_index, grpc_mdelem elem,
framer_state *st) {
uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2);
- uint8_t huffman_prefix;
- grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
- size_t len_val = GRPC_SLICE_LENGTH(value_slice);
+ wire_value value = get_wire_value(elem, st->use_true_binary_metadata);
+ size_t len_val = wire_value_length(value);
uint32_t len_val_len;
GPR_ASSERT(len_val <= UINT32_MAX);
len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1);
GRPC_CHTTP2_WRITE_VARINT(key_index, 2, 0x40,
add_tiny_header_data(st, len_pfx), len_pfx);
- GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
+ GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, value.huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len);
- add_header_data(st, value_slice);
+ add_wire_value(st, value);
}
static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
uint32_t key_index, grpc_mdelem elem,
framer_state *st) {
uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4);
- uint8_t huffman_prefix;
- grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
- size_t len_val = GRPC_SLICE_LENGTH(value_slice);
+ wire_value value = get_wire_value(elem, st->use_true_binary_metadata);
+ size_t len_val = wire_value_length(value);
uint32_t len_val_len;
GPR_ASSERT(len_val <= UINT32_MAX);
len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1);
GRPC_CHTTP2_WRITE_VARINT(key_index, 4, 0x00,
add_tiny_header_data(st, len_pfx), len_pfx);
- GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
+ GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, value.huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len);
- add_header_data(st, value_slice);
+ add_wire_value(st, value);
}
static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
grpc_mdelem elem, framer_state *st) {
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
- uint8_t huffman_prefix;
- grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
- uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice);
+ wire_value value = get_wire_value(elem, st->use_true_binary_metadata);
+ uint32_t len_val = (uint32_t)wire_value_length(value);
uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
GPR_ASSERT(len_key <= UINT32_MAX);
- GPR_ASSERT(GRPC_SLICE_LENGTH(value_slice) <= UINT32_MAX);
+ GPR_ASSERT(wire_value_length(value) <= UINT32_MAX);
*add_tiny_header_data(st, 1) = 0x40;
GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
add_tiny_header_data(st, len_key_len), len_key_len);
add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
- GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
+ GRPC_CHTTP2_WRITE_VARINT(len_val, 1, value.huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len);
- add_header_data(st, value_slice);
+ add_wire_value(st, value);
}
static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
grpc_mdelem elem, framer_state *st) {
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
- uint8_t huffman_prefix;
- grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
- uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice);
+ wire_value value = get_wire_value(elem, st->use_true_binary_metadata);
+ uint32_t len_val = (uint32_t)wire_value_length(value);
uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
GPR_ASSERT(len_key <= UINT32_MAX);
- GPR_ASSERT(GRPC_SLICE_LENGTH(value_slice) <= UINT32_MAX);
+ GPR_ASSERT(wire_value_length(value) <= UINT32_MAX);
*add_tiny_header_data(st, 1) = 0x00;
GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
add_tiny_header_data(st, len_key_len), len_key_len);
add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
- GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
+ GRPC_CHTTP2_WRITE_VARINT(len_val, 1, value.huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len);
- add_header_data(st, value_slice);
+ add_wire_value(st, value);
}
static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c,
@@ -595,23 +623,22 @@ void grpc_chttp2_hpack_compressor_set_max_table_size(
void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c,
- uint32_t stream_id,
- grpc_metadata_batch *metadata, int is_eof,
- size_t max_frame_size,
- grpc_transport_one_way_stats *stats,
+ grpc_metadata_batch *metadata,
+ const grpc_encode_header_options *options,
grpc_slice_buffer *outbuf) {
framer_state st;
grpc_linked_mdelem *l;
gpr_timespec deadline;
- GPR_ASSERT(stream_id != 0);
+ GPR_ASSERT(options->stream_id != 0);
st.seen_regular_header = 0;
- st.stream_id = stream_id;
+ st.stream_id = options->stream_id;
st.output = outbuf;
st.is_first_frame = 1;
- st.stats = stats;
- st.max_frame_size = max_frame_size;
+ st.stats = options->stats;
+ st.max_frame_size = options->max_frame_size;
+ st.use_true_binary_metadata = options->use_true_binary_metadata;
/* Encode a metadata batch; store the returned values, representing
a metadata element that needs to be unreffed back into the metadata
@@ -630,5 +657,5 @@ void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx,
deadline_enc(exec_ctx, c, deadline, &st);
}
- finish_frame(&st, 1, is_eof);
+ finish_frame(&st, 1, options->is_eof);
}
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.h b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
index 83ba5b1b3e..6ce3209604 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
@@ -90,11 +90,18 @@ void grpc_chttp2_hpack_compressor_set_max_table_size(
void grpc_chttp2_hpack_compressor_set_max_usable_size(
grpc_chttp2_hpack_compressor *c, uint32_t max_table_size);
+typedef struct {
+ uint32_t stream_id;
+ bool is_eof;
+ bool use_true_binary_metadata;
+ size_t max_frame_size;
+ grpc_transport_one_way_stats *stats;
+} grpc_encode_header_options;
+
void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx,
- grpc_chttp2_hpack_compressor *c, uint32_t id,
- grpc_metadata_batch *metadata, int is_eof,
- size_t max_frame_size,
- grpc_transport_one_way_stats *stats,
+ grpc_chttp2_hpack_compressor *c,
+ grpc_metadata_batch *metadata,
+ const grpc_encode_header_options *options,
grpc_slice_buffer *outbuf);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_H */
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c
index 5099d736bf..1846a85fc6 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c
@@ -38,11 +38,6 @@
#include <stddef.h>
#include <string.h>
-/* This is here for grpc_is_binary_header
- * TODO(murgatroid99): Remove this
- */
-#include <grpc/grpc.h>
-
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
@@ -55,13 +50,11 @@
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/http2_errors.h"
-/* TODO(ctiller): remove before submission */
-#include "src/core/lib/slice/slice_string_helpers.h"
-
extern int grpc_http_trace;
typedef enum {
NOT_BINARY,
+ BINARY_BEGIN,
B64_BYTE0,
B64_BYTE1,
B64_BYTE2,
@@ -1325,6 +1318,19 @@ static grpc_error *append_string(grpc_exec_ctx *exec_ctx,
case NOT_BINARY:
append_bytes(str, cur, (size_t)(end - cur));
return GRPC_ERROR_NONE;
+ case BINARY_BEGIN:
+ if (cur == end) {
+ p->binary = BINARY_BEGIN;
+ return GRPC_ERROR_NONE;
+ }
+ if (*cur == 0) {
+ /* 'true-binary' case */
+ ++cur;
+ p->binary = NOT_BINARY;
+ append_bytes(str, cur, (size_t)(end - cur));
+ return GRPC_ERROR_NONE;
+ }
+ /* fallthrough */
b64_byte0:
case B64_BYTE0:
if (cur == end) {
@@ -1409,6 +1415,8 @@ static grpc_error *finish_str(grpc_exec_ctx *exec_ctx,
switch ((binary_state)p->binary) {
case NOT_BINARY:
break;
+ case BINARY_BEGIN:
+ break;
case B64_BYTE0:
break;
case B64_BYTE1:
@@ -1571,7 +1579,7 @@ static grpc_error *parse_value_string(grpc_exec_ctx *exec_ctx,
const uint8_t *cur, const uint8_t *end,
bool is_binary) {
return begin_parse_string(exec_ctx, p, cur, end,
- is_binary ? B64_BYTE0 : NOT_BINARY, &p->value);
+ is_binary ? BINARY_BEGIN : NOT_BINARY, &p->value);
}
static grpc_error *parse_value_string_with_indexed_key(
diff --git a/src/core/ext/transport/chttp2/transport/http2_settings.c b/src/core/ext/transport/chttp2/transport/http2_settings.c
new file mode 100644
index 0000000000..d4905107ef
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/http2_settings.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017, 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.
+ */
+
+/*
+ * Automatically generated by tools/codegen/core/gen_settings_ids.py
+ */
+
+#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
+
+#include <grpc/support/useful.h>
+#include "src/core/lib/transport/http2_errors.h"
+
+const uint16_t grpc_setting_id_to_wire_id[] = {1, 2, 3, 4, 5, 6, 65027};
+
+bool grpc_wire_id_to_setting_id(uint32_t wire_id, grpc_chttp2_setting_id *out) {
+ uint32_t i = wire_id - 1;
+ uint32_t x = i % 256;
+ uint32_t y = i / 256;
+ uint32_t h = x;
+ switch (y) {
+ case 254:
+ h += 4;
+ break;
+ }
+ *out = (grpc_chttp2_setting_id)h;
+ return h < GPR_ARRAY_SIZE(grpc_setting_id_to_wire_id) &&
+ grpc_setting_id_to_wire_id[h] == wire_id;
+}
+
+const grpc_chttp2_setting_parameters
+ grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = {
+ {"HEADER_TABLE_SIZE", 4096u, 0u, 4294967295u,
+ GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
+ {"ENABLE_PUSH", 1u, 0u, 1u, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
+ GRPC_HTTP2_PROTOCOL_ERROR},
+ {"MAX_CONCURRENT_STREAMS", 4294967295u, 0u, 4294967295u,
+ GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
+ {"INITIAL_WINDOW_SIZE", 65535u, 0u, 2147483647u,
+ GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
+ GRPC_HTTP2_FLOW_CONTROL_ERROR},
+ {"MAX_FRAME_SIZE", 16384u, 16384u, 16777215u,
+ GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
+ {"MAX_HEADER_LIST_SIZE", 16777216u, 0u, 16777216u,
+ GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
+ {"GRPC_ALLOW_TRUE_BINARY_METADATA", 0u, 0u, 1u,
+ GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
+};
diff --git a/src/core/ext/transport/chttp2/transport/http2_settings.h b/src/core/ext/transport/chttp2/transport/http2_settings.h
new file mode 100644
index 0000000000..9781cdc989
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/http2_settings.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2017, 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.
+ */
+
+/*
+ * Automatically generated by tools/codegen/core/gen_settings_ids.py
+ */
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef enum {
+ GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE = 0, /* wire id 1 */
+ GRPC_CHTTP2_SETTINGS_ENABLE_PUSH = 1, /* wire id 2 */
+ GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 2, /* wire id 3 */
+ GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 3, /* wire id 4 */
+ GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE = 4, /* wire id 5 */
+ GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 5, /* wire id 6 */
+ GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA = 6, /* wire id 65027 */
+} grpc_chttp2_setting_id;
+
+#define GRPC_CHTTP2_NUM_SETTINGS 7
+extern const uint16_t grpc_setting_id_to_wire_id[];
+
+bool grpc_wire_id_to_setting_id(uint32_t wire_id, grpc_chttp2_setting_id *out);
+
+typedef enum {
+ GRPC_CHTTP2_CLAMP_INVALID_VALUE,
+ GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE
+} grpc_chttp2_invalid_value_behavior;
+
+typedef struct {
+ const char *name;
+ uint32_t default_value;
+ uint32_t min_value;
+ uint32_t max_value;
+ grpc_chttp2_invalid_value_behavior invalid_value_behavior;
+ uint32_t error_value;
+} grpc_chttp2_setting_parameters;
+
+extern const grpc_chttp2_setting_parameters
+ grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H */
diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c
index be41b3d186..ae9df175ff 100644
--- a/src/core/ext/transport/chttp2/transport/writing.c
+++ b/src/core/ext/transport/chttp2/transport/writing.c
@@ -219,10 +219,18 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
/* send initial metadata if it's available */
if (!sent_initial_metadata && s->send_initial_metadata) {
- grpc_chttp2_encode_header(
- exec_ctx, &t->hpack_compressor, s->id, s->send_initial_metadata, 0,
- t->settings[GRPC_ACKED_SETTINGS][GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
- &s->stats.outgoing, &t->outbuf);
+ grpc_encode_header_options hopt = {
+ .stream_id = s->id,
+ .is_eof = false,
+ .use_true_binary_metadata =
+ t->settings
+ [GRPC_ACKED_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] != 0,
+ .max_frame_size = t->settings[GRPC_ACKED_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
+ .stats = &s->stats.outgoing};
+ grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor,
+ s->send_initial_metadata, &hopt, &t->outbuf);
s->send_initial_metadata = NULL;
s->sent_initial_metadata = true;
sent_initial_metadata = true;
@@ -315,11 +323,21 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true,
&s->stats.outgoing, &t->outbuf);
} else {
- grpc_chttp2_encode_header(
- exec_ctx, &t->hpack_compressor, s->id, s->send_trailing_metadata,
- true, t->settings[GRPC_ACKED_SETTINGS]
- [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
- &s->stats.outgoing, &t->outbuf);
+ grpc_encode_header_options hopt = {
+ .stream_id = s->id,
+ .is_eof = true,
+ .use_true_binary_metadata =
+ t->settings
+ [GRPC_ACKED_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] !=
+ 0,
+ .max_frame_size =
+ t->settings[GRPC_ACKED_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
+ .stats = &s->stats.outgoing};
+ grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor,
+ s->send_trailing_metadata, &hopt,
+ &t->outbuf);
}
s->send_trailing_metadata = NULL;
s->sent_trailing_metadata = true;
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c
index 0b9189558f..88335ecd0b 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.c
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.c
@@ -1124,7 +1124,8 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
if (stream_state->rs.compressed) {
stream_state->rs.sbs.base.flags |= GRPC_WRITE_INTERNAL_COMPRESS;
}
- *((grpc_byte_buffer **)stream_op->recv_message) =
+ *((grpc_byte_buffer **)
+ stream_op->payload->recv_message.recv_message) =
(grpc_byte_buffer *)&stream_state->rs.sbs;
grpc_closure_sched(
exec_ctx, stream_op->payload->recv_message.recv_message_ready,
diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c
index 57726c8476..c12fabb37c 100644
--- a/src/core/lib/channel/message_size_filter.c
+++ b/src/core/lib/channel/message_size_filter.c
@@ -218,14 +218,14 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
if (strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) {
const grpc_integer_options options = {
- GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH, 0, INT_MAX};
+ GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH, -1, INT_MAX};
chand->max_send_size =
grpc_channel_arg_get_integer(&args->channel_args->args[i], options);
}
if (strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) {
const grpc_integer_options options = {
- GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH, 0, INT_MAX};
+ GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH, -1, INT_MAX};
chand->max_recv_size =
grpc_channel_arg_get_integer(&args->channel_args->args[i], options);
}
diff --git a/src/core/lib/iomgr/resolve_address_uv.c b/src/core/lib/iomgr/resolve_address_uv.c
index 102d1aa290..6b468764fc 100644
--- a/src/core/lib/iomgr/resolve_address_uv.c
+++ b/src/core/lib/iomgr/resolve_address_uv.c
@@ -69,8 +69,9 @@ static int retry_named_port_failure(int status, request *r,
int retry_status;
uv_getaddrinfo_t *req = gpr_malloc(sizeof(uv_getaddrinfo_t));
req->data = r;
+ r->port = svc[i][1];
retry_status = uv_getaddrinfo(uv_default_loop(), req, getaddrinfo_cb,
- r->host, svc[i][1], r->hints);
+ r->host, r->port, r->hints);
if (retry_status < 0 || getaddrinfo_cb == NULL) {
// The callback will not be called
gpr_free(req);
diff --git a/src/core/lib/iomgr/sockaddr_utils.c b/src/core/lib/iomgr/sockaddr_utils.c
index 9d2732666b..a6a4cac3e2 100644
--- a/src/core/lib/iomgr/sockaddr_utils.c
+++ b/src/core/lib/iomgr/sockaddr_utils.c
@@ -55,7 +55,9 @@ int grpc_sockaddr_is_v4mapped(const grpc_resolved_address *resolved_addr,
GPR_ASSERT(resolved_addr != resolved_addr4_out);
const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
struct sockaddr_in *addr4_out =
- (struct sockaddr_in *)resolved_addr4_out->addr;
+ resolved_addr4_out == NULL
+ ? NULL
+ : (struct sockaddr_in *)resolved_addr4_out->addr;
if (addr->sa_family == AF_INET6) {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix,
diff --git a/src/core/lib/slice/slice.c b/src/core/lib/slice/slice.c
index 1cddf062cd..a2fcbbdbdf 100644
--- a/src/core/lib/slice/slice.c
+++ b/src/core/lib/slice/slice.c
@@ -197,6 +197,7 @@ grpc_slice grpc_slice_new_with_len(void *p, size_t len,
}
grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t length) {
+ if (length == 0) return grpc_empty_slice();
grpc_slice slice = grpc_slice_malloc(length);
memcpy(GRPC_SLICE_START_PTR(slice), source, length);
return slice;
@@ -382,8 +383,9 @@ grpc_slice grpc_slice_split_head(grpc_slice *source, size_t split) {
}
int grpc_slice_default_eq_impl(grpc_slice a, grpc_slice b) {
- return GRPC_SLICE_LENGTH(a) == GRPC_SLICE_LENGTH(b) &&
- 0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b),
+ if (GRPC_SLICE_LENGTH(a) != GRPC_SLICE_LENGTH(b)) return false;
+ if (GRPC_SLICE_LENGTH(a) == 0) return true;
+ return 0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b),
GRPC_SLICE_LENGTH(a));
}
diff --git a/src/core/lib/transport/pid_controller.c b/src/core/lib/transport/pid_controller.c
index 19cb1c0b36..c851564201 100644
--- a/src/core/lib/transport/pid_controller.c
+++ b/src/core/lib/transport/pid_controller.c
@@ -49,6 +49,7 @@ void grpc_pid_controller_reset(grpc_pid_controller *pid_controller) {
double grpc_pid_controller_update(grpc_pid_controller *pid_controller,
double error, double dt) {
+ if (dt == 0) return pid_controller->last_control_value;
/* integrate error using the trapezoid rule */
pid_controller->error_integral +=
dt * (pid_controller->last_error + error) * 0.5;
diff --git a/src/cpp/util/error_details.cc b/src/cpp/util/error_details.cc
new file mode 100644
index 0000000000..8bba05ac7d
--- /dev/null
+++ b/src/cpp/util/error_details.cc
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright 2017, 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 <grpc++/support/error_details.h>
+
+#include "src/proto/grpc/status/status.pb.h"
+
+namespace grpc {
+
+Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to) {
+ if (to == nullptr) {
+ return Status(StatusCode::FAILED_PRECONDITION, "");
+ }
+ if (!to->ParseFromString(from.error_details())) {
+ return Status(StatusCode::INVALID_ARGUMENT, "");
+ }
+ return Status::OK;
+}
+
+Status SetErrorDetails(const ::google::rpc::Status& from, Status* to) {
+ if (to == nullptr) {
+ return Status(StatusCode::FAILED_PRECONDITION, "");
+ }
+ StatusCode code = StatusCode::UNKNOWN;
+ if (from.code() >= StatusCode::OK && from.code() <= StatusCode::DATA_LOSS) {
+ code = static_cast<StatusCode>(from.code());
+ }
+ *to = Status(code, from.message(), from.SerializeAsString());
+ return Status::OK;
+}
+
+} // namespace grpc
diff --git a/src/csharp/Grpc.Auth/project.json b/src/csharp/Grpc.Auth/project.json
deleted file mode 100644
index 370bf11b2d..0000000000
--- a/src/csharp/Grpc.Auth/project.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "version": "1.3.0-dev",
- "title": "gRPC C# Auth",
- "authors": [ "Google Inc." ],
- "copyright": "Copyright 2015, Google Inc.",
- "packOptions": {
- "summary": "Auth library for C# implementation of gRPC - an RPC library and framework",
- "description": "Auth library for C# implementation of gRPC - an RPC library and framework. See project site for more info.",
- "owners": [ "grpc-packages" ],
- "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
- "projectUrl": "https://github.com/grpc/grpc",
- "requireLicenseAcceptance": false,
- "tags": [ "gRPC RPC Protocol HTTP/2 Auth OAuth2" ],
- },
- "buildOptions": {
- "define": [ "SIGNED" ],
- "keyFile": "../keys/Grpc.snk",
- "xmlDoc": true,
- "compile": {
- "includeFiles": [ "../Grpc.Core/Version.cs" ]
- }
- },
- "dependencies": {
- "Grpc.Core": "1.3.0-dev",
- "Google.Apis.Auth": "1.21.0"
- },
- "frameworks": {
- "net45": { },
- "netstandard1.5": {
- "dependencies": {
- "NETStandard.Library": "1.6.0"
- }
- }
- }
-}
diff --git a/src/csharp/Grpc.Core.Testing/project.json b/src/csharp/Grpc.Core.Testing/project.json
deleted file mode 100644
index 38d5fab50e..0000000000
--- a/src/csharp/Grpc.Core.Testing/project.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "version": "1.3.0-dev",
- "title": "gRPC C# Core Testing",
- "authors": [ "Google Inc." ],
- "copyright": "Copyright 2017, Google Inc.",
- "packOptions": {
- "summary": "Testing support for gRPC C#",
- "description": "Useful when testing code that uses gRPC.",
- "owners": [ "grpc-packages" ],
- "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
- "projectUrl": "https://github.com/grpc/grpc",
- "requireLicenseAcceptance": false,
- "tags": [ "gRPC test testing" ]
- },
- "buildOptions": {
- "define": [ "SIGNED" ],
- "keyFile": "../keys/Grpc.snk",
- "xmlDoc": true,
- "compile": {
- "includeFiles": [ "../Grpc.Core/Version.cs" ]
- }
- },
- "dependencies": {
- "Grpc.Core": "1.3.0-dev"
- },
- "frameworks": {
- "net45": {
- "frameworkAssemblies": {
- "System.Runtime": "",
- "System.IO": ""
- }
- },
- "netstandard1.5": {
- "dependencies": {
- "NETStandard.Library": "1.6.0"
- }
- }
- }
-}
diff --git a/src/csharp/Grpc.HealthCheck/project.json b/src/csharp/Grpc.HealthCheck/project.json
deleted file mode 100644
index e93d0bf81b..0000000000
--- a/src/csharp/Grpc.HealthCheck/project.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "version": "1.3.0-dev",
- "title": "gRPC C# Healthchecking",
- "authors": [ "Google Inc." ],
- "copyright": "Copyright 2015, Google Inc.",
- "packOptions": {
- "summary": "Implementation of gRPC health service",
- "description": "Example implementation of grpc.health.v1 service that can be used for health-checking.",
- "owners": [ "grpc-packages" ],
- "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
- "projectUrl": "https://github.com/grpc/grpc",
- "requireLicenseAcceptance": false,
- "tags": [ "gRPC health check" ]
- },
- "buildOptions": {
- "define": [ "SIGNED" ],
- "keyFile": "../keys/Grpc.snk",
- "xmlDoc": true,
- "compile": {
- "includeFiles": [ "../Grpc.Core/Version.cs" ]
- }
- },
- "dependencies": {
- "Grpc.Core": "1.3.0-dev",
- "Google.Protobuf": "3.2.0"
- },
- "frameworks": {
- "net45": {},
- "netstandard1.5": {
- "dependencies": {
- "NETStandard.Library": "1.6.0"
- }
- }
- }
-}
diff --git a/src/csharp/Grpc.Reflection/project.json b/src/csharp/Grpc.Reflection/project.json
deleted file mode 100644
index 014c78e489..0000000000
--- a/src/csharp/Grpc.Reflection/project.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "version": "1.3.0-dev",
- "title": "gRPC C# Reflection",
- "authors": [ "Google Inc." ],
- "copyright": "Copyright 2016, Google Inc.",
- "packOptions": {
- "summary": "Implementation of gRPC reflection service",
- "description": "Provides information about services running on a gRPC C# server.",
- "owners": [ "grpc-packages" ],
- "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
- "projectUrl": "https://github.com/grpc/grpc",
- "requireLicenseAcceptance": false,
- "tags": [ "gRPC reflection" ]
- },
- "buildOptions": {
- "define": [ "SIGNED" ],
- "keyFile": "../keys/Grpc.snk",
- "xmlDoc": true,
- "compile": {
- "includeFiles": [ "../Grpc.Core/Version.cs" ]
- }
- },
- "dependencies": {
- "Grpc.Core": "1.3.0-dev",
- "Google.Protobuf": "3.2.0"
- },
- "frameworks": {
- "net45": {},
- "netstandard1.5": {
- "dependencies": {
- "NETStandard.Library": "1.6.0"
- }
- }
- }
-}
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index 244546d3d7..5d573110da 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -99,7 +99,6 @@ Local<Value> nanErrorWithCode(const char *msg, grpc_call_error code) {
bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array) {
HandleScope scope;
- grpc_metadata_array_init(array);
Local<Array> keys = Nan::GetOwnPropertyNames(metadata).ToLocalChecked();
for (unsigned int i = 0; i < keys->Length(); i++) {
Local<String> current_key = Nan::To<String>(
@@ -111,18 +110,20 @@ bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array) {
array->capacity += Local<Array>::Cast(value_array)->Length();
}
array->metadata = reinterpret_cast<grpc_metadata*>(
- gpr_malloc(array->capacity * sizeof(grpc_metadata)));
+ gpr_zalloc(array->capacity * sizeof(grpc_metadata)));
for (unsigned int i = 0; i < keys->Length(); i++) {
Local<String> current_key(Nan::To<String>(keys->Get(i)).ToLocalChecked());
Local<Array> values = Local<Array>::Cast(
Nan::Get(metadata, current_key).ToLocalChecked());
- grpc_slice key_slice = grpc_slice_intern(CreateSliceFromString(current_key));
+ grpc_slice key_slice = CreateSliceFromString(current_key);
+ grpc_slice key_intern_slice = grpc_slice_intern(key_slice);
+ grpc_slice_unref(key_slice);
for (unsigned int j = 0; j < values->Length(); j++) {
Local<Value> value = Nan::Get(values, j).ToLocalChecked();
grpc_metadata *current = &array->metadata[array->count];
- current->key = key_slice;
+ current->key = key_intern_slice;
// Only allow binary headers for "-bin" keys
- if (grpc_is_binary_header(key_slice)) {
+ if (grpc_is_binary_header(key_intern_slice)) {
if (::node::Buffer::HasInstance(value)) {
current->value = CreateSliceFromBuffer(value);
} else {
@@ -142,6 +143,14 @@ bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array) {
return true;
}
+void DestroyMetadataArray(grpc_metadata_array *array) {
+ for (size_t i = 0; i < array->count; i++) {
+ // Don't unref keys because they are interned
+ grpc_slice_unref(array->metadata[i].value);
+ }
+ grpc_metadata_array_destroy(array);
+}
+
Local<Value> ParseMetadata(const grpc_metadata_array *metadata_array) {
EscapableHandleScope scope;
grpc_metadata *metadata_elements = metadata_array->metadata;
@@ -179,6 +188,12 @@ Op::~Op() {
class SendMetadataOp : public Op {
public:
+ SendMetadataOp() {
+ grpc_metadata_array_init(&send_metadata);
+ }
+ ~SendMetadataOp() {
+ DestroyMetadataArray(&send_metadata);
+ }
Local<Value> GetNodeValue() const {
EscapableHandleScope scope;
return scope.Escape(Nan::True());
@@ -187,17 +202,16 @@ class SendMetadataOp : public Op {
if (!value->IsObject()) {
return false;
}
- grpc_metadata_array array;
MaybeLocal<Object> maybe_metadata = Nan::To<Object>(value);
if (maybe_metadata.IsEmpty()) {
return false;
}
if (!CreateMetadataArray(maybe_metadata.ToLocalChecked(),
- &array)) {
+ &send_metadata)) {
return false;
}
- out->data.send_initial_metadata.count = array.count;
- out->data.send_initial_metadata.metadata = array.metadata;
+ out->data.send_initial_metadata.count = send_metadata.count;
+ out->data.send_initial_metadata.metadata = send_metadata.metadata;
return true;
}
bool IsFinalOp() {
@@ -207,6 +221,8 @@ class SendMetadataOp : public Op {
std::string GetTypeString() const {
return "send_metadata";
}
+ private:
+ grpc_metadata_array send_metadata;
};
class SendMessageOp : public Op {
@@ -272,8 +288,12 @@ class SendClientCloseOp : public Op {
class SendServerStatusOp : public Op {
public:
+ SendServerStatusOp() {
+ grpc_metadata_array_init(&status_metadata);
+ }
~SendServerStatusOp() {
grpc_slice_unref(details);
+ DestroyMetadataArray(&status_metadata);
}
Local<Value> GetNodeValue() const {
EscapableHandleScope scope;
@@ -313,12 +333,13 @@ class SendServerStatusOp : public Op {
}
Local<String> details = Nan::To<String>(
maybe_details.ToLocalChecked()).ToLocalChecked();
- grpc_metadata_array array;
- if (!CreateMetadataArray(metadata, &array)) {
+ if (!CreateMetadataArray(metadata, &status_metadata)) {
return false;
}
- out->data.send_status_from_server.trailing_metadata_count = array.count;
- out->data.send_status_from_server.trailing_metadata = array.metadata;
+ out->data.send_status_from_server.trailing_metadata_count =
+ status_metadata.count;
+ out->data.send_status_from_server.trailing_metadata =
+ status_metadata.metadata;
out->data.send_status_from_server.status =
static_cast<grpc_status_code>(code);
this->details = CreateSliceFromString(details);
@@ -335,6 +356,7 @@ class SendServerStatusOp : public Op {
private:
grpc_slice details;
+ grpc_metadata_array status_metadata;
};
class GetMetadataOp : public Op {
@@ -466,8 +488,10 @@ class ServerCloseResponseOp : public Op {
int cancelled;
};
-tag::tag(Callback *callback, OpVec *ops, Call *call) :
+tag::tag(Callback *callback, OpVec *ops, Call *call, Local<Value> call_value) :
callback(callback), ops(ops), call(call){
+ HandleScope scope;
+ call_persist.Reset(call_value);
}
tag::~tag() {
@@ -513,15 +537,20 @@ void DestroyTag(void *tag) {
delete tag_struct;
}
+void Call::DestroyCall() {
+ if (this->wrapped_call != NULL) {
+ grpc_call_destroy(this->wrapped_call);
+ this->wrapped_call = NULL;
+ }
+}
+
Call::Call(grpc_call *call) : wrapped_call(call),
pending_batches(0),
has_final_op_completed(false) {
}
Call::~Call() {
- if (wrapped_call != NULL) {
- grpc_call_destroy(wrapped_call);
- }
+ DestroyCall();
}
void Call::Init(Local<Object> exports) {
@@ -568,12 +597,19 @@ void Call::CompleteBatch(bool is_final_op) {
}
this->pending_batches--;
if (this->has_final_op_completed && this->pending_batches == 0) {
- grpc_call_destroy(this->wrapped_call);
- this->wrapped_call = NULL;
+ this->DestroyCall();
}
}
NAN_METHOD(Call::New) {
+ /* Arguments:
+ * 0: Channel to make the call on
+ * 1: Method
+ * 2: Deadline
+ * 3: host
+ * 4: parent Call
+ * 5: propagation flags
+ */
if (info.IsConstructCall()) {
Call *call;
if (info[0]->IsExternal()) {
@@ -618,25 +654,26 @@ NAN_METHOD(Call::New) {
double deadline = Nan::To<double>(info[2]).FromJust();
grpc_channel *wrapped_channel = channel->GetWrappedChannel();
grpc_call *wrapped_call;
+ grpc_slice method = CreateSliceFromString(
+ Nan::To<String>(info[1]).ToLocalChecked());
if (info[3]->IsString()) {
grpc_slice *host = new grpc_slice;
*host = CreateSliceFromString(
Nan::To<String>(info[3]).ToLocalChecked());
wrapped_call = grpc_channel_create_call(
wrapped_channel, parent_call, propagate_flags,
- GetCompletionQueue(), CreateSliceFromString(
- Nan::To<String>(info[1]).ToLocalChecked()),
+ GetCompletionQueue(), method,
host, MillisecondsToTimespec(deadline), NULL);
delete host;
} else if (info[3]->IsUndefined() || info[3]->IsNull()) {
wrapped_call = grpc_channel_create_call(
wrapped_channel, parent_call, propagate_flags,
- GetCompletionQueue(), CreateSliceFromString(
- Nan::To<String>(info[1]).ToLocalChecked()),
+ GetCompletionQueue(), method,
NULL, MillisecondsToTimespec(deadline), NULL);
} else {
return Nan::ThrowTypeError("Call's fourth argument must be a string");
}
+ grpc_slice_unref(method);
call = new Call(wrapped_call);
Nan::Set(info.This(), Nan::New("channel_").ToLocalChecked(),
channel_object);
@@ -721,7 +758,7 @@ NAN_METHOD(Call::StartBatch) {
Callback *callback = new Callback(callback_func);
grpc_call_error error = grpc_call_start_batch(
call->wrapped_call, &ops[0], nops, new struct tag(
- callback, op_vector.release(), call), NULL);
+ callback, op_vector.release(), call, info.This()), NULL);
if (error != GRPC_CALL_OK) {
return Nan::ThrowError(nanErrorWithCode("startBatch failed", error));
}
diff --git a/src/node/ext/call.h b/src/node/ext/call.h
index cffff00fce..53a5e4ab67 100644
--- a/src/node/ext/call.h
+++ b/src/node/ext/call.h
@@ -58,6 +58,8 @@ v8::Local<v8::Value> ParseMetadata(const grpc_metadata_array *metadata_array);
bool CreateMetadataArray(v8::Local<v8::Object> metadata,
grpc_metadata_array *array);
+void DestroyMetadataArray(grpc_metadata_array *array);
+
/* Wrapper class for grpc_call structs. */
class Call : public Nan::ObjectWrap {
public:
@@ -76,6 +78,8 @@ class Call : public Nan::ObjectWrap {
Call(const Call &);
Call &operator=(const Call &);
+ void DestroyCall();
+
static NAN_METHOD(New);
static NAN_METHOD(StartBatch);
static NAN_METHOD(Cancel);
@@ -109,11 +113,14 @@ class Op {
typedef std::vector<unique_ptr<Op>> OpVec;
struct tag {
- tag(Nan::Callback *callback, OpVec *ops, Call *call);
+ tag(Nan::Callback *callback, OpVec *ops, Call *call,
+ v8::Local<v8::Value> call_value);
~tag();
Nan::Callback *callback;
OpVec *ops;
Call *call;
+ Nan::Persistent<v8::Value, Nan::CopyablePersistentTraits<v8::Value>>
+ call_persist;
};
v8::Local<v8::Value> GetTagNodeValue(void *tag);
diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc
index afcc363131..5bd4bdcd5a 100644
--- a/src/node/ext/call_credentials.cc
+++ b/src/node/ext/call_credentials.cc
@@ -211,6 +211,7 @@ NAN_METHOD(PluginCallback) {
Utf8String details_utf8_str(info[1]);
char *details = *details_utf8_str;
grpc_metadata_array array;
+ grpc_metadata_array_init(&array);
Local<Object> callback_data = Nan::To<Object>(info[3]).ToLocalChecked();
if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(),
&array)){
@@ -226,6 +227,7 @@ NAN_METHOD(PluginCallback) {
Nan::New("user_data").ToLocalChecked()
).ToLocalChecked().As<External>()->Value();
cb(user_data, array.metadata, array.count, code, details);
+ DestroyMetadataArray(&array);
}
NAUV_WORK_CB(SendPluginCallback) {
diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc
index c795ff7f42..1263cc0d28 100644
--- a/src/node/ext/channel.cc
+++ b/src/node/ext/channel.cc
@@ -280,7 +280,7 @@ NAN_METHOD(Channel::WatchConnectivityState) {
channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline),
GetCompletionQueue(),
new struct tag(callback,
- ops.release(), NULL));
+ ops.release(), NULL, Nan::Null()));
CompletionQueueNext();
}
diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc
index 95e273f8ac..122e5e63ee 100644
--- a/src/node/ext/node_grpc.cc
+++ b/src/node/ext/node_grpc.cc
@@ -286,8 +286,10 @@ NAN_METHOD(MetadataKeyIsLegal) {
"headerKeyIsLegal's argument must be a string");
}
Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
+ grpc_slice slice = CreateSliceFromString(key);
info.GetReturnValue().Set(static_cast<bool>(
- grpc_header_key_is_legal(CreateSliceFromString(key))));
+ grpc_header_key_is_legal(slice)));
+ grpc_slice_unref(slice);
}
NAN_METHOD(MetadataNonbinValueIsLegal) {
@@ -296,8 +298,10 @@ NAN_METHOD(MetadataNonbinValueIsLegal) {
"metadataNonbinValueIsLegal's argument must be a string");
}
Local<String> value = Nan::To<String>(info[0]).ToLocalChecked();
+ grpc_slice slice = CreateSliceFromString(value);
info.GetReturnValue().Set(static_cast<bool>(
- grpc_header_nonbin_value_is_legal(CreateSliceFromString(value))));
+ grpc_header_nonbin_value_is_legal(slice)));
+ grpc_slice_unref(slice);
}
NAN_METHOD(MetadataKeyIsBinary) {
@@ -306,8 +310,10 @@ NAN_METHOD(MetadataKeyIsBinary) {
"metadataKeyIsLegal's argument must be a string");
}
Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
+ grpc_slice slice = CreateSliceFromString(key);
info.GetReturnValue().Set(static_cast<bool>(
- grpc_is_binary_header(CreateSliceFromString(key))));
+ grpc_is_binary_header(slice)));
+ grpc_slice_unref(slice);
}
static grpc_ssl_roots_override_result get_ssl_roots_override(
diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc
index ccb55aa54c..f0920c842a 100644
--- a/src/node/ext/server.cc
+++ b/src/node/ext/server.cc
@@ -193,7 +193,7 @@ NAN_METHOD(Server::RequestCall) {
GetCompletionQueue(),
GetCompletionQueue(),
new struct tag(new Callback(info[0].As<Function>()), ops.release(),
- NULL));
+ NULL, Nan::Null()));
if (error != GRPC_CALL_OK) {
return Nan::ThrowError(nanErrorWithCode("requestCall failed", error));
}
@@ -246,7 +246,7 @@ NAN_METHOD(Server::TryShutdown) {
grpc_server_shutdown_and_notify(
server->wrapped_server, GetCompletionQueue(),
new struct tag(new Nan::Callback(info[0].As<Function>()), ops.release(),
- NULL));
+ NULL, Nan::Null()));
CompletionQueueNext();
}
diff --git a/src/node/ext/server_uv.cc b/src/node/ext/server_uv.cc
index c5e5ca9f42..82e7589fc8 100644
--- a/src/node/ext/server_uv.cc
+++ b/src/node/ext/server_uv.cc
@@ -118,7 +118,8 @@ void Server::ShutdownServer() {
grpc_server_shutdown_and_notify(
this->wrapped_server, GetCompletionQueue(),
- new struct tag(new Callback(**shutdown_callback), ops.release(), NULL));
+ new struct tag(new Callback(**shutdown_callback), ops.release(), NULL,
+ Nan::Null()));
grpc_server_cancel_all_calls(this->wrapped_server);
CompletionQueueNext();
this->wrapped_server = NULL;
diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m
index 9105356869..69968dcb60 100644
--- a/src/objective-c/tests/InteropTests.m
+++ b/src/objective-c/tests/InteropTests.m
@@ -100,6 +100,15 @@
return 0;
}
++ (void)setUp {
+#ifdef GRPC_COMPILE_WITH_CRONET
+ // Cronet setup
+ [Cronet setHttp2Enabled:YES];
+ [Cronet start];
+ [GRPCCall useCronetWithEngine:[Cronet getGlobalEngine]];
+#endif
+}
+
- (void)setUp {
self.continueAfterFailure = NO;
diff --git a/src/proto/grpc/status/BUILD b/src/proto/grpc/status/BUILD
new file mode 100644
index 0000000000..c17f87eb3d
--- /dev/null
+++ b/src/proto/grpc/status/BUILD
@@ -0,0 +1,43 @@
+# Copyright 2017, 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.
+
+licenses(["notice"]) # 3-clause BSD
+
+package(default_visibility = ["//visibility:public"])
+
+load("//bazel:grpc_build_system.bzl", "grpc_proto_library")
+
+grpc_proto_library(
+ name = "status_proto",
+ srcs = ["status.proto"],
+ has_services = False,
+ well_known_protos = "@submodule_protobuf//:well_known_protos",
+)
+
+
diff --git a/src/proto/grpc/status/README b/src/proto/grpc/status/README
new file mode 100644
index 0000000000..34e588efac
--- /dev/null
+++ b/src/proto/grpc/status/README
@@ -0,0 +1,2 @@
+The status.proto file is copied from
+https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto.
diff --git a/src/proto/grpc/status/status.proto b/src/proto/grpc/status/status.proto
new file mode 100644
index 0000000000..bc6097b29f
--- /dev/null
+++ b/src/proto/grpc/status/status.proto
@@ -0,0 +1,92 @@
+// Copyright 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package google.rpc;
+
+import "google/protobuf/any.proto";
+
+option go_package = "google.golang.org/genproto/googleapis/rpc/status;status";
+option java_multiple_files = true;
+option java_outer_classname = "StatusProto";
+option java_package = "com.google.rpc";
+option objc_class_prefix = "RPC";
+
+
+// The `Status` type defines a logical error model that is suitable for different
+// programming environments, including REST APIs and RPC APIs. It is used by
+// [gRPC](https://github.com/grpc). The error model is designed to be:
+//
+// - Simple to use and understand for most users
+// - Flexible enough to meet unexpected needs
+//
+// # Overview
+//
+// The `Status` message contains three pieces of data: error code, error message,
+// and error details. The error code should be an enum value of
+// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The
+// error message should be a developer-facing English message that helps
+// developers *understand* and *resolve* the error. If a localized user-facing
+// error message is needed, put the localized message in the error details or
+// localize it in the client. The optional error details may contain arbitrary
+// information about the error. There is a predefined set of error detail types
+// in the package `google.rpc` which can be used for common error conditions.
+//
+// # Language mapping
+//
+// The `Status` message is the logical representation of the error model, but it
+// is not necessarily the actual wire format. When the `Status` message is
+// exposed in different client libraries and different wire protocols, it can be
+// mapped differently. For example, it will likely be mapped to some exceptions
+// in Java, but more likely mapped to some error codes in C.
+//
+// # Other uses
+//
+// The error model and the `Status` message can be used in a variety of
+// environments, either with or without APIs, to provide a
+// consistent developer experience across different environments.
+//
+// Example uses of this error model include:
+//
+// - Partial errors. If a service needs to return partial errors to the client,
+// it may embed the `Status` in the normal response to indicate the partial
+// errors.
+//
+// - Workflow errors. A typical workflow has multiple steps. Each step may
+// have a `Status` message for error reporting purpose.
+//
+// - Batch operations. If a client uses batch request and batch response, the
+// `Status` message should be used directly inside batch response, one for
+// each error sub-response.
+//
+// - Asynchronous operations. If an API call embeds asynchronous operation
+// results in its response, the status of those operations should be
+// represented directly using the `Status` message.
+//
+// - Logging. If some API errors are stored in logs, the message `Status` could
+// be used directly after any stripping needed for security/privacy reasons.
+message Status {
+ // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
+ int32 code = 1;
+
+ // A developer-facing error message, which should be in English. Any
+ // user-facing error message should be localized and sent in the
+ // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
+ string message = 2;
+
+ // A list of messages that carry the error details. There will be a
+ // common set of message types for APIs to use.
+ repeated google.protobuf.Any details = 3;
+}
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 0d0a5fb088..7f810bd0b4 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -216,6 +216,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/transport/chttp2/transport/hpack_encoder.c',
'src/core/ext/transport/chttp2/transport/hpack_parser.c',
'src/core/ext/transport/chttp2/transport/hpack_table.c',
+ 'src/core/ext/transport/chttp2/transport/http2_settings.c',
'src/core/ext/transport/chttp2/transport/huffsyms.c',
'src/core/ext/transport/chttp2/transport/incoming_metadata.c',
'src/core/ext/transport/chttp2/transport/parsing.c',