@@ -248,16 +248,17 @@ def _send_preamble(self):
248
248
# The server will also send an initial settings frame, so get it.
249
249
self ._recv_cb ()
250
250
251
- def close (self ):
251
+ def close (self , error_code = None ):
252
252
"""
253
253
Close the connection to the server.
254
254
255
+ :param error_code: (optional) The error code to reset all streams with.
255
256
:returns: Nothing.
256
257
"""
257
258
# Close all streams
258
259
for stream in list (self .streams .values ()):
259
260
log .debug ("Close stream %d" % stream .stream_id )
260
- stream .close ()
261
+ stream .close (error_code )
261
262
262
263
# Send GoAway frame to the server
263
264
try :
@@ -389,10 +390,14 @@ def receive_frame(self, frame):
389
390
if 'ACK' not in frame .flags :
390
391
self ._update_settings (frame )
391
392
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 )
396
401
elif frame .type == GoAwayFrame .type :
397
402
# If we get GoAway with error code zero, we are doing a graceful
398
403
# shutdown and all is well. Otherwise, throw an exception.
@@ -454,6 +459,12 @@ def _update_settings(self, frame):
454
459
new_size = frame .settings [SettingsFrame .SETTINGS_MAX_FRAME_SIZE ]
455
460
if new_size > FRAME_MAX_LEN and new_size < FRAME_MAX_ALLOWED_LEN :
456
461
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 )
457
468
458
469
def _new_stream (self , stream_id = None , local_closed = False ):
459
470
"""
@@ -536,15 +547,14 @@ def _consume_single_frame(self):
536
547
# Parse the header. We can use the returned memoryview directly here.
537
548
frame , length = Frame .parse_frame_header (header )
538
549
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 ):
542
551
log .warning (
543
552
"Frame size exceeded on stream %d (received: %d, max: %d)" ,
544
553
frame .stream_id ,
545
554
length ,
546
- frame_size
555
+ FRAME_MAX_LEN
547
556
)
557
+ self ._send_rst_frame (frame .stream_id , 6 ) # 6 = FRAME_SIZE_ERROR
548
558
549
559
# Read the remaining data from the socket.
550
560
data = self ._recv_payload (length )
@@ -646,12 +656,11 @@ def _recv_cb(self):
646
656
647
657
def _send_rst_frame (self , stream_id , error_code ):
648
658
"""
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.
650
660
"""
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 )
655
664
656
665
try :
657
666
del self .streams [stream_id ]
0 commit comments