浏览代码

Added some comments + input checking + template for multiplex extension

Taddeus Kroes 12 年之前
父节点
当前提交
6efb88078d
共有 2 个文件被更改,包括 63 次插入12 次删除
  1. 1 1
      __init__.py
  2. 62 11
      extension.py

+ 1 - 1
__init__.py

@@ -8,4 +8,4 @@ from frame import Frame, ControlFrame, OPCODE_CONTINUATION, OPCODE_TEXT, \
 from connection import Connection
 from connection import Connection
 from message import Message, TextMessage, BinaryMessage
 from message import Message, TextMessage, BinaryMessage
 from errors import SocketClosed, HandshakeError, PingError, SSLError
 from errors import SocketClosed, HandshakeError, PingError, SSLError
-from extension import Extension, DeflateFrame
+from extension import Extension, DeflateFrame, Multiplex

+ 62 - 11
extension.py

@@ -15,7 +15,7 @@ class Extension(object):
 
 
         for param, value in kwargs.items():
         for param, value in kwargs.items():
             if param not in self.parameters:
             if param not in self.parameters:
-                raise HandshakeError('invalid parameter "%s"' % param)
+                raise HandshakeError('unrecognized parameter "%s"' % param)
 
 
             if value is None:
             if value is None:
                 value = True
                 value = True
@@ -42,42 +42,93 @@ class Extension(object):
 
 
 
 
 class DeflateFrame(Extension):
 class DeflateFrame(Extension):
+    """
+    This is an implementation of the "deflate-frame" extension, as defined by
+    http://tools.ietf.org/html/draft-tyoshino-hybi-websocket-perframe-deflate-06.
+
+    Supported parameters are:
+    - max_window_size: maximum size for the LZ77 sliding window.
+    - no_context_takeover: disallows usage of LZ77 sliding window from
+                           previously built frames for the current frame.
+
+    Note that the deflate and inflate hooks modify the RSV1 bit and payload of
+    existing `Frame` objects.
+    """
+
     name = 'deflate-frame'
     name = 'deflate-frame'
     rsv1 = True
     rsv1 = True
     parameters = ['max_window_bits', 'no_context_takeover']
     parameters = ['max_window_bits', 'no_context_takeover']
 
 
+    # FIXME: is this correct?
+    default_max_window_bits = 32768
+
     def __init__(self, **kwargs):
     def __init__(self, **kwargs):
         super(DeflateFrame, self).__init__(**kwargs)
         super(DeflateFrame, self).__init__(**kwargs)
 
 
         if self.max_window_bits is None:
         if self.max_window_bits is None:
-            # FIXME: is this correct? None may actually be a better value
-            self.max_window_bits = 0
+            self.max_window_bits = self.default_max_window_bits
+        elif not isinstance(self.max_window_bits, int):
+            raise HandshakeError('"max_window_bits" must be an integer')
+        elif self.max_window_bits > 32768:
+            raise HandshakeError('"max_window_bits" may not be larger than '
+                                 '32768')
+
+        if self.no_context_takeover is None:
+            self.no_context_takeover = False
+        elif self.no_context_takeover is not True:
+            raise HandshakeError('"no_context_takeover" must have no value')
 
 
     def hook_send(self, frame):
     def hook_send(self, frame):
-        # FIXME: original `frame` is modified, maybe it should be copied?
-
         if not frame.rsv1:
         if not frame.rsv1:
             frame.rsv1 = True
             frame.rsv1 = True
-            frame.payload = self.encode(frame.payload)
+            frame.payload = self.deflate(frame.payload)
 
 
         return frame
         return frame
 
 
     def hook_recv(self, frame):
     def hook_recv(self, frame):
-        # FIXME: original `frame` is modified, maybe it should be copied?
-
         if frame.rsv1:
         if frame.rsv1:
             frame.rsv1 = False
             frame.rsv1 = False
-            frame.payload = self.decode(frame.payload)
+            frame.payload = self.inflate(frame.payload)
 
 
         return frame
         return frame
 
 
     def header_params(self):
     def header_params(self):
         raise NotImplementedError  # TODO
         raise NotImplementedError  # TODO
 
 
-    def encode(self, data):
+    def deflate(self, data):
+        raise NotImplementedError  # TODO
+
+    def inflate(self, data):
+        raise NotImplementedError  # TODO
+
+
+class Multiplex(Extension):
+    """
+    This is an implementation of the "mux" extension, as defined by
+    http://tools.ietf.org/html/draft-ietf-hybi-websocket-multiplexing-11.
+
+    Supported parameters are:
+    - quota: TODO
+    """
+
+    name = 'mux'
+    rsv1 = True  # FIXME
+    rsv2 = True  # FIXME
+    rsv3 = True  # FIXME
+    parameters = ['quota']
+
+    def __init__(self, **kwargs):
+        super(Multiplex, self).__init__(**kwargs)
+
+        # TODO: check "quota" value
+
+    def hook_send(self, frame):
+        raise NotImplementedError  # TODO
+
+    def hook_recv(self, frame):
         raise NotImplementedError  # TODO
         raise NotImplementedError  # TODO
 
 
-    def decode(self, data):
+    def header_params(self):
         raise NotImplementedError  # TODO
         raise NotImplementedError  # TODO