| 
					
				 | 
			
			
				@@ -44,6 +44,8 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/useful.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/slice/slice_internal.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define WRITE_BUFFER_SIZE (2 * 1024 * 1024) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 typedef struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_endpoint base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   double bytes_per_second; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -55,6 +57,7 @@ typedef struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice_buffer writing_buffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_error *error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   bool writing; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_closure *write_cb; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } trickle_endpoint; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void te_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -63,6 +66,15 @@ static void te_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_endpoint_read(exec_ctx, te->wrapped, slices, cb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void maybe_call_write_cb_locked(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                       trickle_endpoint *te) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (te->write_cb != NULL && (te->error != GRPC_ERROR_NONE || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                               te->write_buffer.length <= WRITE_BUFFER_SIZE)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_closure_sched(exec_ctx, te->write_cb, GRPC_ERROR_REF(te->error)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    te->write_cb = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void te_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                      grpc_slice_buffer *slices, grpc_closure *cb) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   trickle_endpoint *te = (trickle_endpoint *)ep; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -70,11 +82,13 @@ static void te_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_slice_ref_internal(slices->slices[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_lock(&te->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(te->write_cb == NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (te->write_buffer.length == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     te->last_write = gpr_now(GPR_CLOCK_MONOTONIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice_buffer_addn(&te->write_buffer, slices->slices, slices->count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_REF(te->error)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  te->write_cb = cb; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  maybe_call_write_cb_locked(exec_ctx, te); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_unlock(&te->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -102,6 +116,7 @@ static void te_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (te->error == GRPC_ERROR_NONE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     te->error = GRPC_ERROR_REF(why); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  maybe_call_write_cb_locked(exec_ctx, te); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_unlock(&te->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_endpoint_shutdown(exec_ctx, te->wrapped, why); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -157,6 +172,7 @@ grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   te->base.vtable = &vtable; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   te->wrapped = wrap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   te->bytes_per_second = bytes_per_second; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  te->write_cb = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_init(&te->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice_buffer_init(&te->write_buffer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice_buffer_init(&te->writing_buffer); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -187,6 +203,7 @@ size_t grpc_trickle_endpoint_trickle(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_endpoint_write( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           exec_ctx, te->wrapped, &te->writing_buffer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           grpc_closure_create(te_finish_write, te, grpc_schedule_on_exec_ctx)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      maybe_call_write_cb_locked(exec_ctx, te); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t backlog = te->write_buffer.length; 
			 |