@@ -77,8 +77,10 @@ class Protocol:
77
77
Args:
78
78
side: :attr:`~Side.CLIENT` or :attr:`~Side.SERVER`.
79
79
state: Initial state of the WebSocket connection.
80
- max_size: Maximum size of incoming messages in bytes;
81
- :obj:`None` disables the limit.
80
+ max_size: Maximum size of incoming messages in bytes.
81
+ :obj:`None` disables the limit. You may pass a ``(max_message_size,
82
+ max_fragment_size)`` tuple to set different limits for messages and
83
+ fragments when you expect long messages sent in short fragments.
82
84
logger: Logger for this connection; depending on ``side``,
83
85
defaults to ``logging.getLogger("websockets.client")``
84
86
or ``logging.getLogger("websockets.server")``;
@@ -91,7 +93,7 @@ def __init__(
91
93
side : Side ,
92
94
* ,
93
95
state : State = OPEN ,
94
- max_size : int | None = 2 ** 20 ,
96
+ max_size : tuple [ int | None , int | None ] | int | None = 2 ** 20 ,
95
97
logger : LoggerLike | None = None ,
96
98
) -> None :
97
99
# Unique identifier. For logs.
@@ -114,11 +116,14 @@ def __init__(
114
116
self .state = state
115
117
116
118
# Maximum size of incoming messages in bytes.
117
- self .max_size = max_size
119
+ if isinstance (max_size , int ) or max_size is None :
120
+ self .max_message_size , self .max_fragment_size = max_size , None
121
+ else :
122
+ self .max_message_size , self .max_fragment_size = max_size
118
123
119
124
# Current size of incoming message in bytes. Only set while reading a
120
125
# fragmented message i.e. a data frames with the FIN bit not set.
121
- self .cur_size : int | None = None
126
+ self .current_size : int | None = None
122
127
123
128
# True while sending a fragmented message i.e. a data frames with the
124
129
# FIN bit not set.
@@ -578,12 +583,19 @@ def parse(self) -> Generator[None]:
578
583
# connection isn't closed cleanly.
579
584
raise EOFError ("unexpected end of stream" )
580
585
581
- if self .max_size is None :
582
- max_size = None
583
- elif self .cur_size is None :
584
- max_size = self .max_size
585
- else :
586
- max_size = self .max_size - self .cur_size
586
+ max_size = None
587
+
588
+ if self .max_message_size is not None :
589
+ if self .current_size is None :
590
+ max_size = self .max_message_size
591
+ else :
592
+ max_size = self .max_message_size - self .current_size
593
+
594
+ if self .max_fragment_size is not None :
595
+ if max_size is None :
596
+ max_size = self .max_fragment_size
597
+ else :
598
+ max_size = min (max_size , self .max_fragment_size )
587
599
588
600
# During a normal closure, execution ends here on the next
589
601
# iteration of the loop after receiving a close frame. At
@@ -613,7 +625,7 @@ def parse(self) -> Generator[None]:
613
625
self .parser_exc = exc
614
626
615
627
except PayloadTooBig as exc :
616
- exc .set_current_size (self .cur_size )
628
+ exc .set_current_size (self .current_size )
617
629
self .fail (CloseCode .MESSAGE_TOO_BIG , str (exc ))
618
630
self .parser_exc = exc
619
631
@@ -664,18 +676,18 @@ def recv_frame(self, frame: Frame) -> None:
664
676
665
677
"""
666
678
if frame .opcode is OP_TEXT or frame .opcode is OP_BINARY :
667
- if self .cur_size is not None :
679
+ if self .current_size is not None :
668
680
raise ProtocolError ("expected a continuation frame" )
669
681
if not frame .fin :
670
- self .cur_size = len (frame .data )
682
+ self .current_size = len (frame .data )
671
683
672
684
elif frame .opcode is OP_CONT :
673
- if self .cur_size is None :
685
+ if self .current_size is None :
674
686
raise ProtocolError ("unexpected continuation frame" )
675
687
if frame .fin :
676
- self .cur_size = None
688
+ self .current_size = None
677
689
else :
678
- self .cur_size += len (frame .data )
690
+ self .current_size += len (frame .data )
679
691
680
692
elif frame .opcode is OP_PING :
681
693
# 5.5.2. Ping: "Upon receipt of a Ping frame, an endpoint MUST
@@ -696,7 +708,7 @@ def recv_frame(self, frame: Frame) -> None:
696
708
assert self .close_sent is not None
697
709
self .close_rcvd_then_sent = False
698
710
699
- if self .cur_size is not None :
711
+ if self .current_size is not None :
700
712
raise ProtocolError ("incomplete fragmented message" )
701
713
702
714
# 5.5.1 Close: "If an endpoint receives a Close frame and did
0 commit comments