Index: third_party/twisted_8_1/twisted/protocols/basic.py |
diff --git a/third_party/twisted_8_1/twisted/protocols/basic.py b/third_party/twisted_8_1/twisted/protocols/basic.py |
deleted file mode 100644 |
index a4c531287c82cdf30fc69beefb0c046474c3706a..0000000000000000000000000000000000000000 |
--- a/third_party/twisted_8_1/twisted/protocols/basic.py |
+++ /dev/null |
@@ -1,486 +0,0 @@ |
-# -*- test-case-name: twisted.test.test_protocols -*- |
-# Copyright (c) 2001-2008 Twisted Matrix Laboratories. |
-# See LICENSE for details. |
- |
- |
-""" |
-Basic protocols, such as line-oriented, netstring, and int prefixed strings. |
- |
-Maintainer: U{Itamar Shtull-Trauring<mailto:twisted@itamarst.org>} |
-""" |
- |
-# System imports |
-import re |
-import struct |
- |
-from zope.interface import implements |
- |
-# Twisted imports |
-from twisted.internet import protocol, defer, interfaces, error |
-from twisted.python import log |
- |
-LENGTH, DATA, COMMA = range(3) |
-NUMBER = re.compile('(\d*)(:?)') |
-DEBUG = 0 |
- |
-class NetstringParseError(ValueError): |
- """The incoming data is not in valid Netstring format.""" |
- pass |
- |
- |
-class NetstringReceiver(protocol.Protocol): |
- """This uses djb's Netstrings protocol to break up the input into strings. |
- |
- Each string makes a callback to stringReceived, with a single |
- argument of that string. |
- |
- Security features: |
- 1. Messages are limited in size, useful if you don't want someone |
- sending you a 500MB netstring (change MAX_LENGTH to the maximum |
- length you wish to accept). |
- 2. The connection is lost if an illegal message is received. |
- """ |
- |
- MAX_LENGTH = 99999 |
- brokenPeer = 0 |
- _readerState = LENGTH |
- _readerLength = 0 |
- |
- def stringReceived(self, line): |
- """ |
- Override this. |
- """ |
- raise NotImplementedError |
- |
- def doData(self): |
- buffer,self.__data = self.__data[:int(self._readerLength)],self.__data[int(self._readerLength):] |
- self._readerLength = self._readerLength - len(buffer) |
- self.__buffer = self.__buffer + buffer |
- if self._readerLength != 0: |
- return |
- self.stringReceived(self.__buffer) |
- self._readerState = COMMA |
- |
- def doComma(self): |
- self._readerState = LENGTH |
- if self.__data[0] != ',': |
- if DEBUG: |
- raise NetstringParseError(repr(self.__data)) |
- else: |
- raise NetstringParseError |
- self.__data = self.__data[1:] |
- |
- |
- def doLength(self): |
- m = NUMBER.match(self.__data) |
- if not m.end(): |
- if DEBUG: |
- raise NetstringParseError(repr(self.__data)) |
- else: |
- raise NetstringParseError |
- self.__data = self.__data[m.end():] |
- if m.group(1): |
- try: |
- self._readerLength = self._readerLength * (10**len(m.group(1))) + long(m.group(1)) |
- except OverflowError: |
- raise NetstringParseError, "netstring too long" |
- if self._readerLength > self.MAX_LENGTH: |
- raise NetstringParseError, "netstring too long" |
- if m.group(2): |
- self.__buffer = '' |
- self._readerState = DATA |
- |
- def dataReceived(self, data): |
- self.__data = data |
- try: |
- while self.__data: |
- if self._readerState == DATA: |
- self.doData() |
- elif self._readerState == COMMA: |
- self.doComma() |
- elif self._readerState == LENGTH: |
- self.doLength() |
- else: |
- raise RuntimeError, "mode is not DATA, COMMA or LENGTH" |
- except NetstringParseError: |
- self.transport.loseConnection() |
- self.brokenPeer = 1 |
- |
- def sendString(self, data): |
- self.transport.write('%d:%s,' % (len(data), data)) |
- |
- |
-class SafeNetstringReceiver(NetstringReceiver): |
- """This class is deprecated, use NetstringReceiver instead. |
- """ |
- |
- |
-class LineOnlyReceiver(protocol.Protocol): |
- """A protocol that receives only lines. |
- |
- This is purely a speed optimisation over LineReceiver, for the |
- cases that raw mode is known to be unnecessary. |
- |
- @cvar delimiter: The line-ending delimiter to use. By default this is |
- '\\r\\n'. |
- @cvar MAX_LENGTH: The maximum length of a line to allow (If a |
- sent line is longer than this, the connection is dropped). |
- Default is 16384. |
- """ |
- _buffer = '' |
- delimiter = '\r\n' |
- MAX_LENGTH = 16384 |
- |
- def dataReceived(self, data): |
- """Translates bytes into lines, and calls lineReceived.""" |
- lines = (self._buffer+data).split(self.delimiter) |
- self._buffer = lines.pop(-1) |
- for line in lines: |
- if self.transport.disconnecting: |
- # this is necessary because the transport may be told to lose |
- # the connection by a line within a larger packet, and it is |
- # important to disregard all the lines in that packet following |
- # the one that told it to close. |
- return |
- if len(line) > self.MAX_LENGTH: |
- return self.lineLengthExceeded(line) |
- else: |
- self.lineReceived(line) |
- if len(self._buffer) > self.MAX_LENGTH: |
- return self.lineLengthExceeded(self._buffer) |
- |
- def lineReceived(self, line): |
- """Override this for when each line is received. |
- """ |
- raise NotImplementedError |
- |
- def sendLine(self, line): |
- """Sends a line to the other end of the connection. |
- """ |
- return self.transport.writeSequence((line,self.delimiter)) |
- |
- def lineLengthExceeded(self, line): |
- """Called when the maximum line length has been reached. |
- Override if it needs to be dealt with in some special way. |
- """ |
- return error.ConnectionLost('Line length exceeded') |
- |
- |
-class _PauseableMixin: |
- paused = False |
- |
- def pauseProducing(self): |
- self.paused = True |
- self.transport.pauseProducing() |
- |
- def resumeProducing(self): |
- self.paused = False |
- self.transport.resumeProducing() |
- self.dataReceived('') |
- |
- def stopProducing(self): |
- self.paused = True |
- self.transport.stopProducing() |
- |
- |
-class LineReceiver(protocol.Protocol, _PauseableMixin): |
- """A protocol that receives lines and/or raw data, depending on mode. |
- |
- In line mode, each line that's received becomes a callback to |
- L{lineReceived}. In raw data mode, each chunk of raw data becomes a |
- callback to L{rawDataReceived}. The L{setLineMode} and L{setRawMode} |
- methods switch between the two modes. |
- |
- This is useful for line-oriented protocols such as IRC, HTTP, POP, etc. |
- |
- @cvar delimiter: The line-ending delimiter to use. By default this is |
- '\\r\\n'. |
- @cvar MAX_LENGTH: The maximum length of a line to allow (If a |
- sent line is longer than this, the connection is dropped). |
- Default is 16384. |
- """ |
- line_mode = 1 |
- __buffer = '' |
- delimiter = '\r\n' |
- MAX_LENGTH = 16384 |
- |
- def clearLineBuffer(self): |
- """Clear buffered data.""" |
- self.__buffer = "" |
- |
- def dataReceived(self, data): |
- """Protocol.dataReceived. |
- Translates bytes into lines, and calls lineReceived (or |
- rawDataReceived, depending on mode.) |
- """ |
- self.__buffer = self.__buffer+data |
- while self.line_mode and not self.paused: |
- try: |
- line, self.__buffer = self.__buffer.split(self.delimiter, 1) |
- except ValueError: |
- if len(self.__buffer) > self.MAX_LENGTH: |
- line, self.__buffer = self.__buffer, '' |
- return self.lineLengthExceeded(line) |
- break |
- else: |
- linelength = len(line) |
- if linelength > self.MAX_LENGTH: |
- exceeded = line + self.__buffer |
- self.__buffer = '' |
- return self.lineLengthExceeded(exceeded) |
- why = self.lineReceived(line) |
- if why or self.transport and self.transport.disconnecting: |
- return why |
- else: |
- if not self.paused: |
- data=self.__buffer |
- self.__buffer='' |
- if data: |
- return self.rawDataReceived(data) |
- |
- def setLineMode(self, extra=''): |
- """Sets the line-mode of this receiver. |
- |
- If you are calling this from a rawDataReceived callback, |
- you can pass in extra unhandled data, and that data will |
- be parsed for lines. Further data received will be sent |
- to lineReceived rather than rawDataReceived. |
- |
- Do not pass extra data if calling this function from |
- within a lineReceived callback. |
- """ |
- self.line_mode = 1 |
- if extra: |
- return self.dataReceived(extra) |
- |
- def setRawMode(self): |
- """Sets the raw mode of this receiver. |
- Further data received will be sent to rawDataReceived rather |
- than lineReceived. |
- """ |
- self.line_mode = 0 |
- |
- def rawDataReceived(self, data): |
- """Override this for when raw data is received. |
- """ |
- raise NotImplementedError |
- |
- def lineReceived(self, line): |
- """Override this for when each line is received. |
- """ |
- raise NotImplementedError |
- |
- def sendLine(self, line): |
- """Sends a line to the other end of the connection. |
- """ |
- return self.transport.write(line + self.delimiter) |
- |
- def lineLengthExceeded(self, line): |
- """Called when the maximum line length has been reached. |
- Override if it needs to be dealt with in some special way. |
- |
- The argument 'line' contains the remainder of the buffer, starting |
- with (at least some part) of the line which is too long. This may |
- be more than one line, or may be only the initial portion of the |
- line. |
- """ |
- return self.transport.loseConnection() |
- |
- |
-class StringTooLongError(AssertionError): |
- """ |
- Raised when trying to send a string too long for a length prefixed |
- protocol. |
- """ |
- |
- |
-class IntNStringReceiver(protocol.Protocol, _PauseableMixin): |
- """ |
- Generic class for length prefixed protocols. |
- |
- @ivar recvd: buffer holding received data when splitted. |
- @type recvd: C{str} |
- |
- @ivar structFormat: format used for struct packing/unpacking. Define it in |
- subclass. |
- @type structFormat: C{str} |
- |
- @ivar prefixLength: length of the prefix, in bytes. Define it in subclass, |
- using C{struct.calcSize(structFormat)} |
- @type prefixLength: C{int} |
- """ |
- MAX_LENGTH = 99999 |
- recvd = "" |
- |
- def stringReceived(self, msg): |
- """ |
- Override this. |
- """ |
- raise NotImplementedError |
- |
- def dataReceived(self, recd): |
- """ |
- Convert int prefixed strings into calls to stringReceived. |
- """ |
- self.recvd = self.recvd + recd |
- while len(self.recvd) >= self.prefixLength and not self.paused: |
- length ,= struct.unpack( |
- self.structFormat, self.recvd[:self.prefixLength]) |
- if length > self.MAX_LENGTH: |
- self.transport.loseConnection() |
- return |
- if len(self.recvd) < length + self.prefixLength: |
- break |
- packet = self.recvd[self.prefixLength:length + self.prefixLength] |
- self.recvd = self.recvd[length + self.prefixLength:] |
- self.stringReceived(packet) |
- |
- def sendString(self, data): |
- """ |
- Send an prefixed string to the other end of the connection. |
- |
- @type data: C{str} |
- """ |
- if len(data) >= 2 ** (8 * self.prefixLength): |
- raise StringTooLongError( |
- "Try to send %s bytes whereas maximum is %s" % ( |
- len(data), 2 ** (8 * self.prefixLength))) |
- self.transport.write(struct.pack(self.structFormat, len(data)) + data) |
- |
- |
-class Int32StringReceiver(IntNStringReceiver): |
- """ |
- A receiver for int32-prefixed strings. |
- |
- An int32 string is a string prefixed by 4 bytes, the 32-bit length of |
- the string encoded in network byte order. |
- |
- This class publishes the same interface as NetstringReceiver. |
- """ |
- structFormat = "!I" |
- prefixLength = struct.calcsize(structFormat) |
- |
- |
-class Int16StringReceiver(IntNStringReceiver): |
- """ |
- A receiver for int16-prefixed strings. |
- |
- An int16 string is a string prefixed by 2 bytes, the 16-bit length of |
- the string encoded in network byte order. |
- |
- This class publishes the same interface as NetstringReceiver. |
- """ |
- structFormat = "!H" |
- prefixLength = struct.calcsize(structFormat) |
- |
- |
-class Int8StringReceiver(IntNStringReceiver): |
- """ |
- A receiver for int8-prefixed strings. |
- |
- An int8 string is a string prefixed by 1 byte, the 8-bit length of |
- the string. |
- |
- This class publishes the same interface as NetstringReceiver. |
- """ |
- structFormat = "!B" |
- prefixLength = struct.calcsize(structFormat) |
- |
- |
-class StatefulStringProtocol: |
- """ |
- A stateful string protocol. |
- |
- This is a mixin for string protocols (Int32StringReceiver, |
- NetstringReceiver) which translates stringReceived into a callback |
- (prefixed with 'proto_') depending on state. |
- |
- The state 'done' is special; if a proto_* method returns it, the |
- connection will be closed immediately. |
- """ |
- |
- state = 'init' |
- |
- def stringReceived(self,string): |
- """Choose a protocol phase function and call it. |
- |
- Call back to the appropriate protocol phase; this begins with |
- the function proto_init and moves on to proto_* depending on |
- what each proto_* function returns. (For example, if |
- self.proto_init returns 'foo', then self.proto_foo will be the |
- next function called when a protocol message is received. |
- """ |
- try: |
- pto = 'proto_'+self.state |
- statehandler = getattr(self,pto) |
- except AttributeError: |
- log.msg('callback',self.state,'not found') |
- else: |
- self.state = statehandler(string) |
- if self.state == 'done': |
- self.transport.loseConnection() |
- |
-class FileSender: |
- """A producer that sends the contents of a file to a consumer. |
- |
- This is a helper for protocols that, at some point, will take a |
- file-like object, read its contents, and write them out to the network, |
- optionally performing some transformation on the bytes in between. |
- """ |
- implements(interfaces.IProducer) |
- |
- CHUNK_SIZE = 2 ** 14 |
- |
- lastSent = '' |
- deferred = None |
- |
- def beginFileTransfer(self, file, consumer, transform = None): |
- """Begin transferring a file |
- |
- @type file: Any file-like object |
- @param file: The file object to read data from |
- |
- @type consumer: Any implementor of IConsumer |
- @param consumer: The object to write data to |
- |
- @param transform: A callable taking one string argument and returning |
- the same. All bytes read from the file are passed through this before |
- being written to the consumer. |
- |
- @rtype: C{Deferred} |
- @return: A deferred whose callback will be invoked when the file has been |
- completely written to the consumer. The last byte written to the consumer |
- is passed to the callback. |
- """ |
- self.file = file |
- self.consumer = consumer |
- self.transform = transform |
- |
- self.deferred = deferred = defer.Deferred() |
- self.consumer.registerProducer(self, False) |
- return deferred |
- |
- def resumeProducing(self): |
- chunk = '' |
- if self.file: |
- chunk = self.file.read(self.CHUNK_SIZE) |
- if not chunk: |
- self.file = None |
- self.consumer.unregisterProducer() |
- if self.deferred: |
- self.deferred.callback(self.lastSent) |
- self.deferred = None |
- return |
- |
- if self.transform: |
- chunk = self.transform(chunk) |
- self.consumer.write(chunk) |
- self.lastSent = chunk[-1] |
- |
- def pauseProducing(self): |
- pass |
- |
- def stopProducing(self): |
- if self.deferred: |
- self.deferred.errback(Exception("Consumer asked us to stop producing")) |
- self.deferred = None |