aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/transport/chttp2_transport.c
diff options
context:
space:
mode:
authorGravatar Craig Tiller <craig.tiller@gmail.com>2015-04-21 13:57:55 -0700
committerGravatar Craig Tiller <craig.tiller@gmail.com>2015-04-21 13:57:55 -0700
commit062db022b767177b76fe2cdc221244594f29e473 (patch)
tree818770624f004c57189681facdb114e44e0ed4a3 /src/core/transport/chttp2_transport.c
parentd2b11fafdc533ae7547ca69a9dbd536c35da98c1 (diff)
parent3cdb3b627e4d43806567c6591b5691cd1b6d36d2 (diff)
Merge github.com:google/grpc into batch-metadata
Conflicts: Makefile vsprojects/Grpc.mak vsprojects/vs2010/Grpc.mak vsprojects/vs2010/grpc.vcxproj vsprojects/vs2010/grpc.vcxproj.filters vsprojects/vs2010/grpc_test_util.vcxproj vsprojects/vs2010/grpc_unsecure.vcxproj vsprojects/vs2010/grpc_unsecure.vcxproj.filters
Diffstat (limited to 'src/core/transport/chttp2_transport.c')
-rw-r--r--src/core/transport/chttp2_transport.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index f53c5fa49b..e32ee284e0 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -276,8 +276,8 @@ struct transport {
struct stream {
gpr_uint32 id;
- gpr_uint32 outgoing_window;
gpr_uint32 incoming_window;
+ gpr_int64 outgoing_window;
/* 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' */
@@ -862,7 +862,8 @@ static int prepare_write(transport *t) {
/* for each stream that's become writable, frame it's data (according to
available window sizes) and add to the output buffer */
- while (t->outgoing_window && (s = stream_list_remove_head(t, WRITABLE))) {
+ while (t->outgoing_window && (s = stream_list_remove_head(t, WRITABLE)) &&
+ s->outgoing_window > 0) {
window_delta = grpc_chttp2_preencode(
s->outgoing_sopb.ops, &s->outgoing_sopb.nops,
GPR_MIN(t->outgoing_window, s->outgoing_window), &s->writing_sopb);
@@ -877,7 +878,7 @@ static int prepare_write(transport *t) {
/* if there are still writes to do and the stream still has window
available, then schedule a further write */
- if (s->outgoing_sopb.nops && s->outgoing_window) {
+ if (s->outgoing_sopb.nops > 0 && s->outgoing_window > 0) {
GPR_ASSERT(!t->outgoing_window);
stream_list_add_tail(t, s, WRITABLE);
}
@@ -1459,8 +1460,8 @@ static int init_frame_parser(transport *t) {
}
}
-static int is_window_update_legal(gpr_uint32 window_update, gpr_uint32 window) {
- return window_update < MAX_WINDOW - window;
+static int is_window_update_legal(gpr_int64 window_update, gpr_int64 window) {
+ return window + window_update < MAX_WINDOW;
}
static void free_md(void *p, grpc_op_error result) { gpr_free(p); }
@@ -1542,12 +1543,23 @@ static int parse_frame_slice(transport *t, gpr_slice slice, int is_last) {
}
}
}
+ if (st.initial_window_update) {
+ for (i = 0; i < t->stream_map.count; i++) {
+ stream *s = (stream*)(t->stream_map.values[i]);
+ int was_window_empty = s->outgoing_window <= 0;
+ s->outgoing_window += st.initial_window_update;
+ if (was_window_empty && s->outgoing_window > 0 &&
+ s->outgoing_sopb.nops > 0) {
+ stream_list_join(t, s, WRITABLE);
+ }
+ }
+ }
if (st.window_update) {
if (t->incoming_stream_id) {
/* if there was a stream id, this is for some stream */
stream *s = lookup_stream(t, t->incoming_stream_id);
if (s) {
- int was_window_empty = s->outgoing_window == 0;
+ int was_window_empty = s->outgoing_window <= 0;
if (!is_window_update_legal(st.window_update, s->outgoing_window)) {
cancel_stream(t, s, grpc_chttp2_http2_error_to_grpc_status(
GRPC_CHTTP2_FLOW_CONTROL_ERROR),