| 
					
				 | 
			
			
				@@ -44,9 +44,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/string_util.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/useful.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include "src/core/ext/transport/chttp2/transport/http2_errors.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/ext/transport/chttp2/transport/internal.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include "src/core/ext/transport/chttp2/transport/status_conversion.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/ext/transport/chttp2/transport/varint.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/channel/channel_args.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/http/parser.h" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -55,7 +53,10 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/slice/slice_internal.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/slice/slice_string_helpers.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/support/string.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/lib/transport/error_utils.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/lib/transport/http2_errors.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/transport/static_metadata.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/lib/transport/status_conversion.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/transport/timeout_encoding.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/transport/transport_impl.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -409,7 +410,7 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           grpc_error_add_child(t->close_transport_on_writes_finished, error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!grpc_error_has_clear_grpc_status(error)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                  GRPC_STATUS_UNAVAILABLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -866,7 +867,6 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             (int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             (int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             desc, errstr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_error_free_string(errstr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (error != GRPC_ERROR_NONE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (closure->error_data.error == GRPC_ERROR_NONE) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -895,12 +895,9 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static bool contains_non_ok_status(grpc_metadata_batch *batch) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_linked_mdelem *l; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (l = batch->list.head; l; l = l->next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (l->md->key == GRPC_MDSTR_GRPC_STATUS && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        l->md != GRPC_MDELEM_GRPC_STATUS_0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (batch->idx.named.grpc_status != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return !grpc_mdelem_eq(batch->idx.named.grpc_status->md, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           GRPC_MDELEM_GRPC_STATUS_0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -980,9 +977,12 @@ static void log_metadata(const grpc_metadata_batch *md_batch, uint32_t id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                          bool is_client, bool is_initial) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (grpc_linked_mdelem *md = md_batch->list.head; md != md_batch->list.tail; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        md = md->next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    char *key = grpc_slice_to_c_string(GRPC_MDKEY(md->md)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    char *value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            is_client ? "CLI" : "SVR", grpc_mdstr_as_c_string(md->md->key), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            grpc_mdstr_as_c_string(md->md->value)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            is_client ? "CLI" : "SVR", key, value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_free(key); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_free(value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1025,11 +1025,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (op->cancel_error != GRPC_ERROR_NONE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_chttp2_cancel_stream(exec_ctx, t, s, GRPC_ERROR_REF(op->cancel_error)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (op->close_error != GRPC_ERROR_NONE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    close_from_api(exec_ctx, t, s, GRPC_ERROR_REF(op->close_error)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_chttp2_cancel_stream(exec_ctx, t, s, op->cancel_error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (op->send_initial_metadata != NULL) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1080,8 +1076,9 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         s->send_initial_metadata = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         grpc_chttp2_complete_closure_step( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             exec_ctx, t, s, &s->send_initial_metadata_finished, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            GRPC_ERROR_CREATE( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "Attempt to send initial metadata after stream was closed"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            GRPC_ERROR_CREATE_REFERENCING( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "Attempt to send initial metadata after stream was closed", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                &s->write_closed_error, 1), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             "send_initial_metadata_finished"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1093,7 +1090,9 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (s->write_closed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_chttp2_complete_closure_step( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           exec_ctx, t, s, &s->fetching_send_message_finished, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          GRPC_ERROR_CREATE("Attempt to send message after stream was closed"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          GRPC_ERROR_CREATE_REFERENCING( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              "Attempt to send message after stream was closed", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              &s->write_closed_error, 1), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           "fetching_send_message_finished"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       GPR_ASSERT(s->fetching_send_message == NULL); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1265,11 +1264,16 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        grpc_chttp2_error_code error, grpc_slice data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        grpc_error *error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)error, data, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            &t->qbuf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_http2_error_code http_error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const char *msg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_error_get_status(error, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL, &msg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        &http_error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            grpc_slice_from_copied_string(msg), &t->qbuf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_chttp2_initiate_write(exec_ctx, t, false, "goaway_sent"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GRPC_ERROR_UNREF(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1285,10 +1289,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         op->on_connectivity_state_change); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (op->send_goaway) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    send_goaway(exec_ctx, t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                grpc_chttp2_grpc_status_to_http2_error(op->goaway_status), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                grpc_slice_ref_internal(*op->goaway_message)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (op->goaway_error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    send_goaway(exec_ctx, t, op->goaway_error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (op->set_accept_stream) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1348,8 +1350,8 @@ void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[0], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                 s->recv_initial_metadata); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_chttp2_incoming_metadata_buffer_publish( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        exec_ctx, &s->metadata_buffer[0], s->recv_initial_metadata); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     null_then_run_closure(exec_ctx, &s->recv_initial_metadata_ready, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                           GRPC_ERROR_NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1392,8 +1394,8 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (s->all_incoming_byte_streams_finished && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         s->recv_trailing_metadata_finished != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[1], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                   s->recv_trailing_metadata); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_chttp2_incoming_metadata_buffer_publish( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          exec_ctx, &s->metadata_buffer[1], s->recv_trailing_metadata); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_chttp2_complete_closure_step( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           exec_ctx, t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           "recv_trailing_metadata_finished"); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1441,70 +1443,37 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   maybe_start_some_streams(exec_ctx, t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void status_codes_from_error(grpc_error *error, gpr_timespec deadline, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                    grpc_chttp2_error_code *http2_error, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                    grpc_status_code *grpc_status) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  intptr_t ip_http; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  intptr_t ip_grpc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool have_http = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &ip_http); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool have_grpc = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &ip_grpc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (have_http) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *http2_error = (grpc_chttp2_error_code)ip_http; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } else if (have_grpc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *http2_error = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        grpc_chttp2_grpc_status_to_http2_error((grpc_status_code)ip_grpc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *http2_error = GRPC_CHTTP2_INTERNAL_ERROR; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (have_grpc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *grpc_status = (grpc_status_code)ip_grpc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } else if (have_http) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *grpc_status = grpc_chttp2_http2_error_to_grpc_status( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        (grpc_chttp2_error_code)ip_http, deadline); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *grpc_status = GRPC_STATUS_INTERNAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                grpc_chttp2_transport *t, grpc_chttp2_stream *s, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                grpc_error *due_to_error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!s->read_closed || !s->write_closed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_status_code grpc_status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_chttp2_error_code http_error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    status_codes_from_error(due_to_error, s->deadline, &http_error, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            &grpc_status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!t->is_client && !s->sent_trailing_metadata && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_error_has_clear_grpc_status(due_to_error)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    close_from_api(exec_ctx, t, s, due_to_error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!s->read_closed || !s->write_closed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (s->id != 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_http2_error_code http_error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_error_get_status(due_to_error, s->deadline, NULL, NULL, &http_error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_slice_buffer_add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           &t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                   &s->stats.outgoing)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_chttp2_initiate_write(exec_ctx, t, false, "rst_stream"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const char *msg = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        grpc_error_get_str(due_to_error, GRPC_ERROR_STR_GRPC_MESSAGE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    bool free_msg = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (msg == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      free_msg = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      msg = grpc_error_string(due_to_error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_slice msg_slice = grpc_slice_from_copied_string(msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (free_msg) grpc_error_free_string(msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     s->seen_error = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, due_to_error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                             grpc_chttp2_stream *s, grpc_status_code status, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                             grpc_slice *slice) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                             grpc_chttp2_stream *s, grpc_error *error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_status_code status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const char *msg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_error_get_status(error, s->deadline, &status, &msg, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (status != GRPC_STATUS_OK) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     s->seen_error = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1518,24 +1487,21 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       s->recv_trailing_metadata_finished != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     char status_string[GPR_LTOA_MIN_BUFSIZE]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_ltoa(status, status_string); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_chttp2_incoming_metadata_buffer_add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        &s->metadata_buffer[1], grpc_mdelem_from_metadata_strings( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                    exec_ctx, GRPC_MDSTR_GRPC_STATUS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                    grpc_mdstr_from_string(status_string))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (slice) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      grpc_chttp2_incoming_metadata_buffer_add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          &s->metadata_buffer[1], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          grpc_mdelem_from_metadata_strings( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              grpc_mdstr_from_slice(exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                    grpc_slice_ref_internal(*slice)))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_chttp2_incoming_metadata_buffer_replace_or_add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        exec_ctx, &s->metadata_buffer[1], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                grpc_slice_from_copied_string(status_string))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (msg != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_chttp2_incoming_metadata_buffer_replace_or_add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          exec_ctx, &s->metadata_buffer[1], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  grpc_slice_from_copied_string(msg))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (slice) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_slice_unref_internal(exec_ctx, *slice); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GRPC_ERROR_UNREF(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1601,36 +1567,48 @@ void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                     int close_writes, grpc_error *error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (s->read_closed && s->write_closed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /* already closed */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     GRPC_ERROR_UNREF(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  bool closed_read = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  bool became_closed = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (close_reads && !s->read_closed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     s->read_closed_error = GRPC_ERROR_REF(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     s->read_closed = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (int i = 0; i < 2; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (s->published_metadata[i] == GRPC_METADATA_NOT_PUBLISHED) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        s->published_metadata[i] = GPRC_METADATA_PUBLISHED_AT_CLOSE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    decrement_active_streams_locked(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    closed_read = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (close_writes && !s->write_closed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     s->write_closed_error = GRPC_ERROR_REF(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     s->write_closed = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_chttp2_fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (s->read_closed && s->write_closed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    became_closed = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_error *overall_error = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        removal_error(GRPC_ERROR_REF(error), s, "Stream removed"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (s->id != 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      remove_stream(exec_ctx, t, s->id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    removal_error(GRPC_ERROR_REF(error), s, "Stream removed")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      remove_stream(exec_ctx, t, s->id, GRPC_ERROR_REF(overall_error)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       /* Purge streams waiting on concurrency still waiting for id assignment */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_chttp2_list_remove_waiting_for_concurrency(t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (overall_error != GRPC_ERROR_NONE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_chttp2_fake_status(exec_ctx, t, s, overall_error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (closed_read) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = 0; i < 2; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (s->published_metadata[i] == GRPC_METADATA_NOT_PUBLISHED) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        s->published_metadata[i] = GPRC_METADATA_PUBLISHED_AT_CLOSE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    decrement_active_streams_locked(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (became_closed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GRPC_ERROR_UNREF(error); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1644,112 +1622,92 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   uint8_t *p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   uint32_t len = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_status_code grpc_status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_chttp2_error_code http_error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  status_codes_from_error(error, s->deadline, &http_error, &grpc_status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const char *msg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_error_get_status(error, s->deadline, &grpc_status, &msg, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (s->id != 0 && !t->is_client) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /* Hand roll a header block. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       This is unnecessarily ugly - at some point we should find a more 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       elegant 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       solution. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       It's complicated by the fact that our send machinery would be dead by 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       time we got around to sending this, so instead we ignore HPACK 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       compression 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       and just write the uncompressed bytes onto the wire. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    p = GRPC_SLICE_START_PTR(status_hdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = 0x40; /* literal header */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = 11;   /* len(grpc-status) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Hand roll a header block. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     This is unnecessarily ugly - at some point we should find a more 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     elegant solution. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     It's complicated by the fact that our send machinery would be dead by 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     the time we got around to sending this, so instead we ignore HPACK 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     compression and just write the uncompressed bytes onto the wire. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  p = GRPC_SLICE_START_PTR(status_hdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 0x00; /* literal header, not indexed */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 11;   /* len(grpc-status) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 'g'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 'r'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 'p'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 'c'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = '-'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 's'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 't'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 'a'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 't'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 'u'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = 's'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (grpc_status < 10) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = (uint8_t)('0' + grpc_status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = (uint8_t)('0' + (grpc_status / 10)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = (uint8_t)('0' + (grpc_status % 10)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (msg != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    size_t msg_len = strlen(msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GPR_ASSERT(msg_len <= UINT32_MAX); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    message_pfx = grpc_slice_malloc(14 + msg_len_len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    p = GRPC_SLICE_START_PTR(message_pfx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = 0x00; /* literal header, not indexed */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = 12;   /* len(grpc-message) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *p++ = 'g'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *p++ = 'r'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *p++ = 'p'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *p++ = 'c'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *p++ = '-'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = 'm'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = 'e'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *p++ = 's'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = 't'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = 'a'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = 't'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = 'u'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *p++ = 's'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (grpc_status < 10) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = (uint8_t)('0' + grpc_status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = (uint8_t)('0' + (grpc_status / 10)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = (uint8_t)('0' + (grpc_status % 10)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const char *optional_message = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (optional_message != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      size_t msg_len = strlen(optional_message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      GPR_ASSERT(msg_len <= UINT32_MAX); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      message_pfx = grpc_slice_malloc(14 + msg_len_len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      p = GRPC_SLICE_START_PTR(message_pfx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 0x40; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 12; /* len(grpc-message) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 'g'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 'r'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 'p'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 'c'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = '-'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 'm'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 'e'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 's'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 's'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 'a'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 'g'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      *p++ = 'e'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 0, 0, p, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                               (uint32_t)msg_len_len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      p += msg_len_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      len += (uint32_t)msg_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    hdr = grpc_slice_malloc(9); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    p = GRPC_SLICE_START_PTR(hdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = (uint8_t)(len >> 16); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = (uint8_t)(len >> 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = (uint8_t)(len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = GRPC_CHTTP2_FRAME_HEADER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = (uint8_t)(s->id >> 24); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = (uint8_t)(s->id >> 16); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = (uint8_t)(s->id >> 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *p++ = (uint8_t)(s->id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_slice_buffer_add(&t->qbuf, hdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_slice_buffer_add(&t->qbuf, status_hdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (optional_message) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      grpc_slice_buffer_add(&t->qbuf, message_pfx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      grpc_slice_buffer_add(&t->qbuf, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            grpc_slice_from_copied_string(optional_message)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_slice_buffer_add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_CHTTP2_NO_ERROR, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                &s->stats.outgoing)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const char *msg = grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool free_msg = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (msg == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    free_msg = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    msg = grpc_error_string(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_slice msg_slice = grpc_slice_from_copied_string(msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (free_msg) grpc_error_free_string(msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = 'a'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = 'g'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *p++ = 'e'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 0, 0, p, (uint32_t)msg_len_len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    p += msg_len_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    len += (uint32_t)msg_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  hdr = grpc_slice_malloc(9); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  p = GRPC_SLICE_START_PTR(hdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = (uint8_t)(len >> 16); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = (uint8_t)(len >> 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = (uint8_t)(len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = GRPC_CHTTP2_FRAME_HEADER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = (uint8_t)(s->id >> 24); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = (uint8_t)(s->id >> 16); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = (uint8_t)(s->id >> 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *p++ = (uint8_t)(s->id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_slice_buffer_add(&t->qbuf, hdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_slice_buffer_add(&t->qbuf, status_hdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (msg != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_slice_buffer_add(&t->qbuf, message_pfx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_slice_buffer_add(&t->qbuf, grpc_slice_from_copied_string(msg)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_slice_buffer_add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                              &s->stats.outgoing)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_chttp2_initiate_write(exec_ctx, t, false, "close_from_api"); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1827,8 +1785,10 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (parse_error == GRPC_ERROR_NONE && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     error = grpc_error_set_int( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        GRPC_ERROR_CREATE("Trying to connect an http1.x server"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        GRPC_ERROR_INT_HTTP_STATUS, response.status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        grpc_error_set_int( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            GRPC_ERROR_CREATE("Trying to connect an http1.x server"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            GRPC_ERROR_INT_HTTP_STATUS, response.status), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GRPC_ERROR_UNREF(parse_error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2089,6 +2049,8 @@ static void incoming_byte_stream_publish_error( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_closure_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   bs->on_next = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GRPC_ERROR_UNREF(bs->error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_chttp2_cancel_stream(exec_ctx, bs->transport, bs->stream, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            GRPC_ERROR_REF(error)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   bs->error = error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2197,8 +2159,10 @@ static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               t->peer_string); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    send_goaway(exec_ctx, t, GRPC_CHTTP2_ENHANCE_YOUR_CALM, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                grpc_slice_from_static_string("Buffers full")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    send_goaway(exec_ctx, t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   GRPC_ERROR_INT_HTTP2_ERROR, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   GRPC_HTTP2_ENHANCE_YOUR_CALM)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_log(GPR_DEBUG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             "HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2227,7 +2191,7 @@ static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_chttp2_cancel_stream( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         exec_ctx, t, s, grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                            GRPC_ERROR_INT_HTTP2_ERROR, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                           GRPC_CHTTP2_ENHANCE_YOUR_CALM)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                           GRPC_HTTP2_ENHANCE_YOUR_CALM)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (n > 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       /* Since we cancel one stream per destructive reclamation, if 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          there are more streams left, we can immediately post a new 
			 |