Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: third_party/twisted_8_1/twisted/spread/banana.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.test.test_banana -*-
2 #
3 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6
7 """Banana -- s-exp based protocol.
8
9 Future Plans: This module is almost entirely stable. The same caveat applies
10 to it as applies to L{twisted.spread.jelly}, however. Read its future plans
11 for more details.
12
13 @author: U{Glyph Lefkowitz<mailto:glyph@twistedmatrix.com>}
14 """
15
16 __version__ = "$Revision: 1.37 $"[11:-2]
17
18 from twisted.internet import protocol
19 from twisted.persisted import styles
20 from twisted.python import log
21
22 import copy, cStringIO, struct
23
24 class BananaError(Exception):
25 pass
26
27 def int2b128(integer, stream):
28 if integer == 0:
29 stream(chr(0))
30 return
31 assert integer > 0, "can only encode positive integers"
32 while integer:
33 stream(chr(integer & 0x7f))
34 integer = integer >> 7
35
36 def b1282int(st):
37 oneHundredAndTwentyEight = 128l
38 i = 0
39 place = 0
40 for char in st:
41 num = ord(char)
42 i = i + (num * (oneHundredAndTwentyEight ** place))
43 place = place + 1
44 if i <= 2147483647:
45 return int(i)
46 else:
47 return i
48
49 # delimiter characters.
50 LIST = chr(0x80)
51 INT = chr(0x81)
52 STRING = chr(0x82)
53 NEG = chr(0x83)
54 FLOAT = chr(0x84)
55 # "optional" -- these might be refused by a low-level implementation.
56 LONGINT = chr(0x85)
57 LONGNEG = chr(0x86)
58 # really optional; this is is part of the 'pb' vocabulary
59 VOCAB = chr(0x87)
60
61 HIGH_BIT_SET = chr(0x80)
62
63 def setPrefixLimit(limit):
64 """
65 Set the limit on the prefix length for all Banana connections
66 established after this call.
67
68 The prefix length limit determines how many bytes of prefix a banana
69 decoder will allow before rejecting a potential object as too large.
70
71 @type limit: C{int}
72 @param limit: The number of bytes of prefix for banana to allow when
73 decoding.
74 """
75 global _PREFIX_LIMIT
76 _PREFIX_LIMIT = limit
77 setPrefixLimit(64)
78
79 SIZE_LIMIT = 640 * 1024 # 640k is all you'll ever need :-)
80
81 class Banana(protocol.Protocol, styles.Ephemeral):
82 knownDialects = ["pb", "none"]
83
84 prefixLimit = None
85 sizeLimit = SIZE_LIMIT
86
87 def setPrefixLimit(self, limit):
88 """
89 Set the prefix limit for decoding done by this protocol instance.
90
91 @see: L{setPrefixLimit}
92 """
93 self.prefixLimit = limit
94 self._smallestLongInt = -2 ** (limit * 7) + 1
95 self._smallestInt = -2 ** 31
96 self._largestInt = 2 ** 31 - 1
97 self._largestLongInt = 2 ** (limit * 7) - 1
98
99
100 def connectionReady(self):
101 """Surrogate for connectionMade
102 Called after protocol negotiation.
103 """
104
105 def _selectDialect(self, dialect):
106 self.currentDialect = dialect
107 self.connectionReady()
108
109 def callExpressionReceived(self, obj):
110 if self.currentDialect:
111 self.expressionReceived(obj)
112 else:
113 # this is the first message we've received
114 if self.isClient:
115 # if I'm a client I have to respond
116 for serverVer in obj:
117 if serverVer in self.knownDialects:
118 self.sendEncoded(serverVer)
119 self._selectDialect(serverVer)
120 break
121 else:
122 # I can't speak any of those dialects.
123 log.msg('error losing')
124 self.transport.loseConnection()
125 else:
126 if obj in self.knownDialects:
127 self._selectDialect(obj)
128 else:
129 # the client just selected a protocol that I did not suggest .
130 log.msg('freaky losing')
131 self.transport.loseConnection()
132
133
134 def connectionMade(self):
135 self.setPrefixLimit(_PREFIX_LIMIT)
136 self.currentDialect = None
137 if not self.isClient:
138 self.sendEncoded(self.knownDialects)
139
140
141 def gotItem(self, item):
142 l = self.listStack
143 if l:
144 l[-1][1].append(item)
145 else:
146 self.callExpressionReceived(item)
147
148 buffer = ''
149
150 def dataReceived(self, chunk):
151 buffer = self.buffer + chunk
152 listStack = self.listStack
153 gotItem = self.gotItem
154 while buffer:
155 assert self.buffer != buffer, "This ain't right: %s %s" % (repr(self .buffer), repr(buffer))
156 self.buffer = buffer
157 pos = 0
158 for ch in buffer:
159 if ch >= HIGH_BIT_SET:
160 break
161 pos = pos + 1
162 else:
163 if pos > self.prefixLimit:
164 raise BananaError("Security precaution: more than %d bytes o f prefix" % (self.prefixLimit,))
165 return
166 num = buffer[:pos]
167 typebyte = buffer[pos]
168 rest = buffer[pos+1:]
169 if len(num) > self.prefixLimit:
170 raise BananaError("Security precaution: longer than %d bytes wor th of prefix" % (self.prefixLimit,))
171 if typebyte == LIST:
172 num = b1282int(num)
173 if num > SIZE_LIMIT:
174 raise BananaError("Security precaution: List too long.")
175 listStack.append((num, []))
176 buffer = rest
177 elif typebyte == STRING:
178 num = b1282int(num)
179 if num > SIZE_LIMIT:
180 raise BananaError("Security precaution: String too long.")
181 if len(rest) >= num:
182 buffer = rest[num:]
183 gotItem(rest[:num])
184 else:
185 return
186 elif typebyte == INT:
187 buffer = rest
188 num = b1282int(num)
189 gotItem(int(num))
190 elif typebyte == LONGINT:
191 buffer = rest
192 num = b1282int(num)
193 gotItem(long(num))
194 elif typebyte == LONGNEG:
195 buffer = rest
196 num = b1282int(num)
197 gotItem(-long(num))
198 elif typebyte == NEG:
199 buffer = rest
200 num = -b1282int(num)
201 gotItem(num)
202 elif typebyte == VOCAB:
203 buffer = rest
204 num = b1282int(num)
205 gotItem(self.incomingVocabulary[num])
206 elif typebyte == FLOAT:
207 if len(rest) >= 8:
208 buffer = rest[8:]
209 gotItem(struct.unpack("!d", rest[:8])[0])
210 else:
211 return
212 else:
213 raise NotImplementedError(("Invalid Type Byte %r" % (typebyte,)) )
214 while listStack and (len(listStack[-1][1]) == listStack[-1][0]):
215 item = listStack.pop()[1]
216 gotItem(item)
217 self.buffer = ''
218
219
220 def expressionReceived(self, lst):
221 """Called when an expression (list, string, or int) is received.
222 """
223 raise NotImplementedError()
224
225
226 outgoingVocabulary = {
227 # Jelly Data Types
228 'None' : 1,
229 'class' : 2,
230 'dereference' : 3,
231 'reference' : 4,
232 'dictionary' : 5,
233 'function' : 6,
234 'instance' : 7,
235 'list' : 8,
236 'module' : 9,
237 'persistent' : 10,
238 'tuple' : 11,
239 'unpersistable' : 12,
240
241 # PB Data Types
242 'copy' : 13,
243 'cache' : 14,
244 'cached' : 15,
245 'remote' : 16,
246 'local' : 17,
247 'lcache' : 18,
248
249 # PB Protocol Messages
250 'version' : 19,
251 'login' : 20,
252 'password' : 21,
253 'challenge' : 22,
254 'logged_in' : 23,
255 'not_logged_in' : 24,
256 'cachemessage' : 25,
257 'message' : 26,
258 'answer' : 27,
259 'error' : 28,
260 'decref' : 29,
261 'decache' : 30,
262 'uncache' : 31,
263 }
264
265 incomingVocabulary = {}
266 for k, v in outgoingVocabulary.items():
267 incomingVocabulary[v] = k
268
269 def __init__(self, isClient=1):
270 self.listStack = []
271 self.outgoingSymbols = copy.copy(self.outgoingVocabulary)
272 self.outgoingSymbolCount = 0
273 self.isClient = isClient
274
275 def sendEncoded(self, obj):
276 io = cStringIO.StringIO()
277 self._encode(obj, io.write)
278 value = io.getvalue()
279 self.transport.write(value)
280
281 def _encode(self, obj, write):
282 if isinstance(obj, (list, tuple)):
283 if len(obj) > SIZE_LIMIT:
284 raise BananaError(
285 "list/tuple is too long to send (%d)" % (len(obj),))
286 int2b128(len(obj), write)
287 write(LIST)
288 for elem in obj:
289 self._encode(elem, write)
290 elif isinstance(obj, (int, long)):
291 if obj < self._smallestLongInt or obj > self._largestLongInt:
292 raise BananaError(
293 "int/long is too large to send (%d)" % (obj,))
294 if obj < self._smallestInt:
295 int2b128(-obj, write)
296 write(LONGNEG)
297 elif obj < 0:
298 int2b128(-obj, write)
299 write(NEG)
300 elif obj <= self._largestInt:
301 int2b128(obj, write)
302 write(INT)
303 else:
304 int2b128(obj, write)
305 write(LONGINT)
306 elif isinstance(obj, float):
307 write(FLOAT)
308 write(struct.pack("!d", obj))
309 elif isinstance(obj, str):
310 # TODO: an API for extending banana...
311 if self.currentDialect == "pb" and obj in self.outgoingSymbols:
312 symbolID = self.outgoingSymbols[obj]
313 int2b128(symbolID, write)
314 write(VOCAB)
315 else:
316 if len(obj) > SIZE_LIMIT:
317 raise BananaError(
318 "string is too long to send (%d)" % (len(obj),))
319 int2b128(len(obj), write)
320 write(STRING)
321 write(obj)
322 else:
323 raise BananaError("could not send object: %r" % (obj,))
324
325
326 # For use from the interactive interpreter
327 _i = Banana()
328 _i.connectionMade()
329 _i._selectDialect("none")
330
331
332 def encode(lst):
333 """Encode a list s-expression."""
334 io = cStringIO.StringIO()
335 _i.transport = io
336 _i.sendEncoded(lst)
337 return io.getvalue()
338
339
340 def decode(st):
341 """
342 Decode a banana-encoded string.
343 """
344 l = []
345 _i.expressionReceived = l.append
346 try:
347 _i.dataReceived(st)
348 finally:
349 _i.buffer = ''
350 del _i.expressionReceived
351 return l[0]
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/spread/__init__.py ('k') | third_party/twisted_8_1/twisted/spread/flavors.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698