|  | @@ -56,7 +56,8 @@
 | 
	
		
			
				|  |  |  #include <grpc/support/string.h>
 | 
	
		
			
				|  |  |  #include <grpc/support/useful.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define DEFAULT_WINDOW 65536
 | 
	
		
			
				|  |  | +#define DEFAULT_WINDOW 65535
 | 
	
		
			
				|  |  | +#define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
 | 
	
		
			
				|  |  |  #define MAX_WINDOW 0x7fffffffu
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #define CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
 | 
	
	
		
			
				|  | @@ -190,12 +191,14 @@ struct transport {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* settings */
 | 
	
		
			
				|  |  |    gpr_uint32 settings[NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
 | 
	
		
			
				|  |  | -  gpr_uint8 sent_local_settings;
 | 
	
		
			
				|  |  | -  gpr_uint8 dirtied_local_settings;
 | 
	
		
			
				|  |  | +  gpr_uint32 force_send_settings;   /* bitmask of setting indexes to send out */
 | 
	
		
			
				|  |  | +  gpr_uint8 sent_local_settings;    /* have local settings been sent? */
 | 
	
		
			
				|  |  | +  gpr_uint8 dirtied_local_settings; /* are the local settings dirty? */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* window management */
 | 
	
		
			
				|  |  |    gpr_uint32 outgoing_window;
 | 
	
		
			
				|  |  |    gpr_uint32 incoming_window;
 | 
	
		
			
				|  |  | +  gpr_uint32 connection_window_target;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* deframing */
 | 
	
		
			
				|  |  |    deframe_transport_state deframe_state;
 | 
	
	
		
			
				|  | @@ -383,6 +386,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup,
 | 
	
		
			
				|  |  |    t->is_client = is_client;
 | 
	
		
			
				|  |  |    t->outgoing_window = DEFAULT_WINDOW;
 | 
	
		
			
				|  |  |    t->incoming_window = DEFAULT_WINDOW;
 | 
	
		
			
				|  |  | +  t->connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET;
 | 
	
		
			
				|  |  |    t->deframe_state = is_client ? DTS_FH_0 : DTS_CLIENT_PREFIX_0;
 | 
	
		
			
				|  |  |    t->expect_continuation_stream_id = 0;
 | 
	
		
			
				|  |  |    t->pings = NULL;
 | 
	
	
		
			
				|  | @@ -415,6 +419,9 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup,
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    t->dirtied_local_settings = 1;
 | 
	
		
			
				|  |  | +  /* Hack: it's common for implementations to assume 65536 bytes initial send
 | 
	
		
			
				|  |  | +     window -- this should by rights be 0 */
 | 
	
		
			
				|  |  | +  t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
 | 
	
		
			
				|  |  |    t->sent_local_settings = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* configure http2 the way we like it */
 | 
	
	
		
			
				|  | @@ -422,6 +429,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup,
 | 
	
		
			
				|  |  |      push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0);
 | 
	
		
			
				|  |  |      push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (channel_args) {
 | 
	
		
			
				|  |  |      for (i = 0; i < channel_args->num_args; i++) {
 | 
	
	
		
			
				|  | @@ -506,8 +514,10 @@ static int init_stream(grpc_transport *gt, grpc_stream *gs,
 | 
	
		
			
				|  |  |      grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  s->outgoing_window = DEFAULT_WINDOW;
 | 
	
		
			
				|  |  | -  s->incoming_window = DEFAULT_WINDOW;
 | 
	
		
			
				|  |  | +  s->outgoing_window =
 | 
	
		
			
				|  |  | +      t->settings[PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
		
			
				|  |  | +  s->incoming_window =
 | 
	
		
			
				|  |  | +      t->settings[SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
		
			
				|  |  |    s->write_closed = 0;
 | 
	
		
			
				|  |  |    s->read_closed = 0;
 | 
	
		
			
				|  |  |    s->cancelled = 0;
 | 
	
	
		
			
				|  | @@ -812,9 +822,10 @@ static int prepare_write(transport *t) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (t->dirtied_local_settings && !t->sent_local_settings) {
 | 
	
		
			
				|  |  |      gpr_slice_buffer_add(
 | 
	
		
			
				|  |  | -        &t->outbuf, grpc_chttp2_settings_create(t->settings[SENT_SETTINGS],
 | 
	
		
			
				|  |  | -                                                t->settings[LOCAL_SETTINGS],
 | 
	
		
			
				|  |  | -                                                GRPC_CHTTP2_NUM_SETTINGS));
 | 
	
		
			
				|  |  | +        &t->outbuf, grpc_chttp2_settings_create(
 | 
	
		
			
				|  |  | +                        t->settings[SENT_SETTINGS], t->settings[LOCAL_SETTINGS],
 | 
	
		
			
				|  |  | +                        t->force_send_settings, GRPC_CHTTP2_NUM_SETTINGS));
 | 
	
		
			
				|  |  | +    t->force_send_settings = 0;
 | 
	
		
			
				|  |  |      t->dirtied_local_settings = 0;
 | 
	
		
			
				|  |  |      t->sent_local_settings = 1;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -845,7 +856,9 @@ static int prepare_write(transport *t) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* for each stream that wants to update its window, add that window here */
 | 
	
		
			
				|  |  |    while ((s = stream_list_remove_head(t, WINDOW_UPDATE))) {
 | 
	
		
			
				|  |  | -    gpr_uint32 window_add = DEFAULT_WINDOW - s->incoming_window;
 | 
	
		
			
				|  |  | +    gpr_uint32 window_add =
 | 
	
		
			
				|  |  | +        t->settings[LOCAL_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] -
 | 
	
		
			
				|  |  | +        s->incoming_window;
 | 
	
		
			
				|  |  |      if (!s->read_closed && window_add) {
 | 
	
		
			
				|  |  |        gpr_slice_buffer_add(&t->outbuf,
 | 
	
		
			
				|  |  |                             grpc_chttp2_window_update_create(s->id, window_add));
 | 
	
	
		
			
				|  | @@ -854,8 +867,8 @@ static int prepare_write(transport *t) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* if the transport is ready to send a window update, do so here also */
 | 
	
		
			
				|  |  | -  if (t->incoming_window < DEFAULT_WINDOW / 2) {
 | 
	
		
			
				|  |  | -    gpr_uint32 window_add = DEFAULT_WINDOW - t->incoming_window;
 | 
	
		
			
				|  |  | +  if (t->incoming_window < t->connection_window_target * 3 / 4) {
 | 
	
		
			
				|  |  | +    gpr_uint32 window_add = t->connection_window_target - t->incoming_window;
 | 
	
		
			
				|  |  |      gpr_slice_buffer_add(&t->outbuf,
 | 
	
		
			
				|  |  |                           grpc_chttp2_window_update_create(0, window_add));
 | 
	
		
			
				|  |  |      t->incoming_window += window_add;
 | 
	
	
		
			
				|  | @@ -1017,7 +1030,11 @@ static void drop_connection(transport *t) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void maybe_join_window_updates(transport *t, stream *s) {
 | 
	
		
			
				|  |  | -  if (s->allow_window_updates && s->incoming_window < DEFAULT_WINDOW / 2) {
 | 
	
		
			
				|  |  | +  if (s->allow_window_updates &&
 | 
	
		
			
				|  |  | +      s->incoming_window <
 | 
	
		
			
				|  |  | +          t->settings[LOCAL_SETTINGS]
 | 
	
		
			
				|  |  | +                     [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] *
 | 
	
		
			
				|  |  | +              3 / 4) {
 | 
	
		
			
				|  |  |      stream_list_join(t, s, WINDOW_UPDATE);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 |