diff options
author | Craig Tiller <ctiller@google.com> | 2016-03-31 07:49:58 -0700 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2016-03-31 07:49:58 -0700 |
commit | 64a12c55dfe4bdbdb65b2c508a06f4335f100a98 (patch) | |
tree | 27210a0df4e73a44487d89dc012502fa5d992ee4 /src | |
parent | 6169d5f7b002a68daa3eda36798cec34de11d57f (diff) | |
parent | 6fa2ce56f3600b044d9e27897823de736e948a73 (diff) |
Merge github.com:grpc/grpc into copyright-fix
Diffstat (limited to 'src')
26 files changed, 333 insertions, 165 deletions
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index aab529f47b..62f0c53e0d 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -758,23 +758,35 @@ static void maybe_start_some_streams( } } +#define CLOSURE_BARRIER_STATS_BIT (1 << 0) +#define CLOSURE_BARRIER_FAILURE_BIT (1 << 1) +#define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16) + static grpc_closure *add_closure_barrier(grpc_closure *closure) { - closure->final_data += 2; + closure->final_data += CLOSURE_BARRIER_FIRST_REF_BIT; return closure; } void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, + grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure, int success) { grpc_closure *closure = *pclosure; if (closure == NULL) { return; } - closure->final_data -= 2; + closure->final_data -= CLOSURE_BARRIER_FIRST_REF_BIT; if (!success) { - closure->final_data |= 1; + closure->final_data |= CLOSURE_BARRIER_FAILURE_BIT; } - if (closure->final_data < 2) { - grpc_exec_ctx_enqueue(exec_ctx, closure, closure->final_data == 0, NULL); + if (closure->final_data < CLOSURE_BARRIER_FIRST_REF_BIT) { + if (closure->final_data & CLOSURE_BARRIER_STATS_BIT) { + grpc_transport_move_stats(&stream_global->stats, + stream_global->collecting_stats); + stream_global->collecting_stats = NULL; + } + grpc_exec_ctx_enqueue( + exec_ctx, closure, + (closure->final_data & CLOSURE_BARRIER_FAILURE_BIT) == 0, NULL); } *pclosure = NULL; } @@ -807,7 +819,13 @@ static void perform_stream_op_locked( } /* use final_data as a barrier until enqueue time; the inital counter is dropped at the end of this function */ - on_complete->final_data = 2; + on_complete->final_data = CLOSURE_BARRIER_FIRST_REF_BIT; + + if (op->collect_stats != NULL) { + GPR_ASSERT(stream_global->collecting_stats == NULL); + stream_global->collecting_stats = op->collect_stats; + on_complete->final_data |= CLOSURE_BARRIER_STATS_BIT; + } if (op->cancel_with_status != GRPC_STATUS_OK) { cancel_from_api(exec_ctx, transport_global, stream_global, @@ -840,7 +858,8 @@ static void perform_stream_op_locked( } } else { grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_initial_metadata_finished, 0); + exec_ctx, stream_global, + &stream_global->send_initial_metadata_finished, 0); } } @@ -850,7 +869,7 @@ static void perform_stream_op_locked( stream_global->send_message_finished = add_closure_barrier(on_complete); if (stream_global->write_closed) { grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_message_finished, 0); + exec_ctx, stream_global, &stream_global->send_message_finished, 0); } else { stream_global->send_message = op->send_message; if (stream_global->id != 0) { @@ -870,7 +889,8 @@ static void perform_stream_op_locked( } if (stream_global->write_closed) { grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_trailing_metadata_finished, + exec_ctx, stream_global, + &stream_global->send_trailing_metadata_finished, grpc_metadata_batch_is_empty(op->send_trailing_metadata)); } else if (stream_global->id != 0) { /* TODO(ctiller): check if there's flow control for any outstanding @@ -909,7 +929,7 @@ static void perform_stream_op_locked( grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } - grpc_chttp2_complete_closure_step(exec_ctx, &on_complete, 1); + grpc_chttp2_complete_closure_step(exec_ctx, stream_global, &on_complete, 1); GPR_TIMER_END("perform_stream_op_locked", 0); } @@ -1080,7 +1100,8 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, &stream_global->received_trailing_metadata, stream_global->recv_trailing_metadata); grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->recv_trailing_metadata_finished, 1); + exec_ctx, stream_global, + &stream_global->recv_trailing_metadata_finished, 1); } } } @@ -1131,7 +1152,8 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx, &transport_global->qbuf, grpc_chttp2_rst_stream_create( stream_global->id, - (uint32_t)grpc_chttp2_grpc_status_to_http2_error(status))); + (uint32_t)grpc_chttp2_grpc_status_to_http2_error(status), + &stream_global->stats.outgoing)); } grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status, NULL); @@ -1179,10 +1201,12 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, static void fail_pending_writes(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_global *stream_global) { grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_initial_metadata_finished, 0); + exec_ctx, stream_global, &stream_global->send_initial_metadata_finished, + 0); grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_trailing_metadata_finished, 0); - grpc_chttp2_complete_closure_step(exec_ctx, + exec_ctx, stream_global, &stream_global->send_trailing_metadata_finished, + 0); + grpc_chttp2_complete_closure_step(exec_ctx, stream_global, &stream_global->send_message_finished, 0); } @@ -1319,7 +1343,8 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, gpr_slice_buffer_add( &transport_global->qbuf, - grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR)); + grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR, + &stream_global->stats.outgoing)); if (optional_message) { gpr_slice_ref(*optional_message); diff --git a/src/core/ext/transport/chttp2/transport/frame_data.c b/src/core/ext/transport/chttp2/transport/frame_data.c index d74ac9bf01..9c301d1608 100644 --- a/src/core/ext/transport/chttp2/transport/frame_data.c +++ b/src/core/ext/transport/chttp2/transport/frame_data.c @@ -113,11 +113,13 @@ grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop( void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf, uint32_t write_bytes, int is_eof, + grpc_transport_one_way_stats *stats, gpr_slice_buffer *outbuf) { gpr_slice hdr; uint8_t *p; + static const size_t header_size = 9; - hdr = gpr_slice_malloc(9); + hdr = gpr_slice_malloc(header_size); p = GPR_SLICE_START_PTR(hdr); GPR_ASSERT(write_bytes < (1 << 24)); *p++ = (uint8_t)(write_bytes >> 16); @@ -132,6 +134,9 @@ void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf, gpr_slice_buffer_add(outbuf, hdr); gpr_slice_buffer_move_first(inbuf, write_bytes, outbuf); + + stats->framing_bytes += header_size; + stats->data_bytes += write_bytes; } grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( @@ -156,6 +161,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( switch (p->state) { fh_0: case GRPC_CHTTP2_DATA_FH_0: + stream_parsing->stats.incoming.framing_bytes++; p->frame_type = *cur; switch (p->frame_type) { case 0: @@ -174,6 +180,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_1: + stream_parsing->stats.incoming.framing_bytes++; p->frame_size = ((uint32_t)*cur) << 24; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_2; @@ -181,6 +188,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_2: + stream_parsing->stats.incoming.framing_bytes++; p->frame_size |= ((uint32_t)*cur) << 16; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_3; @@ -188,6 +196,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_3: + stream_parsing->stats.incoming.framing_bytes++; p->frame_size |= ((uint32_t)*cur) << 8; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_4; @@ -195,6 +204,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_4: + stream_parsing->stats.incoming.framing_bytes++; p->frame_size |= ((uint32_t)*cur); p->state = GRPC_CHTTP2_DATA_FRAME; ++cur; @@ -215,7 +225,9 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( } grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing); - if ((uint32_t)(end - cur) == p->frame_size) { + uint32_t remaining = (uint32_t)(end - cur); + if (remaining == p->frame_size) { + stream_parsing->stats.incoming.data_bytes += p->frame_size; grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); @@ -224,7 +236,8 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( p->parsing_frame = NULL; p->state = GRPC_CHTTP2_DATA_FH_0; return GRPC_CHTTP2_PARSE_OK; - } else if ((uint32_t)(end - cur) > p->frame_size) { + } else if (remaining > p->frame_size) { + stream_parsing->stats.incoming.data_bytes += p->frame_size; grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, gpr_slice_sub(slice, (size_t)(cur - beg), @@ -235,11 +248,12 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( cur += p->frame_size; goto fh_0; /* loop */ } else { + GPR_ASSERT(remaining <= p->frame_size); grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); - GPR_ASSERT((size_t)(end - cur) <= p->frame_size); - p->frame_size -= (uint32_t)(end - cur); + p->frame_size -= remaining; + stream_parsing->stats.incoming.data_bytes += remaining; return GRPC_CHTTP2_PARSE_OK; } } diff --git a/src/core/ext/transport/chttp2/transport/frame_data.h b/src/core/ext/transport/chttp2/transport/frame_data.h index b92575963a..2ff32963d6 100644 --- a/src/core/ext/transport/chttp2/transport/frame_data.h +++ b/src/core/ext/transport/chttp2/transport/frame_data.h @@ -41,6 +41,7 @@ #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/transport/byte_stream.h" +#include "src/core/lib/transport/transport.h" typedef enum { GRPC_CHTTP2_DATA_FH_0, @@ -96,6 +97,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf, uint32_t write_bytes, int is_eof, + grpc_transport_one_way_stats *stats, gpr_slice_buffer *outbuf); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_DATA_H */ diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c index 163451742c..22467e9ddd 100644 --- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c @@ -38,8 +38,11 @@ #include "src/core/ext/transport/chttp2/transport/frame.h" -gpr_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code) { - gpr_slice slice = gpr_slice_malloc(13); +gpr_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code, + grpc_transport_one_way_stats *stats) { + static const size_t frame_size = 13; + gpr_slice slice = gpr_slice_malloc(frame_size); + stats->framing_bytes += frame_size; uint8_t *p = GPR_SLICE_START_PTR(slice); *p++ = 0; @@ -84,6 +87,7 @@ grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse( cur++; p->byte++; } + stream_parsing->stats.incoming.framing_bytes += (uint64_t)(end - cur); if (p->byte == 4) { GPR_ASSERT(is_last); diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h index 16383a8151..9c1e756a94 100644 --- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h @@ -37,13 +37,15 @@ #include <grpc/support/slice.h> #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/transport/transport.h" typedef struct { uint8_t byte; uint8_t reason_bytes[4]; } grpc_chttp2_rst_stream_parser; -gpr_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code); +gpr_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code, + grpc_transport_one_way_stats *stats); grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame( grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags); diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.c b/src/core/ext/transport/chttp2/transport/frame_window_update.c index 398e075212..90243418bd 100644 --- a/src/core/ext/transport/chttp2/transport/frame_window_update.c +++ b/src/core/ext/transport/chttp2/transport/frame_window_update.c @@ -36,9 +36,11 @@ #include <grpc/support/log.h> -gpr_slice grpc_chttp2_window_update_create(uint32_t id, - uint32_t window_update) { - gpr_slice slice = gpr_slice_malloc(13); +gpr_slice grpc_chttp2_window_update_create( + uint32_t id, uint32_t window_update, grpc_transport_one_way_stats *stats) { + static const size_t frame_size = 13; + gpr_slice slice = gpr_slice_malloc(frame_size); + stats->header_bytes += frame_size; uint8_t *p = GPR_SLICE_START_PTR(slice); GPR_ASSERT(window_update); @@ -87,6 +89,10 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse( p->byte++; } + if (stream_parsing != NULL) { + stream_parsing->stats.incoming.framing_bytes += (uint32_t)(end - cur); + } + if (p->byte == 4) { uint32_t received_update = p->amount; if (received_update == 0 || (received_update & 0x80000000u)) { diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.h b/src/core/ext/transport/chttp2/transport/frame_window_update.h index 8d56169c5e..d6e87b9329 100644 --- a/src/core/ext/transport/chttp2/transport/frame_window_update.h +++ b/src/core/ext/transport/chttp2/transport/frame_window_update.h @@ -37,6 +37,7 @@ #include <grpc/support/slice.h> #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/transport/transport.h" typedef struct { uint8_t byte; @@ -44,7 +45,8 @@ typedef struct { uint32_t amount; } grpc_chttp2_window_update_parser; -gpr_slice grpc_chttp2_window_update_create(uint32_t id, uint32_t window_delta); +gpr_slice grpc_chttp2_window_update_create(uint32_t id, uint32_t window_delta, + grpc_transport_one_way_stats *stats); grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame( grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags); diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c index f1518b6ed9..807cb5c8f4 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c +++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c @@ -74,6 +74,7 @@ typedef struct { /* output stream id */ uint32_t stream_id; gpr_slice_buffer *output; + grpc_transport_one_way_stats *stats; } framer_state; /* fills p (which is expected to be 9 bytes long) with a data frame header */ @@ -102,6 +103,7 @@ static void finish_frame(framer_state *st, int is_header_boundary, st->stream_id, st->output->length - st->output_length_at_start_of_frame, (uint8_t)((is_last_in_stream ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0) | (is_header_boundary ? GRPC_CHTTP2_DATA_FLAG_END_HEADERS : 0))); + st->stats->framing_bytes += 9; st->is_first_frame = 0; } @@ -147,8 +149,10 @@ static void add_header_data(framer_state *st, gpr_slice slice) { remaining = GRPC_CHTTP2_MAX_PAYLOAD_LENGTH + st->output_length_at_start_of_frame - st->output->length; if (len <= remaining) { + st->stats->header_bytes += len; gpr_slice_buffer_add(st->output, slice); } else { + st->stats->header_bytes += remaining; gpr_slice_buffer_add(st->output, gpr_slice_split_head(&slice, remaining)); finish_frame(st, 0, 0); begin_frame(st); @@ -535,6 +539,7 @@ void grpc_chttp2_hpack_compressor_set_max_table_size( void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, uint32_t stream_id, grpc_metadata_batch *metadata, int is_eof, + grpc_transport_one_way_stats *stats, gpr_slice_buffer *outbuf) { framer_state st; grpc_linked_mdelem *l; @@ -546,6 +551,7 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, st.stream_id = stream_id; st.output = outbuf; st.is_first_frame = 1; + st.stats = stats; /* Encode a metadata batch; store the returned values, representing a metadata element that needs to be unreffed back into the metadata diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.h b/src/core/ext/transport/chttp2/transport/hpack_encoder.h index 2984998a15..0f7b0b063a 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_encoder.h +++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.h @@ -40,6 +40,7 @@ #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata_batch.h" +#include "src/core/lib/transport/transport.h" #define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256 #define GRPC_CHTTP2_HPACKC_NUM_VALUES 256 @@ -90,6 +91,7 @@ void grpc_chttp2_hpack_compressor_set_max_usable_size( void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, uint32_t id, grpc_metadata_batch *metadata, int is_eof, + grpc_transport_one_way_stats *stats, gpr_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 6335e783b9..a36d2fc382 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_parser.c +++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c @@ -1426,6 +1426,9 @@ grpc_chttp2_parse_error grpc_chttp2_header_parser_parse( grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) { grpc_chttp2_hpack_parser *parser = hpack_parser; GPR_TIMER_BEGIN("grpc_chttp2_hpack_parser_parse", 0); + if (stream_parsing != NULL) { + stream_parsing->stats.incoming.header_bytes += GPR_SLICE_LENGTH(slice); + } if (!grpc_chttp2_hpack_parser_parse(parser, GPR_SLICE_START_PTR(slice), GPR_SLICE_END_PTR(slice))) { GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0); diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 327c9670e2..98cd38abd4 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -394,6 +394,9 @@ typedef struct { grpc_metadata_batch *recv_trailing_metadata; grpc_closure *recv_trailing_metadata_finished; + grpc_transport_stream_stats *collecting_stats; + grpc_transport_stream_stats stats; + /** when the application requests writes be closed, the write_closed is 'queued'; when the close is flow controlled into the send path, we are 'sending' it; when the write has been performed it is 'sent' */ @@ -435,6 +438,8 @@ typedef struct { gpr_slice fetching_slice; size_t stream_fetched; grpc_closure finished_fetch; + /** stats gathered during the write */ + grpc_transport_one_way_stats stats; } grpc_chttp2_stream_writing; struct grpc_chttp2_stream_parsing { @@ -460,6 +465,8 @@ struct grpc_chttp2_stream_parsing { int64_t outgoing_window; /** number of bytes received - reset at end of parse thread execution */ int64_t received_bytes; + /** stats gathered during the parse */ + grpc_transport_stream_stats stats; /** incoming metadata */ grpc_chttp2_incoming_metadata_buffer metadata_buffer[2]; @@ -635,6 +642,7 @@ void grpc_chttp2_parsing_become_skip_parser( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing); void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, + grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure, int success); #define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index d78d079830..c754c6005e 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -171,6 +171,9 @@ void grpc_chttp2_publish_reads( grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } + /* flush stats to global stream state */ + grpc_transport_move_stats(&stream_parsing->stats, &stream_global->stats); + /* update outgoing flow control window */ was_zero = stream_global->outgoing_window <= 0; GRPC_CHTTP2_FLOW_MOVE_STREAM("parsed", transport_global, stream_global, @@ -544,8 +547,13 @@ static int init_data_frame_parser( grpc_chttp2_parsing_lookup_stream(transport_parsing, transport_parsing->incoming_stream_id); grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK; - if (!stream_parsing || stream_parsing->received_close) + if (stream_parsing == NULL) { + return init_skip_frame_parser(exec_ctx, transport_parsing, 0); + } + stream_parsing->stats.incoming.framing_bytes += 9; + if (stream_parsing->received_close) { return init_skip_frame_parser(exec_ctx, transport_parsing, 0); + } if (err == GRPC_CHTTP2_PARSE_OK) { err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing); } @@ -566,7 +574,8 @@ static int init_data_frame_parser( gpr_slice_buffer_add( &transport_parsing->qbuf, grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id, - GRPC_CHTTP2_PROTOCOL_ERROR)); + GRPC_CHTTP2_PROTOCOL_ERROR, + &stream_parsing->stats.outgoing)); return init_skip_frame_parser(exec_ctx, transport_parsing, 0); case GRPC_CHTTP2_CONNECTION_ERROR: return 0; @@ -717,6 +726,7 @@ static int init_header_frame_parser( transport_parsing->incoming_stream = stream_parsing; } GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1)); + stream_parsing->stats.incoming.framing_bytes += 9; if (stream_parsing->received_close) { gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header"); transport_parsing->incoming_stream = NULL; @@ -752,9 +762,14 @@ static int init_window_update_frame_parser( &transport_parsing->simple.window_update, transport_parsing->incoming_frame_size, transport_parsing->incoming_frame_flags); - if (transport_parsing->incoming_stream_id) { - transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream( - transport_parsing, transport_parsing->incoming_stream_id); + if (transport_parsing->incoming_stream_id != 0) { + grpc_chttp2_stream_parsing *stream_parsing = + transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream( + transport_parsing, transport_parsing->incoming_stream_id); + if (stream_parsing == NULL) { + return init_skip_frame_parser(exec_ctx, transport_parsing, 0); + } + stream_parsing->stats.incoming.framing_bytes += 9; } transport_parsing->parser = grpc_chttp2_window_update_parser_parse; transport_parsing->parser_data = &transport_parsing->simple.window_update; @@ -778,11 +793,13 @@ static int init_rst_stream_parser( &transport_parsing->simple.rst_stream, transport_parsing->incoming_frame_size, transport_parsing->incoming_frame_flags); - transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream( - transport_parsing, transport_parsing->incoming_stream_id); + grpc_chttp2_stream_parsing *stream_parsing = + transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream( + transport_parsing, transport_parsing->incoming_stream_id); if (!transport_parsing->incoming_stream) { return init_skip_frame_parser(exec_ctx, transport_parsing, 0); } + stream_parsing->stats.incoming.framing_bytes += 9; transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse; transport_parsing->parser_data = &transport_parsing->simple.rst_stream; return ok; @@ -856,7 +873,8 @@ static int parse_frame_slice(grpc_exec_ctx *exec_ctx, gpr_slice_buffer_add( &transport_parsing->qbuf, grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id, - GRPC_CHTTP2_PROTOCOL_ERROR)); + GRPC_CHTTP2_PROTOCOL_ERROR, + &stream_parsing->stats.outgoing)); } return 1; case GRPC_CHTTP2_CONNECTION_ERROR: diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c index 456fa53d2b..a8fb463939 100644 --- a/src/core/ext/transport/chttp2/transport/writing.c +++ b/src/core/ext/transport/chttp2/transport/writing.c @@ -161,8 +161,10 @@ int grpc_chttp2_unlocking_check_writes( transport_global->announce_incoming_window, UINT32_MAX); GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", transport_global, announce_incoming_window, announced); - gpr_slice_buffer_add(&transport_writing->outbuf, - grpc_chttp2_window_update_create(0, announced)); + grpc_transport_one_way_stats throwaway_stats; + gpr_slice_buffer_add( + &transport_writing->outbuf, + grpc_chttp2_window_update_create(0, announced, &throwaway_stats)); } GPR_TIMER_END("grpc_chttp2_unlocking_check_writes", 0); @@ -205,7 +207,8 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx, if (stream_writing->send_initial_metadata != NULL) { grpc_chttp2_encode_header( &transport_writing->hpack_compressor, stream_writing->id, - stream_writing->send_initial_metadata, 0, &transport_writing->outbuf); + stream_writing->send_initial_metadata, 0, &stream_writing->stats, + &transport_writing->outbuf); stream_writing->send_initial_metadata = NULL; stream_writing->sent_initial_metadata = 1; } @@ -216,7 +219,8 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx, gpr_slice_buffer_add( &transport_writing->outbuf, grpc_chttp2_window_update_create(stream_writing->id, - stream_writing->announce_window)); + stream_writing->announce_window, + &stream_writing->stats)); GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing, stream_writing, announce_window, announce); stream_writing->announce_window = 0; @@ -255,7 +259,8 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx, stream_writing->send_trailing_metadata); grpc_chttp2_encode_data( stream_writing->id, &stream_writing->flow_controlled_buffer, - send_bytes, is_last_frame, &transport_writing->outbuf); + send_bytes, is_last_frame, &stream_writing->stats, + &transport_writing->outbuf); GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing, stream_writing, outgoing_window, send_bytes); @@ -281,19 +286,20 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx, stream_writing->send_trailing_metadata != NULL) { if (grpc_metadata_batch_is_empty( stream_writing->send_trailing_metadata)) { - grpc_chttp2_encode_data(stream_writing->id, - &stream_writing->flow_controlled_buffer, 0, 1, - &transport_writing->outbuf); + grpc_chttp2_encode_data( + stream_writing->id, &stream_writing->flow_controlled_buffer, 0, 1, + &stream_writing->stats, &transport_writing->outbuf); } else { - grpc_chttp2_encode_header(&transport_writing->hpack_compressor, - stream_writing->id, - stream_writing->send_trailing_metadata, 1, - &transport_writing->outbuf); + grpc_chttp2_encode_header( + &transport_writing->hpack_compressor, stream_writing->id, + stream_writing->send_trailing_metadata, 1, &stream_writing->stats, + &transport_writing->outbuf); } if (!transport_writing->is_client && !stream_writing->read_closed) { gpr_slice_buffer_add(&transport_writing->outbuf, grpc_chttp2_rst_stream_create( - stream_writing->id, GRPC_CHTTP2_NO_ERROR)); + stream_writing->id, GRPC_CHTTP2_NO_ERROR, + &stream_writing->stats)); } stream_writing->send_trailing_metadata = NULL; stream_writing->sent_trailing_metadata = 1; @@ -328,17 +334,21 @@ void grpc_chttp2_cleanup_writing( transport_global, transport_writing, &stream_global, &stream_writing)) { if (stream_writing->sent_initial_metadata) { grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_initial_metadata_finished, 1); + exec_ctx, stream_global, + &stream_global->send_initial_metadata_finished, 1); } + grpc_transport_move_one_way_stats(&stream_writing->stats, + &stream_global->stats.outgoing); if (stream_writing->sent_message) { GPR_ASSERT(stream_writing->send_message == NULL); grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_message_finished, 1); + exec_ctx, stream_global, &stream_global->send_message_finished, 1); stream_writing->sent_message = 0; } if (stream_writing->sent_trailing_metadata) { grpc_chttp2_complete_closure_step( - exec_ctx, &stream_global->send_trailing_metadata_finished, 1); + exec_ctx, stream_global, + &stream_global->send_trailing_metadata_finished, 1); } if (stream_writing->sent_trailing_metadata) { grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c index 816a3acc75..deba23e21f 100644 --- a/src/core/lib/channel/http_client_filter.c +++ b/src/core/lib/channel/http_client_filter.c @@ -112,7 +112,9 @@ static void hc_mutate_op(grpc_call_element *elem, /* Send : prefixed headers, which have to be before any application layer headers. */ grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method, - GRPC_MDELEM_METHOD_POST); + op->send_idempotent_request + ? GRPC_MDELEM_METHOD_PUT + : GRPC_MDELEM_METHOD_POST); grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme, channeld->static_scheme); grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers, diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c index 80097852c4..c140c61b8f 100644 --- a/src/core/lib/channel/http_server_filter.c +++ b/src/core/lib/channel/http_server_filter.c @@ -41,7 +41,7 @@ typedef struct call_data { uint8_t seen_path; - uint8_t seen_post; + uint8_t seen_method; uint8_t sent_status; uint8_t seen_scheme; uint8_t seen_te_trailers; @@ -50,6 +50,7 @@ typedef struct call_data { grpc_linked_mdelem content_type; grpc_metadata_batch *recv_initial_metadata; + bool *recv_idempotent_request; /** Closure to call when finished with the hs_on_recv hook */ grpc_closure *on_done_recv; /** Receive closures are chained: we inject this closure as the on_done_recv @@ -72,11 +73,16 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) { /* Check if it is one of the headers we care about. */ if (md == GRPC_MDELEM_TE_TRAILERS || md == GRPC_MDELEM_METHOD_POST || - md == GRPC_MDELEM_SCHEME_HTTP || md == GRPC_MDELEM_SCHEME_HTTPS || + md == GRPC_MDELEM_METHOD_PUT || md == GRPC_MDELEM_SCHEME_HTTP || + md == GRPC_MDELEM_SCHEME_HTTPS || md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) { /* swallow it */ if (md == GRPC_MDELEM_METHOD_POST) { - calld->seen_post = 1; + calld->seen_method = 1; + *calld->recv_idempotent_request = false; + } else if (md == GRPC_MDELEM_METHOD_PUT) { + calld->seen_method = 1; + *calld->recv_idempotent_request = true; } else if (md->key == GRPC_MDSTR_SCHEME) { calld->seen_scheme = 1; } else if (md == GRPC_MDELEM_TE_TRAILERS) { @@ -142,7 +148,7 @@ static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) { /* Have we seen the required http2 transport headers? (:method, :scheme, content-type, with :path and :authority covered at the channel level right now) */ - if (calld->seen_post && calld->seen_scheme && calld->seen_te_trailers && + if (calld->seen_method && calld->seen_scheme && calld->seen_te_trailers && calld->seen_path && calld->seen_authority) { /* do nothing */ } else { @@ -152,7 +158,7 @@ static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) { if (!calld->seen_authority) { gpr_log(GPR_ERROR, "Missing :authority header"); } - if (!calld->seen_post) { + if (!calld->seen_method) { gpr_log(GPR_ERROR, "Missing :method header"); } if (!calld->seen_scheme) { @@ -185,7 +191,9 @@ static void hs_mutate_op(grpc_call_element *elem, if (op->recv_initial_metadata) { /* substitute our callback for the higher callback */ + GPR_ASSERT(op->recv_idempotent_request != NULL); calld->recv_initial_metadata = op->recv_initial_metadata; + calld->recv_idempotent_request = op->recv_idempotent_request; calld->on_done_recv = op->recv_initial_metadata_ready; op->recv_initial_metadata_ready = &calld->hs_on_recv; } diff --git a/src/core/lib/client_config/resolvers/sockaddr_resolver.c b/src/core/lib/client_config/resolvers/sockaddr_resolver.c index e2b3c6ac7f..0e2656d033 100644 --- a/src/core/lib/client_config/resolvers/sockaddr_resolver.c +++ b/src/core/lib/client_config/resolvers/sockaddr_resolver.c @@ -267,46 +267,17 @@ static grpc_resolver *sockaddr_create( r->lb_policy_name = NULL; if (0 != strcmp(args->uri->query, "")) { gpr_slice query_slice; - gpr_slice_buffer query_parts; /* the &-separated elements of the query */ - gpr_slice_buffer query_param_parts; /* the =-separated subelements */ + gpr_slice_buffer query_parts; query_slice = gpr_slice_new(args->uri->query, strlen(args->uri->query), do_nothing); gpr_slice_buffer_init(&query_parts); - gpr_slice_buffer_init(&query_param_parts); - /* the query can contain "lb_policy=<policy>" and "lb_enabled=<1|0>" */ - - bool lb_enabled; - gpr_slice_split(query_slice, "&", &query_parts); - for (i = 0; i < query_parts.count; i++) { - gpr_slice_split(query_parts.slices[i], "=", &query_param_parts); - GPR_ASSERT(query_param_parts.count == 2); - if (0 == gpr_slice_str_cmp(query_param_parts.slices[0], "lb_policy")) { - r->lb_policy_name = - gpr_dump_slice(query_param_parts.slices[1], GPR_DUMP_ASCII); - } else if (0 == - gpr_slice_str_cmp(query_param_parts.slices[0], "lb_enabled")) { - if (0 != gpr_slice_str_cmp(query_param_parts.slices[1], "0")) { - /* anything other than 0 is taken to be true */ - lb_enabled = true; - } - } else { - gpr_log(GPR_ERROR, "invalid query element value: '%s'", - query_parts.slices[0]); - } - gpr_slice_buffer_reset_and_unref(&query_param_parts); - } - - if (strcmp("grpclb", r->lb_policy_name) == 0 && !lb_enabled) { - /* we want grpclb but the "resolved" addresses aren't LB enabled. Bail - * out, as this is meant mostly for tests. */ - gpr_log(GPR_ERROR, - "Requested 'grpclb' LB policy but resolved addresses don't " - "support load balancing."); - abort(); + gpr_slice_split(query_slice, "=", &query_parts); + GPR_ASSERT(query_parts.count == 2); + if (0 == gpr_slice_str_cmp(query_parts.slices[0], "lb_policy")) { + r->lb_policy_name = gpr_dump_slice(query_parts.slices[1], GPR_DUMP_ASCII); } gpr_slice_buffer_destroy(&query_parts); - gpr_slice_buffer_destroy(&query_param_parts); gpr_slice_unref(query_slice); } if (r->lb_policy_name == NULL) { diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 2f713d6419..37cc724b53 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -174,6 +174,9 @@ struct grpc_call { /* Received call statuses from various sources */ received_status status[STATUS_SOURCE_COUNT]; + /* Call stats: only valid after trailing metadata received */ + grpc_transport_stream_stats stats; + /* Compression algorithm for the call */ grpc_compression_algorithm compression_algorithm; /* Supported encodings (compression algorithms), a bitset */ @@ -909,7 +912,7 @@ static void set_cancelled_value(grpc_status_code status, void *dest) { *(int *)dest = (status != GRPC_STATUS_OK); } -static int are_write_flags_valid(uint32_t flags) { +static bool are_write_flags_valid(uint32_t flags) { /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */ const uint32_t allowed_write_positions = (GRPC_WRITE_USED_MASK | GRPC_WRITE_INTERNAL_USED_MASK); @@ -917,6 +920,15 @@ static int are_write_flags_valid(uint32_t flags) { return !(flags & invalid_positions); } +static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) { + /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */ + uint32_t invalid_positions = ~GRPC_INITIAL_METADATA_USED_MASK; + if (!is_client) { + invalid_positions |= GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; + } + return !(flags & invalid_positions); +} + static batch_control *allocate_batch_control(grpc_call *call) { size_t i; for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) { @@ -1196,7 +1208,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, switch (op->op) { case GRPC_OP_SEND_INITIAL_METADATA: /* Flag validation: currently allow no flags */ - if (op->flags != 0) { + if (!are_initial_metadata_flags_valid(op->flags, call->is_client)) { error = GRPC_CALL_ERROR_INVALID_FLAGS; goto done_with_error; } @@ -1220,6 +1232,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->metadata_batch[0][0].deadline = call->send_deadline; stream_op.send_initial_metadata = &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]; + stream_op.send_idempotent_request = + (op->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) != 0; break; case GRPC_OP_SEND_MESSAGE: if (!are_write_flags_valid(op->flags)) { @@ -1371,6 +1385,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, bctl->recv_final_op = 1; stream_op.recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; + stream_op.collect_stats = &call->stats; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: /* Flag validation: currently allow no flags */ @@ -1392,6 +1407,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, bctl->recv_final_op = 1; stream_op.recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; + stream_op.collect_stats = &call->stats; break; } } diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index fb4d6089ff..1898bee1c1 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -100,6 +100,7 @@ typedef struct requested_call { typedef struct channel_registered_method { registered_method *server_registered_method; + uint32_t flags; grpc_mdstr *method; grpc_mdstr *host; } channel_registered_method; @@ -152,6 +153,7 @@ struct call_data { grpc_completion_queue *cq_new; grpc_metadata_batch *recv_initial_metadata; + bool recv_idempotent_request; grpc_metadata_array initial_metadata; grpc_closure got_initial_metadata; @@ -171,6 +173,7 @@ struct request_matcher { struct registered_method { char *method; char *host; + uint32_t flags; request_matcher request_matcher; registered_method *next; }; @@ -468,6 +471,9 @@ static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { if (!rm) break; if (rm->host != calld->host) continue; if (rm->method != calld->path) continue; + if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) && + !calld->recv_idempotent_request) + continue; finish_start_new_rpc(exec_ctx, server, elem, &rm->server_registered_method->request_matcher); return; @@ -480,6 +486,9 @@ static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { if (!rm) break; if (rm->host != NULL) continue; if (rm->method != calld->path) continue; + if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) && + !calld->recv_idempotent_request) + continue; finish_start_new_rpc(exec_ctx, server, elem, &rm->server_registered_method->request_matcher); return; @@ -598,9 +607,11 @@ static void server_mutate_op(grpc_call_element *elem, call_data *calld = elem->call_data; if (op->recv_initial_metadata != NULL) { + GPR_ASSERT(op->recv_idempotent_request == NULL); calld->recv_initial_metadata = op->recv_initial_metadata; calld->on_done_recv_initial_metadata = op->recv_initial_metadata_ready; op->recv_initial_metadata_ready = &calld->server_on_recv_initial_metadata; + op->recv_idempotent_request = &calld->recv_idempotent_request; } } @@ -830,10 +841,12 @@ static int streq(const char *a, const char *b) { } void *grpc_server_register_method(grpc_server *server, const char *method, - const char *host) { + const char *host, uint32_t flags) { registered_method *m; - GRPC_API_TRACE("grpc_server_register_method(server=%p, method=%s, host=%s)", - 3, (server, method, host)); + GRPC_API_TRACE( + "grpc_server_register_method(server=%p, method=%s, host=%s, " + "flags=0x%08x)", + 4, (server, method, host, flags)); if (!method) { gpr_log(GPR_ERROR, "grpc_server_register_method method string cannot be NULL"); @@ -846,12 +859,18 @@ void *grpc_server_register_method(grpc_server *server, const char *method, return NULL; } } + if ((flags & ~GRPC_INITIAL_METADATA_USED_MASK) != 0) { + gpr_log(GPR_ERROR, "grpc_server_register_method invalid flags 0x%08x", + flags); + return NULL; + } m = gpr_malloc(sizeof(registered_method)); memset(m, 0, sizeof(*m)); request_matcher_init(&m->request_matcher, server->max_requested_calls); m->method = gpr_strdup(method); m->host = gpr_strdup(host); m->next = server->registered_methods; + m->flags = flags; server->registered_methods = m; return m; } @@ -930,6 +949,7 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, if (probes > max_probes) max_probes = probes; crm = &chand->registered_methods[(hash + probes) % slots]; crm->server_registered_method = rm; + crm->flags = rm->flags; crm->host = host; crm->method = method; } @@ -1247,6 +1267,10 @@ static void begin_call(grpc_exec_ctx *exec_ctx, grpc_server *server, cpstr(&rc->data.batch.details->method, &rc->data.batch.details->method_capacity, calld->path); rc->data.batch.details->deadline = calld->deadline; + rc->data.batch.details->flags = + 0 | (calld->recv_idempotent_request + ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST + : 0); break; case REGISTERED_CALL: *rc->data.registered.deadline = calld->deadline; diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c index 812ee5a8c4..73b0041fd4 100644 --- a/src/core/lib/transport/static_metadata.c +++ b/src/core/lib/transport/static_metadata.c @@ -1,5 +1,4 @@ /* - * * Copyright 2015, Google Inc. * All rights reserved. * @@ -28,19 +27,16 @@ * 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. - * */ /* * WARNING: Auto-generated code. * * To make changes to this file, change - * tools/codegen/core/gen_static_metadata.py, - * and then re-run it. + * tools/codegen/core/gen_static_metadata.py, and then re-run it. * * See metadata.h for an explanation of the interface here, and metadata.c for - * an - * explanation of what's going on. + * an explanation of what's going on. */ #include "src/core/lib/transport/static_metadata.h" @@ -52,7 +48,7 @@ uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 6, 2, 4, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] = {11, 35, 10, 35, 12, 35, 12, 49, 13, 35, 14, 35, 15, 35, 16, 35, 17, 35, @@ -60,10 +56,10 @@ const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] = 30, 18, 30, 35, 31, 35, 32, 35, 36, 35, 37, 35, 38, 35, 39, 35, 42, 33, 42, 34, 42, 48, 42, 53, 42, 54, 42, 55, 42, 56, 43, 33, 43, 48, 43, 53, 46, 0, 46, 1, 46, 2, 50, 35, 57, 35, 58, 35, 59, 35, 60, 35, 61, 35, - 62, 35, 63, 35, 64, 35, 65, 35, 66, 40, 66, 68, 67, 78, 67, 79, 69, 35, - 70, 35, 71, 35, 72, 35, 73, 35, 74, 35, 75, 41, 75, 51, 75, 52, 76, 35, - 77, 35, 80, 3, 80, 4, 80, 5, 80, 6, 80, 7, 80, 8, 80, 9, 81, 35, - 82, 83, 84, 35, 85, 35, 86, 35, 87, 35, 88, 35}; + 62, 35, 63, 35, 64, 35, 65, 35, 66, 40, 66, 68, 66, 71, 67, 79, 67, 80, + 69, 35, 70, 35, 72, 35, 73, 35, 74, 35, 75, 35, 76, 41, 76, 51, 76, 52, + 77, 35, 78, 35, 81, 3, 81, 4, 81, 5, 81, 6, 81, 7, 81, 8, 81, 9, + 82, 35, 83, 84, 85, 35, 86, 35, 87, 35, 88, 35, 89, 35}; const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "0", @@ -137,6 +133,7 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "POST", "proxy-authenticate", "proxy-authorization", + "PUT", "range", "referer", "refresh", diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h index f7a545ec00..f9d8bcdc8f 100644 --- a/src/core/lib/transport/static_metadata.h +++ b/src/core/lib/transport/static_metadata.h @@ -1,5 +1,4 @@ /* - * * Copyright 2015, Google Inc. * All rights reserved. * @@ -28,19 +27,16 @@ * 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. - * */ /* * WARNING: Auto-generated code. * * To make changes to this file, change - * tools/codegen/core/gen_static_metadata.py, - * and then re-run it. + * tools/codegen/core/gen_static_metadata.py, and then re-run it. * * See metadata.h for an explanation of the interface here, and metadata.c for - * an - * explanation of what's going on. + * an explanation of what's going on. */ #ifndef GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H @@ -48,7 +44,7 @@ #include "src/core/lib/transport/metadata.h" -#define GRPC_STATIC_MDSTR_COUNT 89 +#define GRPC_STATIC_MDSTR_COUNT 90 extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; /* "0" */ #define GRPC_MDSTR_0 (&grpc_static_mdstr_table[0]) @@ -193,44 +189,46 @@ extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; #define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[69]) /* "proxy-authorization" */ #define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[70]) +/* "PUT" */ +#define GRPC_MDSTR_PUT (&grpc_static_mdstr_table[71]) /* "range" */ -#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[71]) +#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[72]) /* "referer" */ -#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[72]) +#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[73]) /* "refresh" */ -#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[73]) +#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[74]) /* "retry-after" */ -#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[74]) +#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[75]) /* ":scheme" */ -#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[75]) +#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[76]) /* "server" */ -#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[76]) +#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[77]) /* "set-cookie" */ -#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[77]) +#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[78]) /* "/" */ -#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[78]) +#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[79]) /* "/index.html" */ -#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[79]) +#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[80]) /* ":status" */ -#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[80]) +#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[81]) /* "strict-transport-security" */ -#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[81]) +#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[82]) /* "te" */ -#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[82]) +#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[83]) /* "trailers" */ -#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[83]) +#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[84]) /* "transfer-encoding" */ -#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[84]) +#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[85]) /* "user-agent" */ -#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[85]) +#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[86]) /* "vary" */ -#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[86]) +#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[87]) /* "via" */ -#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[87]) +#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[88]) /* "www-authenticate" */ -#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[88]) +#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[89]) -#define GRPC_STATIC_MDELEM_COUNT 78 +#define GRPC_STATIC_MDELEM_COUNT 79 extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT]; /* "accept-charset": "" */ @@ -343,61 +341,63 @@ extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT]; #define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[49]) /* ":method": "POST" */ #define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[50]) +/* ":method": "PUT" */ +#define GRPC_MDELEM_METHOD_PUT (&grpc_static_mdelem_table[51]) /* ":path": "/" */ -#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[51]) +#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[52]) /* ":path": "/index.html" */ -#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[52]) +#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[53]) /* "proxy-authenticate": "" */ -#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[53]) +#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[54]) /* "proxy-authorization": "" */ -#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[54]) +#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[55]) /* "range": "" */ -#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[55]) +#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[56]) /* "referer": "" */ -#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[56]) +#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[57]) /* "refresh": "" */ -#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[57]) +#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[58]) /* "retry-after": "" */ -#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[58]) +#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[59]) /* ":scheme": "grpc" */ -#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[59]) +#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[60]) /* ":scheme": "http" */ -#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[60]) +#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[61]) /* ":scheme": "https" */ -#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[61]) +#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[62]) /* "server": "" */ -#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[62]) +#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[63]) /* "set-cookie": "" */ -#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[63]) +#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[64]) /* ":status": "200" */ -#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[64]) +#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[65]) /* ":status": "204" */ -#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[65]) +#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[66]) /* ":status": "206" */ -#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[66]) +#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[67]) /* ":status": "304" */ -#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[67]) +#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[68]) /* ":status": "400" */ -#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[68]) +#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[69]) /* ":status": "404" */ -#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[69]) +#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[70]) /* ":status": "500" */ -#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[70]) +#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[71]) /* "strict-transport-security": "" */ #define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \ - (&grpc_static_mdelem_table[71]) + (&grpc_static_mdelem_table[72]) /* "te": "trailers" */ -#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[72]) +#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[73]) /* "transfer-encoding": "" */ -#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[73]) +#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[74]) /* "user-agent": "" */ -#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[74]) +#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[75]) /* "vary": "" */ -#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[75]) +#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[76]) /* "via": "" */ -#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[76]) +#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[77]) /* "www-authenticate": "" */ -#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[77]) +#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[78]) extern const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2]; diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c index 352d20627e..53c634adca 100644 --- a/src/core/lib/transport/transport.c +++ b/src/core/lib/transport/transport.c @@ -35,6 +35,7 @@ #include <grpc/support/alloc.h> #include <grpc/support/atm.h> #include <grpc/support/log.h> +#include <grpc/support/sync.h> #include "src/core/lib/transport/transport_impl.h" #ifdef GRPC_STREAM_REFCOUNT_DEBUG @@ -76,6 +77,24 @@ void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs, grpc_closure_init(&refcount->destroy, cb, cb_arg); } +static void move64(uint64_t *from, uint64_t *to) { + *to += *from; + *from = 0; +} + +void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats *from, + grpc_transport_one_way_stats *to) { + move64(&from->framing_bytes, &to->framing_bytes); + move64(&from->data_bytes, &to->data_bytes); + move64(&from->header_bytes, &to->header_bytes); +} + +void grpc_transport_move_stats(grpc_transport_stream_stats *from, + grpc_transport_stream_stats *to) { + grpc_transport_move_one_way_stats(&from->incoming, &to->incoming); + grpc_transport_move_one_way_stats(&from->outgoing, &to->outgoing); +} + size_t grpc_transport_stream_size(grpc_transport *transport) { return transport->vtable->sizeof_stream; } diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 94656a447a..460e4dcedc 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -78,11 +78,32 @@ void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount); grpc_stream_ref_init(rc, ir, cb, cb_arg) #endif +typedef struct { + uint64_t framing_bytes; + uint64_t data_bytes; + uint64_t header_bytes; +} grpc_transport_one_way_stats; + +typedef struct grpc_transport_stream_stats { + grpc_transport_one_way_stats incoming; + grpc_transport_one_way_stats outgoing; +} grpc_transport_stream_stats; + +void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats *from, + grpc_transport_one_way_stats *to); + +void grpc_transport_move_stats(grpc_transport_stream_stats *from, + grpc_transport_stream_stats *to); + /* Transport stream op: a set of operations to perform on a transport against a single stream */ typedef struct grpc_transport_stream_op { - /** Send initial metadata to the peer, from the provided metadata batch. */ + /** Send initial metadata to the peer, from the provided metadata batch. + idempotent_request MUST be set if this is non-null */ grpc_metadata_batch *send_initial_metadata; + /** Iff send_initial_metadata != NULL, flags if this is an idempotent request + or not */ + bool send_idempotent_request; /** Send trailing metadata to the peer, from the provided metadata batch. */ grpc_metadata_batch *send_trailing_metadata; @@ -92,6 +113,7 @@ typedef struct grpc_transport_stream_op { /** Receive initial metadata from the stream, into provided metadata batch. */ grpc_metadata_batch *recv_initial_metadata; + bool *recv_idempotent_request; /** Should be enqueued when initial metadata is ready to be processed. */ grpc_closure *recv_initial_metadata_ready; @@ -104,6 +126,9 @@ typedef struct grpc_transport_stream_op { */ grpc_metadata_batch *recv_trailing_metadata; + /** Collect any stats into provided buffer, zero internal stat counters */ + grpc_transport_stream_stats *collect_stats; + /** Should be enqueued when all requested operations (excluding recv_message and recv_initial_metadata which have their own closures) in a given batch have been completed. */ diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index 76f8971631..3e44c502fc 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -264,6 +264,7 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag { void* const tag_; bool in_flight_; const bool has_request_payload_; + uint32_t incoming_flags_; grpc_call* call_; grpc_call_details* call_details_; gpr_timespec deadline_; @@ -334,7 +335,7 @@ bool Server::RegisterService(const grpc::string* host, Service* service) { } RpcServiceMethod* method = it->get(); void* tag = grpc_server_register_method(server_, method->name(), - host ? host->c_str() : nullptr); + host ? host->c_str() : nullptr, 0); if (tag == nullptr) { gpr_log(GPR_DEBUG, "Attempt to register %s multiple times", method->name()); diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h index 4d18369e1f..adcd8e954a 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/python/grpcio/grpc/_cython/imports.generated.h @@ -283,7 +283,7 @@ extern grpc_call_destroy_type grpc_call_destroy_import; typedef grpc_call_error(*grpc_server_request_call_type)(grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new); extern grpc_server_request_call_type grpc_server_request_call_import; #define grpc_server_request_call grpc_server_request_call_import -typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host); +typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, uint32_t flags); extern grpc_server_register_method_type grpc_server_register_method_import; #define grpc_server_register_method grpc_server_register_method_import typedef grpc_call_error(*grpc_server_request_registered_call_type)(grpc_server *server, void *registered_method, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *request_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new); diff --git a/src/python/grpcio/precompiled.py b/src/python/grpcio/precompiled.py index 3cf0ded1e9..b6aa7fc90e 100644 --- a/src/python/grpcio/precompiled.py +++ b/src/python/grpcio/precompiled.py @@ -91,6 +91,9 @@ class BuildTaggedExt(setuptools.Command): def update_setup_arguments(setup_arguments): + if not USE_PRECOMPILED_BINARIES: + sys.stderr.write('not using precompiled extension') + return url = '{}/{}.so'.format(BINARIES_REPOSITORY, _tagged_ext_name('cygrpc')) target_path = os.path.join(PYTHON_STEM, 'grpc/_cython/cygrpc.so') try: diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 3bf81af8fb..22ea84c750 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -283,7 +283,7 @@ extern grpc_call_destroy_type grpc_call_destroy_import; typedef grpc_call_error(*grpc_server_request_call_type)(grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new); extern grpc_server_request_call_type grpc_server_request_call_import; #define grpc_server_request_call grpc_server_request_call_import -typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host); +typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, uint32_t flags); extern grpc_server_register_method_type grpc_server_register_method_import; #define grpc_server_register_method grpc_server_register_method_import typedef grpc_call_error(*grpc_server_request_registered_call_type)(grpc_server *server, void *registered_method, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *request_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new); |