| Index: third_party/twisted_8_1/twisted/spread/banana.py
|
| diff --git a/third_party/twisted_8_1/twisted/spread/banana.py b/third_party/twisted_8_1/twisted/spread/banana.py
|
| deleted file mode 100644
|
| index df34503dd2aae0d1211343f3b45ac2733751ea9b..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/spread/banana.py
|
| +++ /dev/null
|
| @@ -1,351 +0,0 @@
|
| -# -*- test-case-name: twisted.test.test_banana -*-
|
| -#
|
| -# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -
|
| -"""Banana -- s-exp based protocol.
|
| -
|
| -Future Plans: This module is almost entirely stable. The same caveat applies
|
| -to it as applies to L{twisted.spread.jelly}, however. Read its future plans
|
| -for more details.
|
| -
|
| -@author: U{Glyph Lefkowitz<mailto:glyph@twistedmatrix.com>}
|
| -"""
|
| -
|
| -__version__ = "$Revision: 1.37 $"[11:-2]
|
| -
|
| -from twisted.internet import protocol
|
| -from twisted.persisted import styles
|
| -from twisted.python import log
|
| -
|
| -import copy, cStringIO, struct
|
| -
|
| -class BananaError(Exception):
|
| - pass
|
| -
|
| -def int2b128(integer, stream):
|
| - if integer == 0:
|
| - stream(chr(0))
|
| - return
|
| - assert integer > 0, "can only encode positive integers"
|
| - while integer:
|
| - stream(chr(integer & 0x7f))
|
| - integer = integer >> 7
|
| -
|
| -def b1282int(st):
|
| - oneHundredAndTwentyEight = 128l
|
| - i = 0
|
| - place = 0
|
| - for char in st:
|
| - num = ord(char)
|
| - i = i + (num * (oneHundredAndTwentyEight ** place))
|
| - place = place + 1
|
| - if i <= 2147483647:
|
| - return int(i)
|
| - else:
|
| - return i
|
| -
|
| -# delimiter characters.
|
| -LIST = chr(0x80)
|
| -INT = chr(0x81)
|
| -STRING = chr(0x82)
|
| -NEG = chr(0x83)
|
| -FLOAT = chr(0x84)
|
| -# "optional" -- these might be refused by a low-level implementation.
|
| -LONGINT = chr(0x85)
|
| -LONGNEG = chr(0x86)
|
| -# really optional; this is is part of the 'pb' vocabulary
|
| -VOCAB = chr(0x87)
|
| -
|
| -HIGH_BIT_SET = chr(0x80)
|
| -
|
| -def setPrefixLimit(limit):
|
| - """
|
| - Set the limit on the prefix length for all Banana connections
|
| - established after this call.
|
| -
|
| - The prefix length limit determines how many bytes of prefix a banana
|
| - decoder will allow before rejecting a potential object as too large.
|
| -
|
| - @type limit: C{int}
|
| - @param limit: The number of bytes of prefix for banana to allow when
|
| - decoding.
|
| - """
|
| - global _PREFIX_LIMIT
|
| - _PREFIX_LIMIT = limit
|
| -setPrefixLimit(64)
|
| -
|
| -SIZE_LIMIT = 640 * 1024 # 640k is all you'll ever need :-)
|
| -
|
| -class Banana(protocol.Protocol, styles.Ephemeral):
|
| - knownDialects = ["pb", "none"]
|
| -
|
| - prefixLimit = None
|
| - sizeLimit = SIZE_LIMIT
|
| -
|
| - def setPrefixLimit(self, limit):
|
| - """
|
| - Set the prefix limit for decoding done by this protocol instance.
|
| -
|
| - @see: L{setPrefixLimit}
|
| - """
|
| - self.prefixLimit = limit
|
| - self._smallestLongInt = -2 ** (limit * 7) + 1
|
| - self._smallestInt = -2 ** 31
|
| - self._largestInt = 2 ** 31 - 1
|
| - self._largestLongInt = 2 ** (limit * 7) - 1
|
| -
|
| -
|
| - def connectionReady(self):
|
| - """Surrogate for connectionMade
|
| - Called after protocol negotiation.
|
| - """
|
| -
|
| - def _selectDialect(self, dialect):
|
| - self.currentDialect = dialect
|
| - self.connectionReady()
|
| -
|
| - def callExpressionReceived(self, obj):
|
| - if self.currentDialect:
|
| - self.expressionReceived(obj)
|
| - else:
|
| - # this is the first message we've received
|
| - if self.isClient:
|
| - # if I'm a client I have to respond
|
| - for serverVer in obj:
|
| - if serverVer in self.knownDialects:
|
| - self.sendEncoded(serverVer)
|
| - self._selectDialect(serverVer)
|
| - break
|
| - else:
|
| - # I can't speak any of those dialects.
|
| - log.msg('error losing')
|
| - self.transport.loseConnection()
|
| - else:
|
| - if obj in self.knownDialects:
|
| - self._selectDialect(obj)
|
| - else:
|
| - # the client just selected a protocol that I did not suggest.
|
| - log.msg('freaky losing')
|
| - self.transport.loseConnection()
|
| -
|
| -
|
| - def connectionMade(self):
|
| - self.setPrefixLimit(_PREFIX_LIMIT)
|
| - self.currentDialect = None
|
| - if not self.isClient:
|
| - self.sendEncoded(self.knownDialects)
|
| -
|
| -
|
| - def gotItem(self, item):
|
| - l = self.listStack
|
| - if l:
|
| - l[-1][1].append(item)
|
| - else:
|
| - self.callExpressionReceived(item)
|
| -
|
| - buffer = ''
|
| -
|
| - def dataReceived(self, chunk):
|
| - buffer = self.buffer + chunk
|
| - listStack = self.listStack
|
| - gotItem = self.gotItem
|
| - while buffer:
|
| - assert self.buffer != buffer, "This ain't right: %s %s" % (repr(self.buffer), repr(buffer))
|
| - self.buffer = buffer
|
| - pos = 0
|
| - for ch in buffer:
|
| - if ch >= HIGH_BIT_SET:
|
| - break
|
| - pos = pos + 1
|
| - else:
|
| - if pos > self.prefixLimit:
|
| - raise BananaError("Security precaution: more than %d bytes of prefix" % (self.prefixLimit,))
|
| - return
|
| - num = buffer[:pos]
|
| - typebyte = buffer[pos]
|
| - rest = buffer[pos+1:]
|
| - if len(num) > self.prefixLimit:
|
| - raise BananaError("Security precaution: longer than %d bytes worth of prefix" % (self.prefixLimit,))
|
| - if typebyte == LIST:
|
| - num = b1282int(num)
|
| - if num > SIZE_LIMIT:
|
| - raise BananaError("Security precaution: List too long.")
|
| - listStack.append((num, []))
|
| - buffer = rest
|
| - elif typebyte == STRING:
|
| - num = b1282int(num)
|
| - if num > SIZE_LIMIT:
|
| - raise BananaError("Security precaution: String too long.")
|
| - if len(rest) >= num:
|
| - buffer = rest[num:]
|
| - gotItem(rest[:num])
|
| - else:
|
| - return
|
| - elif typebyte == INT:
|
| - buffer = rest
|
| - num = b1282int(num)
|
| - gotItem(int(num))
|
| - elif typebyte == LONGINT:
|
| - buffer = rest
|
| - num = b1282int(num)
|
| - gotItem(long(num))
|
| - elif typebyte == LONGNEG:
|
| - buffer = rest
|
| - num = b1282int(num)
|
| - gotItem(-long(num))
|
| - elif typebyte == NEG:
|
| - buffer = rest
|
| - num = -b1282int(num)
|
| - gotItem(num)
|
| - elif typebyte == VOCAB:
|
| - buffer = rest
|
| - num = b1282int(num)
|
| - gotItem(self.incomingVocabulary[num])
|
| - elif typebyte == FLOAT:
|
| - if len(rest) >= 8:
|
| - buffer = rest[8:]
|
| - gotItem(struct.unpack("!d", rest[:8])[0])
|
| - else:
|
| - return
|
| - else:
|
| - raise NotImplementedError(("Invalid Type Byte %r" % (typebyte,)))
|
| - while listStack and (len(listStack[-1][1]) == listStack[-1][0]):
|
| - item = listStack.pop()[1]
|
| - gotItem(item)
|
| - self.buffer = ''
|
| -
|
| -
|
| - def expressionReceived(self, lst):
|
| - """Called when an expression (list, string, or int) is received.
|
| - """
|
| - raise NotImplementedError()
|
| -
|
| -
|
| - outgoingVocabulary = {
|
| - # Jelly Data Types
|
| - 'None' : 1,
|
| - 'class' : 2,
|
| - 'dereference' : 3,
|
| - 'reference' : 4,
|
| - 'dictionary' : 5,
|
| - 'function' : 6,
|
| - 'instance' : 7,
|
| - 'list' : 8,
|
| - 'module' : 9,
|
| - 'persistent' : 10,
|
| - 'tuple' : 11,
|
| - 'unpersistable' : 12,
|
| -
|
| - # PB Data Types
|
| - 'copy' : 13,
|
| - 'cache' : 14,
|
| - 'cached' : 15,
|
| - 'remote' : 16,
|
| - 'local' : 17,
|
| - 'lcache' : 18,
|
| -
|
| - # PB Protocol Messages
|
| - 'version' : 19,
|
| - 'login' : 20,
|
| - 'password' : 21,
|
| - 'challenge' : 22,
|
| - 'logged_in' : 23,
|
| - 'not_logged_in' : 24,
|
| - 'cachemessage' : 25,
|
| - 'message' : 26,
|
| - 'answer' : 27,
|
| - 'error' : 28,
|
| - 'decref' : 29,
|
| - 'decache' : 30,
|
| - 'uncache' : 31,
|
| - }
|
| -
|
| - incomingVocabulary = {}
|
| - for k, v in outgoingVocabulary.items():
|
| - incomingVocabulary[v] = k
|
| -
|
| - def __init__(self, isClient=1):
|
| - self.listStack = []
|
| - self.outgoingSymbols = copy.copy(self.outgoingVocabulary)
|
| - self.outgoingSymbolCount = 0
|
| - self.isClient = isClient
|
| -
|
| - def sendEncoded(self, obj):
|
| - io = cStringIO.StringIO()
|
| - self._encode(obj, io.write)
|
| - value = io.getvalue()
|
| - self.transport.write(value)
|
| -
|
| - def _encode(self, obj, write):
|
| - if isinstance(obj, (list, tuple)):
|
| - if len(obj) > SIZE_LIMIT:
|
| - raise BananaError(
|
| - "list/tuple is too long to send (%d)" % (len(obj),))
|
| - int2b128(len(obj), write)
|
| - write(LIST)
|
| - for elem in obj:
|
| - self._encode(elem, write)
|
| - elif isinstance(obj, (int, long)):
|
| - if obj < self._smallestLongInt or obj > self._largestLongInt:
|
| - raise BananaError(
|
| - "int/long is too large to send (%d)" % (obj,))
|
| - if obj < self._smallestInt:
|
| - int2b128(-obj, write)
|
| - write(LONGNEG)
|
| - elif obj < 0:
|
| - int2b128(-obj, write)
|
| - write(NEG)
|
| - elif obj <= self._largestInt:
|
| - int2b128(obj, write)
|
| - write(INT)
|
| - else:
|
| - int2b128(obj, write)
|
| - write(LONGINT)
|
| - elif isinstance(obj, float):
|
| - write(FLOAT)
|
| - write(struct.pack("!d", obj))
|
| - elif isinstance(obj, str):
|
| - # TODO: an API for extending banana...
|
| - if self.currentDialect == "pb" and obj in self.outgoingSymbols:
|
| - symbolID = self.outgoingSymbols[obj]
|
| - int2b128(symbolID, write)
|
| - write(VOCAB)
|
| - else:
|
| - if len(obj) > SIZE_LIMIT:
|
| - raise BananaError(
|
| - "string is too long to send (%d)" % (len(obj),))
|
| - int2b128(len(obj), write)
|
| - write(STRING)
|
| - write(obj)
|
| - else:
|
| - raise BananaError("could not send object: %r" % (obj,))
|
| -
|
| -
|
| -# For use from the interactive interpreter
|
| -_i = Banana()
|
| -_i.connectionMade()
|
| -_i._selectDialect("none")
|
| -
|
| -
|
| -def encode(lst):
|
| - """Encode a list s-expression."""
|
| - io = cStringIO.StringIO()
|
| - _i.transport = io
|
| - _i.sendEncoded(lst)
|
| - return io.getvalue()
|
| -
|
| -
|
| -def decode(st):
|
| - """
|
| - Decode a banana-encoded string.
|
| - """
|
| - l = []
|
| - _i.expressionReceived = l.append
|
| - try:
|
| - _i.dataReceived(st)
|
| - finally:
|
| - _i.buffer = ''
|
| - del _i.expressionReceived
|
| - return l[0]
|
|
|