[Checkins] SVN: zc.ngi/trunk/src/zc/ngi/adapters. Added a sized-message adapter.

Jim Fulton jim at zope.com
Fri Sep 8 15:01:52 EDT 2006


Log message for revision 70077:
  Added a sized-message adapter.
  

Changed:
  U   zc.ngi/trunk/src/zc/ngi/adapters.py
  U   zc.ngi/trunk/src/zc/ngi/adapters.txt

-=-
Modified: zc.ngi/trunk/src/zc/ngi/adapters.py
===================================================================
--- zc.ngi/trunk/src/zc/ngi/adapters.py	2006-09-08 19:01:49 UTC (rev 70076)
+++ zc.ngi/trunk/src/zc/ngi/adapters.py	2006-09-08 19:01:51 UTC (rev 70077)
@@ -15,6 +15,7 @@
 
 $Id$
 """
+import struct
 
 class Lines:
 
@@ -39,4 +40,56 @@
         self.handler.handle_close(self, reason)
 
 
+class Sized:
+
+    def __init__(self, connection):
+        self.connection = connection
+        self.close = connection.close
+
+    def setHandler(self, handler):
+        self.handler = handler
+        self.input = []
+        self.want = 4
+        self.got = 0
+        self.getting_size = True
+        self.connection.setHandler(self)
+
+    def handle_input(self, connection, data):
+        self.got += len(data)
+        self.input.append(data)
+        while self.got >= self.want:
+            extra = self.got - self.want
+            if extra == 0:
+                collected = ''.join(self.input)
+                self.input = []
+            else:
+                input = self.input
+                self.input = [data[-extra:]]
+                input[-1] = input[-1][:-extra]
+                collected = ''.join(input)
+
+            self.got = extra
+
+            if self.getting_size:
+                # we were recieving the message size
+                assert self.want == 4
+                if collected == '\xff\xff\xff\xff':
+                    # NULL message. Ignore
+                    continue
+                self.want = struct.unpack(">I", collected)[0]
+                self.getting_size = False
+            else:
+                self.want = 4
+                self.getting_size = True
+                self.handler.handle_input(self, collected)
+
+    def handle_close(self, connection, reason):
+        self.handler.handle_close(self, reason)
+
+    def write(self, message):
+        if message is None:
+            self.connection.write('\xff\xff\xff\xff')
+        else:
+            self.connection.write(struct.pack(">I", len(message)))
+            self.connection.write(message)
     

Modified: zc.ngi/trunk/src/zc/ngi/adapters.txt
===================================================================
--- zc.ngi/trunk/src/zc/ngi/adapters.txt	2006-09-08 19:01:49 UTC (rev 70076)
+++ zc.ngi/trunk/src/zc/ngi/adapters.txt	2006-09-08 19:01:51 UTC (rev 70077)
@@ -19,7 +19,7 @@
     >>> connection = zc.ngi.testing.Connection()
     >>> handler = zc.ngi.testing.PrintingHandler(connection)
  
-This handler is used by by default as the peer
+This handler is used by default as the peer
 of testing connections:
 
     >>> connection.test_input('x' * 80)
@@ -60,3 +60,61 @@
 
     >>> adapter.connection is connection
     True
+
+Sized Messages
+==============
+
+The second adapter we'll look at will handle binary data organized
+into sized messages.  Each message has two parts, a length, and a
+payload.  Of course, the length gives the length of the payload.
+
+To see this, we'll use the adapter to adapt a testing connection:
+
+    >>> connection = zc.ngi.testing.Connection()
+    >>> adapter = zc.ngi.adapters.Sized(connection)
+    >>> handler = zc.ngi.testing.PrintingHandler(adapter)
+
+Now, we'll generate some input. We do so by providing (big-endian) sizes by
+calling struct pack:
+    
+    >>> import struct
+    >>> message1 = 'Hello\nWorld!\nHow are you?'
+    >>> message2 = 'This is message 2'
+    >>> connection.test_input(struct.pack(">I", len(message1)))
+    >>> connection.test_input(message1[:10])
+    >>> connection.test_input(message1[10:]+ struct.pack(">I", len(message2)))
+    -> 'Hello\nWorld!\nHow are you?'
+
+    >>> connection.test_input(message2)
+    -> 'This is message 2'
+
+Here we saw that our handler got the two messages individually.
+
+If we write a message, we can see that the message is preceeded by the
+message size:
+
+    >>> adapter.write(message1) 
+    -> '\x00\x00\x00\x19'
+    -> 'Hello\nWorld!\nHow are you?'
+   
+Null messages
+-------------
+
+It can be useful to send Null messages to make sure that a client is
+still connected.  The sized adapter supprts such messages.  Calling
+write with None, sends a null message, which is a message with a
+length of 1 << 32 - 1 and no message data:
+
+    >>> adapter.write(None)
+    -> '\xff\xff\xff\xff'
+
+On input, Null messages are ignored by the sized adapter and are not
+sent to the application:
+
+    >>> connection.test_input('\xff\xff\xff\xff')
+
+
+ 
+
+
+



More information about the Checkins mailing list