[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