@@ -248,16 +248,17 @@ def _send_preamble(self):
248248 # The server will also send an initial settings frame, so get it.
249249 self ._recv_cb ()
250250
251- def close (self ):
251+ def close (self , error_code = None ):
252252 """
253253 Close the connection to the server.
254254
255+ :param error_code: (optional) The error code to reset all streams with.
255256 :returns: Nothing.
256257 """
257258 # Close all streams
258259 for stream in list (self .streams .values ()):
259260 log .debug ("Close stream %d" % stream .stream_id )
260- stream .close ()
261+ stream .close (error_code )
261262
262263 # Send GoAway frame to the server
263264 try :
@@ -389,10 +390,14 @@ def receive_frame(self, frame):
389390 if 'ACK' not in frame .flags :
390391 self ._update_settings (frame )
391392
392- # Need to return an ack.
393- f = SettingsFrame (0 )
394- f .flags .add ('ACK' )
395- self ._send_cb (f )
393+ # When the setting containing the max frame size value is out
394+ # of range, the spec dictates to tear down the connection.
395+ # Therefore we make sure the socket is still alive before
396+ # returning the ack.
397+ if self ._sock is not None :
398+ f = SettingsFrame (0 )
399+ f .flags .add ('ACK' )
400+ self ._send_cb (f )
396401 elif frame .type == GoAwayFrame .type :
397402 # If we get GoAway with error code zero, we are doing a graceful
398403 # shutdown and all is well. Otherwise, throw an exception.
@@ -454,6 +459,12 @@ def _update_settings(self, frame):
454459 new_size = frame .settings [SettingsFrame .SETTINGS_MAX_FRAME_SIZE ]
455460 if new_size > FRAME_MAX_LEN and new_size < FRAME_MAX_ALLOWED_LEN :
456461 self ._settings [SettingsFrame .SETTINGS_MAX_FRAME_SIZE ] = new_size
462+ else :
463+ log .warning (
464+ "Frame size %d is outside of allowed range" ,
465+ new_size )
466+ # Tear the connection down with error code PROTOCOL_ERROR
467+ self .close (1 )
457468
458469 def _new_stream (self , stream_id = None , local_closed = False ):
459470 """
@@ -536,15 +547,14 @@ def _consume_single_frame(self):
536547 # Parse the header. We can use the returned memoryview directly here.
537548 frame , length = Frame .parse_frame_header (header )
538549
539- frame_size = self ._settings [SettingsFrame .SETTINGS_MAX_FRAME_SIZE ]
540- if (length > frame_size ):
541- self ._send_rst_frame (frame .stream_id , 6 ) # 6 = FRAME_SIZE_ERROR
550+ if (length > FRAME_MAX_LEN ):
542551 log .warning (
543552 "Frame size exceeded on stream %d (received: %d, max: %d)" ,
544553 frame .stream_id ,
545554 length ,
546- frame_size
555+ FRAME_MAX_LEN
547556 )
557+ self ._send_rst_frame (frame .stream_id , 6 ) # 6 = FRAME_SIZE_ERROR
548558
549559 # Read the remaining data from the socket.
550560 data = self ._recv_payload (length )
@@ -646,12 +656,11 @@ def _recv_cb(self):
646656
647657 def _send_rst_frame (self , stream_id , error_code ):
648658 """
649- Send reset stream frame with error code and remove stream from map.
659+ Send reset stream frame with error code and remove stream from map.
650660 """
651- if error_code is not None :
652- f = RstStreamFrame (stream_id )
653- f .error_code = error_code
654- self ._send_cb (f )
661+ f = RstStreamFrame (stream_id )
662+ f .error_code = error_code
663+ self ._send_cb (f )
655664
656665 try :
657666 del self .streams [stream_id ]
0 commit comments