|  | @@ -113,6 +113,10 @@ static void cancel_from_api(grpc_chttp2_transport_global *transport_global,
 | 
	
		
			
				|  |  |  static void add_to_pollset_locked(grpc_chttp2_transport *t,
 | 
	
		
			
				|  |  |                                    grpc_pollset *pollset);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/** Start new streams that have been created if we can */
 | 
	
		
			
				|  |  | +static void maybe_start_some_streams(
 | 
	
		
			
				|  |  | +    grpc_chttp2_transport_global *transport_global);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /*
 | 
	
		
			
				|  |  |   * CONSTRUCTION/DESTRUCTION/REFCOUNTING
 | 
	
		
			
				|  |  |   */
 | 
	
	
		
			
				|  | @@ -489,6 +493,16 @@ static void unlock(grpc_chttp2_transport *t) {
 | 
	
		
			
				|  |  |    /* unlock_check_parser(t); */
 | 
	
		
			
				|  |  |    unlock_check_channel_callbacks(t);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  if (!t->parsing_active) {
 | 
	
		
			
				|  |  | +    size_t new_stream_count =
 | 
	
		
			
				|  |  | +        grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
 | 
	
		
			
				|  |  | +        grpc_chttp2_stream_map_size(&t->new_stream_map);
 | 
	
		
			
				|  |  | +    if (new_stream_count != t->global.concurrent_stream_count) {
 | 
	
		
			
				|  |  | +      t->global.concurrent_stream_count = new_stream_count;
 | 
	
		
			
				|  |  | +      maybe_start_some_streams(&t->global);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    run_closures = t->global.pending_closures;
 | 
	
		
			
				|  |  |    t->global.pending_closures = NULL;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -556,8 +570,11 @@ static void writing_action(void *gt, int iomgr_success_ignored) {
 | 
	
		
			
				|  |  |  void grpc_chttp2_add_incoming_goaway(
 | 
	
		
			
				|  |  |      grpc_chttp2_transport_global *transport_global, gpr_uint32 goaway_error,
 | 
	
		
			
				|  |  |      gpr_slice goaway_text) {
 | 
	
		
			
				|  |  | +  char *msg = gpr_hexdump((char*)GPR_SLICE_START_PTR(goaway_text), GPR_SLICE_LENGTH(goaway_text), GPR_HEXDUMP_PLAINTEXT);
 | 
	
		
			
				|  |  | +  gpr_log(GPR_DEBUG, "add goaway: st=%d err=%d text=%s", transport_global->goaway_state, goaway_error, msg);
 | 
	
		
			
				|  |  | +  gpr_free(msg);
 | 
	
		
			
				|  |  |    if (transport_global->goaway_state == GRPC_CHTTP2_ERROR_STATE_NONE) {
 | 
	
		
			
				|  |  | -    transport_global->goaway_state = GRPC_CHTTP2_ERROR_STATE_NOTIFIED;
 | 
	
		
			
				|  |  | +    transport_global->goaway_state = GRPC_CHTTP2_ERROR_STATE_SEEN;
 | 
	
		
			
				|  |  |      transport_global->goaway_text = goaway_text;
 | 
	
		
			
				|  |  |      transport_global->goaway_error = goaway_error;
 | 
	
		
			
				|  |  |    } else {
 | 
	
	
		
			
				|  | @@ -568,6 +585,7 @@ void grpc_chttp2_add_incoming_goaway(
 | 
	
		
			
				|  |  |  static void maybe_start_some_streams(
 | 
	
		
			
				|  |  |      grpc_chttp2_transport_global *transport_global) {
 | 
	
		
			
				|  |  |    grpc_chttp2_stream_global *stream_global;
 | 
	
		
			
				|  |  | +  gpr_log(GPR_DEBUG, "nextid=%d count=%d", transport_global->next_stream_id, transport_global->concurrent_stream_count);
 | 
	
		
			
				|  |  |    /* start streams where we have free grpc_chttp2_stream ids and free
 | 
	
		
			
				|  |  |     * concurrency */
 | 
	
		
			
				|  |  |    while (transport_global->next_stream_id <= MAX_CLIENT_STREAM_ID &&
 | 
	
	
		
			
				|  | @@ -581,15 +599,16 @@ static void maybe_start_some_streams(
 | 
	
		
			
				|  |  |                         transport_global->is_client ? "CLI" : "SVR",
 | 
	
		
			
				|  |  |                         stream_global, transport_global->next_stream_id));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (transport_global->next_stream_id == MAX_CLIENT_STREAM_ID) {
 | 
	
		
			
				|  |  | +    GPR_ASSERT(stream_global->id == 0);
 | 
	
		
			
				|  |  | +    stream_global->id = transport_global->next_stream_id;
 | 
	
		
			
				|  |  | +    transport_global->next_stream_id += 2;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
 | 
	
		
			
				|  |  |        grpc_chttp2_add_incoming_goaway(
 | 
	
		
			
				|  |  |            transport_global, GRPC_CHTTP2_NO_ERROR,
 | 
	
		
			
				|  |  |            gpr_slice_from_copied_string("Exceeded sequence number limit"));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    GPR_ASSERT(stream_global->id == 0);
 | 
	
		
			
				|  |  | -    stream_global->id = transport_global->next_stream_id;
 | 
	
		
			
				|  |  | -    transport_global->next_stream_id += 2;
 | 
	
		
			
				|  |  |      stream_global->outgoing_window =
 | 
	
		
			
				|  |  |          transport_global
 | 
	
		
			
				|  |  |              ->settings[PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
	
		
			
				|  | @@ -606,7 +625,7 @@ static void maybe_start_some_streams(
 | 
	
		
			
				|  |  |      grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    /* cancel out streams that will never be started */
 | 
	
		
			
				|  |  | -  while (transport_global->next_stream_id > MAX_CLIENT_STREAM_ID &&
 | 
	
		
			
				|  |  | +  while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID &&
 | 
	
		
			
				|  |  |           grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
 | 
	
		
			
				|  |  |                                                        &stream_global)) {
 | 
	
		
			
				|  |  |      cancel_from_api(transport_global, stream_global, GRPC_STATUS_UNAVAILABLE);
 | 
	
	
		
			
				|  | @@ -1000,8 +1019,6 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices,
 | 
	
		
			
				|  |  |                                           &t->parsing_stream_map);
 | 
	
		
			
				|  |  |          /* handle higher level things */
 | 
	
		
			
				|  |  |          grpc_chttp2_publish_reads(&t->global, &t->parsing);
 | 
	
		
			
				|  |  | -        t->global.concurrent_stream_count =
 | 
	
		
			
				|  |  | -            grpc_chttp2_stream_map_size(&t->parsing_stream_map);
 | 
	
		
			
				|  |  |          t->parsing_active = 0;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        if (i == nslices) {
 | 
	
	
		
			
				|  | @@ -1059,6 +1076,7 @@ static void unlock_check_channel_callbacks(grpc_chttp2_transport *t) {
 | 
	
		
			
				|  |  |      if (t->global.goaway_state == GRPC_CHTTP2_ERROR_STATE_SEEN &&
 | 
	
		
			
				|  |  |          t->global.error_state != GRPC_CHTTP2_ERROR_STATE_NOTIFIED) {
 | 
	
		
			
				|  |  |        notify_goaways_args *a = gpr_malloc(sizeof(*a));
 | 
	
		
			
				|  |  | +      a->t = t;
 | 
	
		
			
				|  |  |        a->error = t->global.goaway_error;
 | 
	
		
			
				|  |  |        a->text = t->global.goaway_text;
 | 
	
		
			
				|  |  |        t->global.goaway_state = GRPC_CHTTP2_ERROR_STATE_NOTIFIED;
 |