@@ -56,7 +56,7 @@ static struct aws_http_stream *s_connection_make_request(
5656static void s_connection_close (struct aws_http_connection * connection_base );
5757static bool s_connection_is_open (const struct aws_http_connection * connection_base );
5858static bool s_connection_new_requests_allowed (const struct aws_http_connection * connection_base );
59- static void s_connection_update_window (struct aws_http_connection * connection_base , size_t increment_size );
59+ static void s_connection_update_window (struct aws_http_connection * connection_base , uint32_t increment_size );
6060static int s_connection_change_settings (
6161 struct aws_http_connection * connection_base ,
6262 const struct aws_http2_setting * settings_array ,
@@ -268,6 +268,7 @@ static void s_stop(
268268
269269void aws_h2_connection_shutdown_due_to_write_err (struct aws_h2_connection * connection , int error_code ) {
270270 AWS_PRECONDITION (error_code );
271+ AWS_PRECONDITION (aws_channel_thread_is_callers_thread (connection -> base .channel_slot -> channel ));
271272
272273 if (connection -> thread_data .channel_shutdown_waiting_for_goaway_to_be_written ) {
273274 /* If shutdown is waiting for writes to complete, but writes are now broken,
@@ -2152,28 +2153,29 @@ static bool s_connection_new_requests_allowed(const struct aws_http_connection *
21522153 return new_stream_error_code == 0 ;
21532154}
21542155
2155- static void s_connection_update_window (struct aws_http_connection * connection_base , size_t increment_size ) {
2156+ static void s_connection_update_window (struct aws_http_connection * connection_base , uint32_t increment_size ) {
21562157 struct aws_h2_connection * connection = AWS_CONTAINER_OF (connection_base , struct aws_h2_connection , base );
21572158 if (!increment_size ) {
2159+ /* Silently do nothing. */
21582160 return ;
21592161 }
21602162 if (!connection_base -> manual_window_management ) {
2161- /* auto-mode, manual update window is not supported */
2163+ /* auto-mode, manual update window is not supported, silently do nothing with warning log. */
21622164 CONNECTION_LOG (
2163- WARN , connection , "Manual window management is off, update window operations are not supported." );
2165+ DEBUG , connection , "Manual window management is off, update window operations are not supported." );
21642166 return ;
21652167 }
2166- /* Type cast the increment size here, if overflow happens, we will detect it later, and the frame will be destroyed
2167- */
21682168 struct aws_h2_frame * connection_window_update_frame =
2169- aws_h2_frame_new_window_update (connection -> base .alloc , 0 , ( uint32_t ) increment_size );
2169+ aws_h2_frame_new_window_update (connection -> base .alloc , 0 , increment_size );
21702170 if (!connection_window_update_frame ) {
21712171 CONNECTION_LOGF (
21722172 ERROR ,
21732173 connection ,
21742174 "Failed to create WINDOW_UPDATE frame on connection, error %s" ,
21752175 aws_error_name (aws_last_error ()));
2176- return ;
2176+ /* OOM should result in a crash. And the increment size is too huge is the only other failure case, which will
2177+ * result in overflow. */
2178+ goto overflow ;
21772179 }
21782180
21792181 int err = 0 ;
@@ -2196,32 +2198,34 @@ static void s_connection_update_window(struct aws_http_connection *connection_ba
21962198 }
21972199 s_unlock_synced_data (connection );
21982200 } /* END CRITICAL SECTION */
2201+ if (err ) {
2202+ CONNECTION_LOG (
2203+ ERROR ,
2204+ connection ,
2205+ "The connection's flow-control windows has been incremented beyond 2**31 -1, the max for HTTP/2. The " );
2206+ aws_h2_frame_destroy (connection_window_update_frame );
2207+ goto overflow ;
2208+ }
21992209
22002210 if (cross_thread_work_should_schedule ) {
22012211 CONNECTION_LOG (TRACE , connection , "Scheduling cross-thread work task" );
22022212 aws_channel_schedule_task_now (connection -> base .channel_slot -> channel , & connection -> cross_thread_work_task );
22032213 }
22042214
22052215 if (!connection_open ) {
2206- CONNECTION_LOG (ERROR , connection , "Failed to update connection window, connection is closed or closing." );
2207- aws_raise_error (AWS_ERROR_INVALID_STATE );
2208- aws_h2_frame_destroy (connection_window_update_frame );
2209- return ;
2210- }
2211-
2212- if (err ) {
2213- /* The increment_size is still not 100% safe, since we cannot control the incoming data frame. So just
2214- * ruled out the value that is obviously wrong values */
2215- CONNECTION_LOGF (
2216- ERROR ,
2217- connection ,
2218- "The increment size is too big for HTTP/2 protocol, max flow-control "
2219- "window size is 2147483647. We got %zu, which will cause the flow-control window to exceed the maximum" ,
2220- increment_size );
2221- aws_raise_error (AWS_ERROR_INVALID_ARGUMENT );
2216+ /* connection already closed, just do nothing */
22222217 aws_h2_frame_destroy (connection_window_update_frame );
22232218 return ;
22242219 }
2220+ return ;
2221+ overflow :
2222+ /* Shutdown the connection as overflow detected */
2223+ s_stop (
2224+ connection ,
2225+ false /*stop_reading*/ ,
2226+ false /*stop_writing*/ ,
2227+ true /*schedule_shutdown*/ ,
2228+ AWS_ERROR_OVERFLOW_DETECTED );
22252229}
22262230
22272231static int s_connection_change_settings (
@@ -2371,7 +2375,9 @@ static int s_connection_send_goaway(
23712375 connection_open = connection -> synced_data .is_open ;
23722376 if (!connection_open ) {
23732377 s_unlock_synced_data (connection );
2374- goto closed ;
2378+ CONNECTION_LOG (DEBUG , connection , "Goaway not sent, connection is closed or closing." );
2379+ aws_mem_release (connection -> base .alloc , pending_goaway );
2380+ goto done ;
23752381 }
23762382 was_cross_thread_work_scheduled = connection -> synced_data .is_cross_thread_work_task_scheduled ;
23772383 connection -> synced_data .is_cross_thread_work_task_scheduled = true;
@@ -2392,12 +2398,8 @@ static int s_connection_send_goaway(
23922398 CONNECTION_LOG (TRACE , connection , "Scheduling cross-thread work task" );
23932399 aws_channel_schedule_task_now (connection -> base .channel_slot -> channel , & connection -> cross_thread_work_task );
23942400 }
2401+ done :
23952402 return AWS_OP_SUCCESS ;
2396-
2397- closed :
2398- CONNECTION_LOG (ERROR , connection , "Failed to send goaway, connection is closed or closing." );
2399- aws_mem_release (connection -> base .alloc , pending_goaway );
2400- return aws_raise_error (AWS_ERROR_INVALID_STATE );
24012403}
24022404
24032405static void s_get_settings_general (
0 commit comments