|  | @@ -28,7 +28,7 @@
 | 
	
		
			
				|  |  |  #include "src/core/lib/support/string.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static uint32_t grpc_chttp2_target_announced_window(
 | 
	
		
			
				|  |  | -    const grpc_chttp2_transport* t);
 | 
	
		
			
				|  |  | +    const grpc_chttp2_transport_flowctl* tfc, uint32_t acked_local_window);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #ifndef NDEBUG
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -41,15 +41,18 @@ typedef struct {
 | 
	
		
			
				|  |  |    int64_t announced_window_delta;
 | 
	
		
			
				|  |  |  } shadow_flow_control;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void pretrace(shadow_flow_control* sfc, grpc_chttp2_transport* t,
 | 
	
		
			
				|  |  | -                     grpc_chttp2_stream* s) {
 | 
	
		
			
				|  |  | -  sfc->remote_window = t->remote_window;
 | 
	
		
			
				|  |  | -  sfc->target_window = grpc_chttp2_target_announced_window(t);
 | 
	
		
			
				|  |  | -  sfc->announced_window = t->announced_window;
 | 
	
		
			
				|  |  | -  if (s != NULL) {
 | 
	
		
			
				|  |  | -    sfc->remote_window_delta = s->remote_window_delta;
 | 
	
		
			
				|  |  | -    sfc->local_window_delta = s->local_window_delta;
 | 
	
		
			
				|  |  | -    sfc->announced_window_delta = s->announced_window_delta;
 | 
	
		
			
				|  |  | +static void pretrace(shadow_flow_control* shadow_fc,
 | 
	
		
			
				|  |  | +                     grpc_chttp2_transport_flowctl* tfc,
 | 
	
		
			
				|  |  | +                     grpc_chttp2_stream_flowctl* sfc) {
 | 
	
		
			
				|  |  | +  shadow_fc->remote_window = tfc->remote_window;
 | 
	
		
			
				|  |  | +  shadow_fc->target_window = grpc_chttp2_target_announced_window(
 | 
	
		
			
				|  |  | +      tfc, tfc->t->settings[GRPC_ACKED_SETTINGS]
 | 
	
		
			
				|  |  | +                           [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
 | 
	
		
			
				|  |  | +  shadow_fc->announced_window = tfc->announced_window;
 | 
	
		
			
				|  |  | +  if (sfc != NULL) {
 | 
	
		
			
				|  |  | +    shadow_fc->remote_window_delta = sfc->remote_window_delta;
 | 
	
		
			
				|  |  | +    shadow_fc->local_window_delta = sfc->local_window_delta;
 | 
	
		
			
				|  |  | +    shadow_fc->announced_window_delta = sfc->announced_window_delta;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -65,35 +68,39 @@ static char* fmt_str(int64_t old, int64_t new) {
 | 
	
		
			
				|  |  |    return str_lp;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void posttrace(shadow_flow_control* sfc, grpc_chttp2_transport* t,
 | 
	
		
			
				|  |  | -                      grpc_chttp2_stream* s, char* reason) {
 | 
	
		
			
				|  |  | +static void posttrace(shadow_flow_control* shadow_fc,
 | 
	
		
			
				|  |  | +                      grpc_chttp2_transport_flowctl* tfc,
 | 
	
		
			
				|  |  | +                      grpc_chttp2_stream_flowctl* sfc, char* reason) {
 | 
	
		
			
				|  |  |    uint32_t acked_local_window =
 | 
	
		
			
				|  |  | -      t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
		
			
				|  |  | +      tfc->t->settings[GRPC_SENT_SETTINGS]
 | 
	
		
			
				|  |  | +                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
		
			
				|  |  |    uint32_t remote_window =
 | 
	
		
			
				|  |  | -      t->settings[GRPC_PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
		
			
				|  |  | -  char* trw_str = fmt_str(sfc->remote_window, t->remote_window);
 | 
	
		
			
				|  |  | +      tfc->t->settings[GRPC_PEER_SETTINGS]
 | 
	
		
			
				|  |  | +                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
		
			
				|  |  | +  char* trw_str = fmt_str(shadow_fc->remote_window, tfc->remote_window);
 | 
	
		
			
				|  |  |    char* tlw_str =
 | 
	
		
			
				|  |  | -      fmt_str(sfc->target_window, grpc_chttp2_target_announced_window(t));
 | 
	
		
			
				|  |  | -  char* taw_str = fmt_str(sfc->announced_window, t->announced_window);
 | 
	
		
			
				|  |  | +      fmt_str(shadow_fc->target_window,
 | 
	
		
			
				|  |  | +              grpc_chttp2_target_announced_window(tfc, acked_local_window));
 | 
	
		
			
				|  |  | +  char* taw_str = fmt_str(shadow_fc->announced_window, tfc->announced_window);
 | 
	
		
			
				|  |  |    char* srw_str;
 | 
	
		
			
				|  |  |    char* slw_str;
 | 
	
		
			
				|  |  |    char* saw_str;
 | 
	
		
			
				|  |  | -  if (s != NULL) {
 | 
	
		
			
				|  |  | -    srw_str = fmt_str(sfc->remote_window_delta + remote_window,
 | 
	
		
			
				|  |  | -                      s->remote_window_delta + remote_window);
 | 
	
		
			
				|  |  | -    slw_str = fmt_str(sfc->local_window_delta + acked_local_window,
 | 
	
		
			
				|  |  | -                      s->local_window_delta + acked_local_window);
 | 
	
		
			
				|  |  | -    saw_str = fmt_str(sfc->announced_window_delta + acked_local_window,
 | 
	
		
			
				|  |  | -                      s->announced_window_delta + acked_local_window);
 | 
	
		
			
				|  |  | +  if (sfc != NULL) {
 | 
	
		
			
				|  |  | +    srw_str = fmt_str(shadow_fc->remote_window_delta + remote_window,
 | 
	
		
			
				|  |  | +                      sfc->remote_window_delta + remote_window);
 | 
	
		
			
				|  |  | +    slw_str = fmt_str(shadow_fc->local_window_delta + acked_local_window,
 | 
	
		
			
				|  |  | +                      sfc->local_window_delta + acked_local_window);
 | 
	
		
			
				|  |  | +    saw_str = fmt_str(shadow_fc->announced_window_delta + acked_local_window,
 | 
	
		
			
				|  |  | +                      sfc->announced_window_delta + acked_local_window);
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  |      srw_str = gpr_leftpad("", ' ', 30);
 | 
	
		
			
				|  |  |      slw_str = gpr_leftpad("", ' ', 30);
 | 
	
		
			
				|  |  |      saw_str = gpr_leftpad("", ' ', 30);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    gpr_log(GPR_DEBUG,
 | 
	
		
			
				|  |  | -          "%p[%u][%s] | %s | trw:%s, ttw:%s, taw:%s, srw:%s, slw:%s, saw:%s", t,
 | 
	
		
			
				|  |  | -          s != NULL ? s->id : 0, t->is_client ? "cli" : "svr", reason, trw_str,
 | 
	
		
			
				|  |  | -          tlw_str, taw_str, srw_str, slw_str, saw_str);
 | 
	
		
			
				|  |  | +          "%p[%u][%s] | %s | trw:%s, ttw:%s, taw:%s, srw:%s, slw:%s, saw:%s",
 | 
	
		
			
				|  |  | +          tfc, sfc != NULL ? sfc->s->id : 0, tfc->t->is_client ? "cli" : "svr",
 | 
	
		
			
				|  |  | +          reason, trw_str, tlw_str, taw_str, srw_str, slw_str, saw_str);
 | 
	
		
			
				|  |  |    gpr_free(trw_str);
 | 
	
		
			
				|  |  |    gpr_free(tlw_str);
 | 
	
		
			
				|  |  |    gpr_free(taw_str);
 | 
	
	
		
			
				|  | @@ -122,190 +129,190 @@ static void trace_action(grpc_chttp2_flowctl_action action) {
 | 
	
		
			
				|  |  |            urgency_to_string(action.send_stream_update));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define PRETRACE(t, s)     \
 | 
	
		
			
				|  |  | -  shadow_flow_control sfc; \
 | 
	
		
			
				|  |  | -  GRPC_FLOW_CONTROL_IF_TRACING(pretrace(&sfc, t, s))
 | 
	
		
			
				|  |  | -#define POSTTRACE(t, s, reason) \
 | 
	
		
			
				|  |  | -  GRPC_FLOW_CONTROL_IF_TRACING(posttrace(&sfc, t, s, reason))
 | 
	
		
			
				|  |  | +#define PRETRACE(tfc, sfc)       \
 | 
	
		
			
				|  |  | +  shadow_flow_control shadow_fc; \
 | 
	
		
			
				|  |  | +  GRPC_FLOW_CONTROL_IF_TRACING(pretrace(&shadow_fc, tfc, sfc))
 | 
	
		
			
				|  |  | +#define POSTTRACE(tfc, sfc, reason) \
 | 
	
		
			
				|  |  | +  GRPC_FLOW_CONTROL_IF_TRACING(posttrace(&shadow_fc, tfc, sfc, reason))
 | 
	
		
			
				|  |  |  #define TRACEACTION(action) GRPC_FLOW_CONTROL_IF_TRACING(trace_action(action))
 | 
	
		
			
				|  |  |  #else
 | 
	
		
			
				|  |  | -#define PRETRACE(t, s)
 | 
	
		
			
				|  |  | -#define POSTTRACE(t, s, reason)
 | 
	
		
			
				|  |  | +#define PRETRACE(tfc, sfc)
 | 
	
		
			
				|  |  | +#define POSTTRACE(tfc, sfc, reason)
 | 
	
		
			
				|  |  |  #define TRACEACTION(action)
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* How many bytes of incoming flow control would we like to advertise */
 | 
	
		
			
				|  |  |  static uint32_t grpc_chttp2_target_announced_window(
 | 
	
		
			
				|  |  | -    const grpc_chttp2_transport* t) {
 | 
	
		
			
				|  |  | +    const grpc_chttp2_transport_flowctl* tfc, uint32_t acked_init_window) {
 | 
	
		
			
				|  |  |    return (uint32_t)GPR_MIN(
 | 
	
		
			
				|  |  |        (int64_t)((1u << 31) - 1),
 | 
	
		
			
				|  |  | -      t->announced_stream_total_over_incoming_window +
 | 
	
		
			
				|  |  | -          t->settings[GRPC_ACKED_SETTINGS]
 | 
	
		
			
				|  |  | -                     [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
 | 
	
		
			
				|  |  | +      tfc->announced_stream_total_over_incoming_window + acked_init_window);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // we have sent data on the wire, we must track this in our bookkeeping for the
 | 
	
		
			
				|  |  |  // remote peer's flow control.
 | 
	
		
			
				|  |  | -void grpc_chttp2_flowctl_sent_data(grpc_chttp2_transport* t,
 | 
	
		
			
				|  |  | -                                   grpc_chttp2_stream* s, int64_t size) {
 | 
	
		
			
				|  |  | -  PRETRACE(t, s);
 | 
	
		
			
				|  |  | -  t->remote_window -= size;
 | 
	
		
			
				|  |  | -  s->remote_window_delta -= size;
 | 
	
		
			
				|  |  | -  POSTTRACE(t, s, "  data sent");
 | 
	
		
			
				|  |  | +void grpc_chttp2_flowctl_sent_data(grpc_chttp2_transport_flowctl* tfc,
 | 
	
		
			
				|  |  | +                                   grpc_chttp2_stream_flowctl* sfc,
 | 
	
		
			
				|  |  | +                                   int64_t size) {
 | 
	
		
			
				|  |  | +  PRETRACE(tfc, sfc);
 | 
	
		
			
				|  |  | +  tfc->remote_window -= size;
 | 
	
		
			
				|  |  | +  sfc->remote_window_delta -= size;
 | 
	
		
			
				|  |  | +  POSTTRACE(tfc, sfc, "  data sent");
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void announced_window_delta_preupdate(grpc_chttp2_transport* t,
 | 
	
		
			
				|  |  | -                                             grpc_chttp2_stream* s) {
 | 
	
		
			
				|  |  | -  if (s->announced_window_delta > 0) {
 | 
	
		
			
				|  |  | -    t->announced_stream_total_over_incoming_window -= s->announced_window_delta;
 | 
	
		
			
				|  |  | +static void announced_window_delta_preupdate(grpc_chttp2_transport_flowctl* tfc,
 | 
	
		
			
				|  |  | +                                             grpc_chttp2_stream_flowctl* sfc) {
 | 
	
		
			
				|  |  | +  if (sfc->announced_window_delta > 0) {
 | 
	
		
			
				|  |  | +    tfc->announced_stream_total_over_incoming_window -=
 | 
	
		
			
				|  |  | +        sfc->announced_window_delta;
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    t->announced_stream_total_under_incoming_window +=
 | 
	
		
			
				|  |  | -        -s->announced_window_delta;
 | 
	
		
			
				|  |  | +    tfc->announced_stream_total_under_incoming_window +=
 | 
	
		
			
				|  |  | +        -sfc->announced_window_delta;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void announced_window_delta_postupdate(grpc_chttp2_transport* t,
 | 
	
		
			
				|  |  | -                                              grpc_chttp2_stream* s) {
 | 
	
		
			
				|  |  | -  if (s->announced_window_delta > 0) {
 | 
	
		
			
				|  |  | -    t->announced_stream_total_over_incoming_window += s->announced_window_delta;
 | 
	
		
			
				|  |  | +static void announced_window_delta_postupdate(
 | 
	
		
			
				|  |  | +    grpc_chttp2_transport_flowctl* tfc, grpc_chttp2_stream_flowctl* sfc) {
 | 
	
		
			
				|  |  | +  if (sfc->announced_window_delta > 0) {
 | 
	
		
			
				|  |  | +    tfc->announced_stream_total_over_incoming_window +=
 | 
	
		
			
				|  |  | +        sfc->announced_window_delta;
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    t->announced_stream_total_under_incoming_window -=
 | 
	
		
			
				|  |  | -        -s->announced_window_delta;
 | 
	
		
			
				|  |  | +    tfc->announced_stream_total_under_incoming_window -=
 | 
	
		
			
				|  |  | +        -sfc->announced_window_delta;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // We have received data from the wire. We must track this in our own flow
 | 
	
		
			
				|  |  |  // control bookkeeping.
 | 
	
		
			
				|  |  |  // Returns an error if the incoming frame violates our flow control.
 | 
	
		
			
				|  |  | -grpc_error* grpc_chttp2_flowctl_recv_data(grpc_chttp2_transport* t,
 | 
	
		
			
				|  |  | -                                          grpc_chttp2_stream* s,
 | 
	
		
			
				|  |  | -                                          int64_t incoming_frame_size) {
 | 
	
		
			
				|  |  | -  PRETRACE(t, s);
 | 
	
		
			
				|  |  | -  if (incoming_frame_size > t->announced_window) {
 | 
	
		
			
				|  |  | +grpc_error* grpc_chttp2_flowctl_recv_data(grpc_chttp2_transport_flowctl* tfc,
 | 
	
		
			
				|  |  | +                                          grpc_chttp2_stream_flowctl* sfc,
 | 
	
		
			
				|  |  | +                                          int64_t incoming_frame_size,
 | 
	
		
			
				|  |  | +                                          uint32_t acked_init_window,
 | 
	
		
			
				|  |  | +                                          uint32_t sent_init_window) {
 | 
	
		
			
				|  |  | +  PRETRACE(tfc, sfc);
 | 
	
		
			
				|  |  | +  if (incoming_frame_size > tfc->announced_window) {
 | 
	
		
			
				|  |  |      char* msg;
 | 
	
		
			
				|  |  | -    gpr_asprintf(&msg, "frame of size %d overflows local window of %" PRId64,
 | 
	
		
			
				|  |  | -                 t->incoming_frame_size, t->announced_window);
 | 
	
		
			
				|  |  | +    gpr_asprintf(&msg,
 | 
	
		
			
				|  |  | +                 "frame of size %" PRId64 " overflows local window of %" PRId64,
 | 
	
		
			
				|  |  | +                 incoming_frame_size, tfc->announced_window);
 | 
	
		
			
				|  |  |      grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
 | 
	
		
			
				|  |  |      gpr_free(msg);
 | 
	
		
			
				|  |  |      return err;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // TODO(ncteisen): can this ever be null? ANSWER: only when incoming frame
 | 
	
		
			
				|  |  | -  // size is zero?
 | 
	
		
			
				|  |  | -  if (s != NULL) {
 | 
	
		
			
				|  |  | +  if (sfc != NULL) {
 | 
	
		
			
				|  |  |      int64_t acked_stream_window =
 | 
	
		
			
				|  |  | -        s->announced_window_delta +
 | 
	
		
			
				|  |  | -        t->settings[GRPC_ACKED_SETTINGS]
 | 
	
		
			
				|  |  | -                   [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
		
			
				|  |  | -    int64_t sent_stream_window =
 | 
	
		
			
				|  |  | -        s->announced_window_delta +
 | 
	
		
			
				|  |  | -        t->settings[GRPC_SENT_SETTINGS]
 | 
	
		
			
				|  |  | -                   [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
		
			
				|  |  | +        sfc->announced_window_delta + acked_init_window;
 | 
	
		
			
				|  |  | +    int64_t sent_stream_window = sfc->announced_window_delta + sent_init_window;
 | 
	
		
			
				|  |  |      if (incoming_frame_size > acked_stream_window) {
 | 
	
		
			
				|  |  |        if (incoming_frame_size <= sent_stream_window) {
 | 
	
		
			
				|  |  |          gpr_log(
 | 
	
		
			
				|  |  |              GPR_ERROR,
 | 
	
		
			
				|  |  | -            "Incoming frame of size %d exceeds local window size of %" PRId64
 | 
	
		
			
				|  |  | +            "Incoming frame of size %" PRId64
 | 
	
		
			
				|  |  | +            " exceeds local window size of %" PRId64
 | 
	
		
			
				|  |  |              ".\n"
 | 
	
		
			
				|  |  |              "The (un-acked, future) window size would be %" PRId64
 | 
	
		
			
				|  |  |              " which is not exceeded.\n"
 | 
	
		
			
				|  |  |              "This would usually cause a disconnection, but allowing it due to"
 | 
	
		
			
				|  |  |              "broken HTTP2 implementations in the wild.\n"
 | 
	
		
			
				|  |  |              "See (for example) https://github.com/netty/netty/issues/6520.",
 | 
	
		
			
				|  |  | -            t->incoming_frame_size, acked_stream_window, sent_stream_window);
 | 
	
		
			
				|  |  | +            incoming_frame_size, acked_stream_window, sent_stream_window);
 | 
	
		
			
				|  |  |        } else {
 | 
	
		
			
				|  |  |          char* msg;
 | 
	
		
			
				|  |  | -        gpr_asprintf(&msg,
 | 
	
		
			
				|  |  | -                     "frame of size %d overflows local window of %" PRId64,
 | 
	
		
			
				|  |  | -                     t->incoming_frame_size, acked_stream_window);
 | 
	
		
			
				|  |  | +        gpr_asprintf(&msg, "frame of size %" PRId64
 | 
	
		
			
				|  |  | +                           " overflows local window of %" PRId64,
 | 
	
		
			
				|  |  | +                     incoming_frame_size, acked_stream_window);
 | 
	
		
			
				|  |  |          grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
 | 
	
		
			
				|  |  |          gpr_free(msg);
 | 
	
		
			
				|  |  |          return err;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    announced_window_delta_preupdate(t, s);
 | 
	
		
			
				|  |  | -    s->announced_window_delta -= incoming_frame_size;
 | 
	
		
			
				|  |  | -    announced_window_delta_postupdate(t, s);
 | 
	
		
			
				|  |  | -    s->local_window_delta -= incoming_frame_size;
 | 
	
		
			
				|  |  | -    s->received_bytes += incoming_frame_size;
 | 
	
		
			
				|  |  | +    announced_window_delta_preupdate(tfc, sfc);
 | 
	
		
			
				|  |  | +    sfc->announced_window_delta -= incoming_frame_size;
 | 
	
		
			
				|  |  | +    announced_window_delta_postupdate(tfc, sfc);
 | 
	
		
			
				|  |  | +    sfc->local_window_delta -= incoming_frame_size;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  t->announced_window -= incoming_frame_size;
 | 
	
		
			
				|  |  | +  tfc->announced_window -= incoming_frame_size;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  POSTTRACE(t, s, "  data recv");
 | 
	
		
			
				|  |  | +  POSTTRACE(tfc, sfc, "  data recv");
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Returns a non zero announce integer if we should send a transport window
 | 
	
		
			
				|  |  |  // update
 | 
	
		
			
				|  |  |  uint32_t grpc_chttp2_flowctl_maybe_send_transport_update(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport* t) {
 | 
	
		
			
				|  |  | -  PRETRACE(t, NULL);
 | 
	
		
			
				|  |  | -  uint32_t target_announced_window = grpc_chttp2_target_announced_window(t);
 | 
	
		
			
				|  |  | +    grpc_chttp2_transport_flowctl* tfc, uint32_t acked_init_window,
 | 
	
		
			
				|  |  | +    bool has_outbuf) {
 | 
	
		
			
				|  |  | +  PRETRACE(tfc, NULL);
 | 
	
		
			
				|  |  | +  uint32_t target_announced_window =
 | 
	
		
			
				|  |  | +      grpc_chttp2_target_announced_window(tfc, acked_init_window);
 | 
	
		
			
				|  |  |    uint32_t threshold_to_send_transport_window_update =
 | 
	
		
			
				|  |  | -      t->outbuf.count > 0 ? 3 * target_announced_window / 4
 | 
	
		
			
				|  |  | -                          : target_announced_window / 2;
 | 
	
		
			
				|  |  | -  if (t->announced_window <= threshold_to_send_transport_window_update &&
 | 
	
		
			
				|  |  | -      t->announced_window != target_announced_window) {
 | 
	
		
			
				|  |  | +      has_outbuf ? 3 * target_announced_window / 4
 | 
	
		
			
				|  |  | +                 : target_announced_window / 2;
 | 
	
		
			
				|  |  | +  if (tfc->announced_window <= threshold_to_send_transport_window_update &&
 | 
	
		
			
				|  |  | +      tfc->announced_window != target_announced_window) {
 | 
	
		
			
				|  |  |      uint32_t announce = (uint32_t)GPR_CLAMP(
 | 
	
		
			
				|  |  | -        target_announced_window - t->announced_window, 0, UINT32_MAX);
 | 
	
		
			
				|  |  | -    t->announced_window += announce;
 | 
	
		
			
				|  |  | -    POSTTRACE(t, NULL, "t updt sent");
 | 
	
		
			
				|  |  | +        target_announced_window - tfc->announced_window, 0, UINT32_MAX);
 | 
	
		
			
				|  |  | +    tfc->announced_window += announce;
 | 
	
		
			
				|  |  | +    POSTTRACE(tfc, NULL, "t updt sent");
 | 
	
		
			
				|  |  |      return announce;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    GRPC_FLOW_CONTROL_IF_TRACING(
 | 
	
		
			
				|  |  | -      gpr_log(GPR_DEBUG, "%p[0][%s] will not to send transport update", t,
 | 
	
		
			
				|  |  | -              t->is_client ? "cli" : "svr"));
 | 
	
		
			
				|  |  | +      gpr_log(GPR_DEBUG, "%p[0][%s] will not send transport update", tfc,
 | 
	
		
			
				|  |  | +              tfc->t->is_client ? "cli" : "svr"));
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Returns a non zero announce integer if we should send a stream window update
 | 
	
		
			
				|  |  | -uint32_t grpc_chttp2_flowctl_maybe_send_stream_update(grpc_chttp2_stream* s) {
 | 
	
		
			
				|  |  | -  PRETRACE(s->t, s);
 | 
	
		
			
				|  |  | -  if (s->local_window_delta > s->announced_window_delta) {
 | 
	
		
			
				|  |  | +uint32_t grpc_chttp2_flowctl_maybe_send_stream_update(
 | 
	
		
			
				|  |  | +    grpc_chttp2_transport_flowctl* tfc, grpc_chttp2_stream_flowctl* sfc) {
 | 
	
		
			
				|  |  | +  PRETRACE(tfc, sfc);
 | 
	
		
			
				|  |  | +  if (sfc->local_window_delta > sfc->announced_window_delta) {
 | 
	
		
			
				|  |  |      uint32_t announce = (uint32_t)GPR_CLAMP(
 | 
	
		
			
				|  |  | -        s->local_window_delta - s->announced_window_delta, 0, UINT32_MAX);
 | 
	
		
			
				|  |  | -    announced_window_delta_preupdate(s->t, s);
 | 
	
		
			
				|  |  | -    s->announced_window_delta += announce;
 | 
	
		
			
				|  |  | -    announced_window_delta_postupdate(s->t, s);
 | 
	
		
			
				|  |  | -    POSTTRACE(s->t, s, "s updt sent");
 | 
	
		
			
				|  |  | +        sfc->local_window_delta - sfc->announced_window_delta, 0, UINT32_MAX);
 | 
	
		
			
				|  |  | +    announced_window_delta_preupdate(tfc, sfc);
 | 
	
		
			
				|  |  | +    sfc->announced_window_delta += announce;
 | 
	
		
			
				|  |  | +    announced_window_delta_postupdate(tfc, sfc);
 | 
	
		
			
				|  |  | +    POSTTRACE(tfc, sfc, "s updt sent");
 | 
	
		
			
				|  |  |      return announce;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    GRPC_FLOW_CONTROL_IF_TRACING(
 | 
	
		
			
				|  |  | -      gpr_log(GPR_DEBUG, "%p[%u][%s] will not to send stream update", s->t,
 | 
	
		
			
				|  |  | -              s->id, s->t->is_client ? "cli" : "svr"));
 | 
	
		
			
				|  |  | +      gpr_log(GPR_DEBUG, "%p[%u][%s] will not send stream update", tfc,
 | 
	
		
			
				|  |  | +              sfc->s->id, tfc->t->is_client ? "cli" : "svr"));
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // we have received a WINDOW_UPDATE frame for a transport
 | 
	
		
			
				|  |  | -void grpc_chttp2_flowctl_recv_transport_update(grpc_chttp2_transport* t,
 | 
	
		
			
				|  |  | -                                               uint32_t size) {
 | 
	
		
			
				|  |  | -  PRETRACE(t, NULL);
 | 
	
		
			
				|  |  | -  t->remote_window += size;
 | 
	
		
			
				|  |  | -  POSTTRACE(t, NULL, "t updt recv");
 | 
	
		
			
				|  |  | +void grpc_chttp2_flowctl_recv_transport_update(
 | 
	
		
			
				|  |  | +    grpc_chttp2_transport_flowctl* tfc, uint32_t size) {
 | 
	
		
			
				|  |  | +  PRETRACE(tfc, NULL);
 | 
	
		
			
				|  |  | +  tfc->remote_window += size;
 | 
	
		
			
				|  |  | +  POSTTRACE(tfc, NULL, "t updt recv");
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // we have received a WINDOW_UPDATE frame for a stream
 | 
	
		
			
				|  |  | -void grpc_chttp2_flowctl_recv_stream_update(grpc_chttp2_stream* s,
 | 
	
		
			
				|  |  | +void grpc_chttp2_flowctl_recv_stream_update(grpc_chttp2_transport_flowctl* tfc,
 | 
	
		
			
				|  |  | +                                            grpc_chttp2_stream_flowctl* sfc,
 | 
	
		
			
				|  |  |                                              uint32_t size) {
 | 
	
		
			
				|  |  | -  PRETRACE(s->t, s);
 | 
	
		
			
				|  |  | -  s->remote_window_delta += size;
 | 
	
		
			
				|  |  | -  POSTTRACE(s->t, s, "s updt recv");
 | 
	
		
			
				|  |  | +  PRETRACE(tfc, sfc);
 | 
	
		
			
				|  |  | +  sfc->remote_window_delta += size;
 | 
	
		
			
				|  |  | +  POSTTRACE(tfc, sfc, "s updt recv");
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void grpc_chttp2_flowctl_incoming_bs_update(grpc_chttp2_transport* t,
 | 
	
		
			
				|  |  | -                                            grpc_chttp2_stream* s,
 | 
	
		
			
				|  |  | +void grpc_chttp2_flowctl_incoming_bs_update(grpc_chttp2_transport_flowctl* tfc,
 | 
	
		
			
				|  |  | +                                            grpc_chttp2_stream_flowctl* sfc,
 | 
	
		
			
				|  |  | +                                            uint32_t sent_init_window,
 | 
	
		
			
				|  |  |                                              size_t max_size_hint,
 | 
	
		
			
				|  |  |                                              size_t have_already) {
 | 
	
		
			
				|  |  | -  PRETRACE(t, s);
 | 
	
		
			
				|  |  | +  PRETRACE(tfc, sfc);
 | 
	
		
			
				|  |  |    uint32_t max_recv_bytes;
 | 
	
		
			
				|  |  | -  uint32_t initial_window_size =
 | 
	
		
			
				|  |  | -      t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* clamp max recv hint to an allowable size */
 | 
	
		
			
				|  |  | -  if (max_size_hint >= UINT32_MAX - initial_window_size) {
 | 
	
		
			
				|  |  | -    max_recv_bytes = UINT32_MAX - initial_window_size;
 | 
	
		
			
				|  |  | +  if (max_size_hint >= UINT32_MAX - sent_init_window) {
 | 
	
		
			
				|  |  | +    max_recv_bytes = UINT32_MAX - sent_init_window;
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  |      max_recv_bytes = (uint32_t)max_size_hint;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -318,34 +325,38 @@ void grpc_chttp2_flowctl_incoming_bs_update(grpc_chttp2_transport* t,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* add some small lookahead to keep pipelines flowing */
 | 
	
		
			
				|  |  | -  GPR_ASSERT(max_recv_bytes <= UINT32_MAX - initial_window_size);
 | 
	
		
			
				|  |  | -  if (s->local_window_delta < max_recv_bytes && !s->read_closed) {
 | 
	
		
			
				|  |  | +  GPR_ASSERT(max_recv_bytes <= UINT32_MAX - sent_init_window);
 | 
	
		
			
				|  |  | +  if (sfc->local_window_delta < max_recv_bytes) {
 | 
	
		
			
				|  |  |      uint32_t add_max_recv_bytes =
 | 
	
		
			
				|  |  | -        (uint32_t)(max_recv_bytes - s->local_window_delta);
 | 
	
		
			
				|  |  | -    s->local_window_delta += add_max_recv_bytes;
 | 
	
		
			
				|  |  | +        (uint32_t)(max_recv_bytes - sfc->local_window_delta);
 | 
	
		
			
				|  |  | +    sfc->local_window_delta += add_max_recv_bytes;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  POSTTRACE(t, s, "app st recv");
 | 
	
		
			
				|  |  | +  POSTTRACE(tfc, sfc, "app st recv");
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void grpc_chttp2_flowctl_destroy_stream(grpc_chttp2_stream* s) {
 | 
	
		
			
				|  |  | -  announced_window_delta_preupdate(s->t, s);
 | 
	
		
			
				|  |  | +void grpc_chttp2_flowctl_destroy_stream(grpc_chttp2_transport_flowctl* tfc,
 | 
	
		
			
				|  |  | +                                        grpc_chttp2_stream_flowctl* sfc) {
 | 
	
		
			
				|  |  | +  announced_window_delta_preupdate(tfc, sfc);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  grpc_chttp2_flowctl_action grpc_chttp2_flowctl_get_action(
 | 
	
		
			
				|  |  | -    const grpc_chttp2_transport* t, const grpc_chttp2_stream* s) {
 | 
	
		
			
				|  |  | +    const grpc_chttp2_transport_flowctl* tfc,
 | 
	
		
			
				|  |  | +    const grpc_chttp2_stream_flowctl* sfc, bool stream_read_closed,
 | 
	
		
			
				|  |  | +    uint32_t sent_init_window) {
 | 
	
		
			
				|  |  |    grpc_chttp2_flowctl_action action;
 | 
	
		
			
				|  |  |    memset(&action, 0, sizeof(action));
 | 
	
		
			
				|  |  | -  uint32_t target_announced_window = grpc_chttp2_target_announced_window(t);
 | 
	
		
			
				|  |  | -  int64_t init_window =
 | 
	
		
			
				|  |  | -      t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 | 
	
		
			
				|  |  | -  if (t->announced_window < target_announced_window / 2) {
 | 
	
		
			
				|  |  | +  uint32_t target_announced_window =
 | 
	
		
			
				|  |  | +      grpc_chttp2_target_announced_window(tfc, sent_init_window);
 | 
	
		
			
				|  |  | +  if (tfc->announced_window < target_announced_window / 2) {
 | 
	
		
			
				|  |  |      action.send_transport_update = GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (s != NULL && !s->read_closed) {
 | 
	
		
			
				|  |  | -    if ((int64_t)s->local_window_delta > (int64_t)s->announced_window_delta &&
 | 
	
		
			
				|  |  | -        (int64_t)s->announced_window_delta <= -init_window / 2) {
 | 
	
		
			
				|  |  | +  if (sfc != NULL && !stream_read_closed) {
 | 
	
		
			
				|  |  | +    if ((int64_t)sfc->local_window_delta >
 | 
	
		
			
				|  |  | +            (int64_t)sfc->announced_window_delta &&
 | 
	
		
			
				|  |  | +        (int64_t)sfc->announced_window_delta + sent_init_window <=
 | 
	
		
			
				|  |  | +            sent_init_window / 2) {
 | 
	
		
			
				|  |  |        action.send_stream_update = GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY;
 | 
	
		
			
				|  |  | -    } else if (s->local_window_delta > s->announced_window_delta) {
 | 
	
		
			
				|  |  | +    } else if (sfc->local_window_delta > sfc->announced_window_delta) {
 | 
	
		
			
				|  |  |        action.send_stream_update = GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 |