| 
					
				 | 
			
			
				@@ -69,13 +69,21 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define DEFAULT_CLIENT_KEEPALIVE_TIME_S INT_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_S 20 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define DEFAULT_CLIENT_KEEPALIVE_TIME_MS INT_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_MS 20000 /* 20 seconds */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define DEFAULT_SERVER_KEEPALIVE_TIME_MS 7200000  /* 2 hours */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define DEFAULT_SERVER_KEEPALIVE_TIMEOUT_MS 20000 /* 20 seconds */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static int g_default_client_keepalive_time_s = DEFAULT_CLIENT_KEEPALIVE_TIME_S; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static int g_default_client_keepalive_timeout_s = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_S; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define KEEPALIVE_TIME_BACKOFF_MULTIPLIER 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int g_default_client_keepalive_time_ms = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    DEFAULT_CLIENT_KEEPALIVE_TIME_MS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int g_default_client_keepalive_timeout_ms = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_MS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int g_default_server_keepalive_time_ms = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    DEFAULT_SERVER_KEEPALIVE_TIME_MS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int g_default_server_keepalive_timeout_ms = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    DEFAULT_SERVER_KEEPALIVE_TIMEOUT_MS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static bool g_default_keepalive_permit_without_calls = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -153,6 +161,8 @@ static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define DEFAULT_MIN_TIME_BETWEEN_PINGS_MS 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define DEFAULT_MAX_PINGS_BETWEEN_DATA 3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define DEFAULT_MAX_PING_STRIKES 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** keepalive-relevant functions */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -351,19 +361,35 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       .max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       .min_time_between_pings = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           gpr_time_from_millis(DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, GPR_TIMESPAN), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      .max_ping_strikes = DEFAULT_MAX_PING_STRIKES, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      .min_ping_interval_without_data = gpr_time_from_millis( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS, GPR_TIMESPAN), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* client-side keepalive setting */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  t->keepalive_time = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      g_default_client_keepalive_time_s == INT_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          ? gpr_inf_future(GPR_TIMESPAN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          : gpr_time_from_seconds(g_default_client_keepalive_time_s, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                  GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  t->keepalive_timeout = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      g_default_client_keepalive_timeout_s == INT_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          ? gpr_inf_future(GPR_TIMESPAN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          : gpr_time_from_seconds(g_default_client_keepalive_timeout_s, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                  GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Keepalive setting */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (t->is_client) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    t->keepalive_time = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        g_default_client_keepalive_time_ms == INT_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ? gpr_inf_future(GPR_TIMESPAN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            : gpr_time_from_millis(g_default_client_keepalive_time_ms, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    t->keepalive_timeout = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        g_default_client_keepalive_timeout_ms == INT_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ? gpr_inf_future(GPR_TIMESPAN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            : gpr_time_from_millis(g_default_client_keepalive_timeout_ms, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    t->keepalive_time = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        g_default_server_keepalive_time_ms == INT_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ? gpr_inf_future(GPR_TIMESPAN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            : gpr_time_from_millis(g_default_server_keepalive_time_ms, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    t->keepalive_timeout = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        g_default_server_keepalive_timeout_ms == INT_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ? gpr_inf_future(GPR_TIMESPAN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            : gpr_time_from_millis(g_default_server_keepalive_timeout_ms, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   t->keepalive_permit_without_calls = g_default_keepalive_permit_without_calls; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (channel_args) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -396,6 +422,11 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             &channel_args->args[i], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             (grpc_integer_options){DEFAULT_MAX_PINGS_BETWEEN_DATA, 0, INT_MAX}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else if (0 == strcmp(channel_args->args[i].key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                             GRPC_ARG_HTTP2_MAX_PING_STRIKES)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        t->ping_policy.max_ping_strikes = grpc_channel_arg_get_integer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            &channel_args->args[i], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            (grpc_integer_options){DEFAULT_MAX_PING_STRIKES, 0, INT_MAX}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } else if (0 == strcmp(channel_args->args[i].key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                              GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         t->ping_policy.min_time_between_pings = gpr_time_from_millis( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -404,6 +435,15 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 (grpc_integer_options){DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                        INT_MAX}), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else if (0 == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 strcmp(channel_args->args[i].key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        GRPC_ARG_HTTP2_MIN_PING_INTERVAL_WITHOUT_DATA_MS)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        t->ping_policy.min_ping_interval_without_data = gpr_time_from_millis( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            grpc_channel_arg_get_integer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                &channel_args->args[i], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (grpc_integer_options){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS, 0, INT_MAX}), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } else if (0 == strcmp(channel_args->args[i].key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                              GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -414,23 +454,27 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         t->enable_bdp_probe = grpc_channel_arg_get_integer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             &channel_args->args[i], (grpc_integer_options){1, 0, 1}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } else if (0 == strcmp(channel_args->args[i].key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                             GRPC_ARG_CLIENT_KEEPALIVE_TIME_S)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                             GRPC_ARG_KEEPALIVE_TIME_MS)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const int value = grpc_channel_arg_get_integer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             &channel_args->args[i], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            (grpc_integer_options){g_default_client_keepalive_time_s, 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                   INT_MAX}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            (grpc_integer_options){t->is_client 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                       ? g_default_client_keepalive_time_ms 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                       : g_default_server_keepalive_time_ms, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   1, INT_MAX}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         t->keepalive_time = value == INT_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                 ? gpr_inf_future(GPR_TIMESPAN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                : gpr_time_from_seconds(value, GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                : gpr_time_from_millis(value, GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } else if (0 == strcmp(channel_args->args[i].key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                             GRPC_ARG_CLIENT_KEEPALIVE_TIMEOUT_S)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                             GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const int value = grpc_channel_arg_get_integer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             &channel_args->args[i], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            (grpc_integer_options){g_default_client_keepalive_timeout_s, 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                   INT_MAX}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            (grpc_integer_options){t->is_client 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                       ? g_default_client_keepalive_timeout_ms 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                       : g_default_server_keepalive_timeout_ms, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   0, INT_MAX}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         t->keepalive_timeout = value == INT_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                    ? gpr_inf_future(GPR_TIMESPAN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                   : gpr_time_from_seconds(value, GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   : gpr_time_from_millis(value, GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } else if (0 == strcmp(channel_args->args[i].key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                              GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         t->keepalive_permit_without_calls = 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -488,8 +532,11 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       t->ping_policy.max_pings_without_data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   t->ping_state.is_delayed_ping_timer_set = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /** Start client-side keepalive pings */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (t->is_client) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  t->ping_recv_state.ping_strikes = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Start keepalive pings */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (gpr_time_cmp(t->keepalive_time, gpr_inf_future(GPR_TIMESPAN)) != 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_timer_init( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -918,6 +965,26 @@ void grpc_chttp2_add_incoming_goaway(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // GRPC_CHTTP2_IF_TRACING( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   //     gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   t->seen_goaway = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * data equal to “too_many_pings”, it should log the occurrence at a log level 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * that is enabled by default and double the configured KEEPALIVE_TIME used 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * for new connections on that channel. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (t->is_client && goaway_error == GRPC_HTTP2_ENHANCE_YOUR_CALM && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_slice_str_cmp(goaway_text, "too_many_pings") == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_log(GPR_ERROR, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "Received a GOAWAY with error code ENHANCE_YOUR_CALM and debug " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "data equal to \"too_many_pings\""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    double current_keepalive_time_ms = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        gpr_timespec_to_micros(t->keepalive_time) / 1000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    t->keepalive_time = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        current_keepalive_time_ms > INT_MAX / KEEPALIVE_TIME_BACKOFF_MULTIPLIER 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ? gpr_inf_future(GPR_TIMESPAN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            : gpr_time_from_millis((int64_t)(current_keepalive_time_ms * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                             KEEPALIVE_TIME_BACKOFF_MULTIPLIER), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   GPR_TIMESPAN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* lie: use transient failure from the transport to indicate goaway has been 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    * received */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   connectivity_state_set( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1459,6 +1526,21 @@ static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GRPC_ERROR_UNREF(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void grpc_chttp2_add_ping_strike(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 grpc_chttp2_transport *t) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_log(GPR_DEBUG, "PING strike"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (++t->ping_recv_state.ping_strikes > t->ping_policy.max_ping_strikes && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      t->ping_policy.max_ping_strikes != 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    send_goaway(exec_ctx, t, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                grpc_error_set_int( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    GRPC_ERROR_CREATE_FROM_STATIC_STRING("too_many_pings"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_ENHANCE_YOUR_CALM)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /*The transport will be closed after the write is done */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    close_transport_locked( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        exec_ctx, t, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Too many pings")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                         void *stream_op, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                         grpc_error *error_ignored) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2125,6 +2207,10 @@ static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (grpc_http_trace) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_log(GPR_DEBUG, "%s: Start BDP ping", t->peer_string); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Reset the keepalive ping timer */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_bdp_estimator_start_ping(&t->bdp_estimator); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2139,20 +2225,32 @@ static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                               bool is_client) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (args) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for (i = 0; i < args->num_args; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (0 == strcmp(args->args[i].key, GRPC_ARG_CLIENT_KEEPALIVE_TIME_S)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        g_default_client_keepalive_time_s = grpc_channel_arg_get_integer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            &args->args[i], (grpc_integer_options){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                g_default_client_keepalive_time_s, 1, INT_MAX}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } else if (0 == strcmp(args->args[i].key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                             GRPC_ARG_CLIENT_KEEPALIVE_TIMEOUT_S)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        g_default_client_keepalive_timeout_s = grpc_channel_arg_get_integer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (0 == strcmp(args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const int value = grpc_channel_arg_get_integer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            &args->args[i], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            (grpc_integer_options){g_default_client_keepalive_time_ms, 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                   INT_MAX}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (is_client) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          g_default_client_keepalive_time_ms = value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          g_default_server_keepalive_time_ms = value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else if (0 == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 strcmp(args->args[i].key, GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const int value = grpc_channel_arg_get_integer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             &args->args[i], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            (grpc_integer_options){g_default_client_keepalive_timeout_s, 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            (grpc_integer_options){g_default_client_keepalive_timeout_ms, 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                    INT_MAX}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (is_client) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          g_default_client_keepalive_timeout_ms = value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          g_default_server_keepalive_timeout_ms = value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } else if (0 == strcmp(args->args[i].key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                              GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         g_default_keepalive_permit_without_calls = 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2170,7 +2268,8 @@ static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_chttp2_transport *t = arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (error == GRPC_ERROR_NONE && !(t->destroying || t->closed)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (t->keepalive_permit_without_calls || t->stream_map.count > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (t->keepalive_permit_without_calls || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        grpc_chttp2_stream_map_size(&t->stream_map) > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2183,6 +2282,13 @@ static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else if (error == GRPC_ERROR_CANCELLED && !(t->destroying || t->closed)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* The keepalive ping timer may be cancelled by bdp */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_timer_init( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        exec_ctx, &t->keepalive_ping_timer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "init keepalive ping"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2224,8 +2330,8 @@ static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                               "keepalive watchdog timeout")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /** The watchdog timer should have been cancelled by 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        finish_keepalive_ping_locked. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* The watchdog timer should have been cancelled by 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * finish_keepalive_ping_locked. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (error != GRPC_ERROR_CANCELLED) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING); 
			 |