]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Invert fragment-handling logic for clarity
authorBen Darnell <ben@bendarnell.com>
Fri, 30 Dec 2011 21:29:12 +0000 (13:29 -0800)
committerBen Darnell <ben@bendarnell.com>
Fri, 30 Dec 2011 21:29:12 +0000 (13:29 -0800)
tornado/websocket.py

index 8c72ba33703c6726595148784149f42c8575380e..3e23101899b79cc333acdac788580685b97d8120 100644 (file)
@@ -463,44 +463,37 @@ class WebSocketProtocol8(WebSocketProtocol):
         for i in xrange(len(data)):
             unmasked[i] = unmasked[i] ^ self._frame_mask[i % 4]
 
-        if not self._final_frame:
-            if self._frame_opcode_is_control:
+        if self._frame_opcode_is_control:
+            # control frames may be interleaved with a series of fragmented
+            # data frames, so control frames must not interact with
+            # self._fragmented_*
+            if not self._final_frame:
                 # control frames must not be fragmented
                 self._abort()
                 return
+            opcode = self._frame_opcode
+        elif self._frame_opcode == 0:  # continuation frame
+            if self._fragmented_message_buffer is None:
+                # nothing to continue
+                self._abort()
+                return
+            self._fragmented_message_buffer += unmasked
+            if self._final_frame:
+                opcode = self._fragmented_message_opcode
+                unmasked = self._fragmented_message_buffer
+                self._fragmented_message_buffer = None
+        else:  # start of new data message
             if self._fragmented_message_buffer is not None:
-                if self._frame_opcode != 0:
-                    # continuation frames must have opcode 0
-                    self._abort()
-                    return
-                self._fragmented_message_buffer += unmasked
+                # can't start new message until the old one is finished
+                self._abort()
+                return
+            if self._final_frame:
+                opcode = self._frame_opcode
             else:
-                if self._frame_opcode == 0:
-                    # continuation frame but nothing to continue
-                    self._abort()
-                    return
                 self._fragmented_message_opcode = self._frame_opcode
                 self._fragmented_message_buffer = unmasked
-        else:
-            if self._frame_opcode == 0:
-                if self._fragmented_message_buffer is None:
-                    # continuation frame but nothing to continue
-                    self._abort()
-                    return
-                unmasked = self._fragmented_message_buffer + unmasked
-                opcode = self._fragmented_message_opcode
-                self._fragmented_message_buffer = None
-            else:
-                opcode = self._frame_opcode
-                if (self._fragmented_message_buffer is not None and
-                    not self._frame_opcode_is_control):
-                    # We have a fragmented buffer but we're not continuing
-                    # it.  This is an error for data packets, but
-                    # (non-fragmentable) control packets can be interleaved
-                    # with fragmented data.
-                    self._abort()
-                    return
 
+        if self._final_frame:
             self._handle_message(opcode, bytes_type(unmasked))
 
         if not self.client_terminated: