def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log, faildict=None): if not faildict: faildict = { error.ConnectionDone: failure.Failure(error.ConnectionDone()), error.ConnectionLost: failure.Failure(error.ConnectionLost()) } why = None inRead = False if event & POLL_DISCONNECTED and not (event & POLLIN): why = main.CONNECTION_LOST else: try: if event & POLLIN: why = selectable.doRead() inRead = True if not why and event & POLLOUT: why = selectable.doWrite() inRead = False if not selectable.fileno() == fd: why = error.ConnectionFdescWentAway( 'Filedescriptor went away') inRead = False except AttributeError as ae: if "'NoneType' object has no attribute 'writeHeaders'" not in six.text_type( ae): log.deferr() why = sys.exc_info()[1] else: why = None except: log.deferr() why = sys.exc_info()[1] if why: try: self._disconnectSelectable(selectable, why, inRead) except RuntimeError: pass
def _sendRequest(self, msg, data): """ Send a request and return a deferred which waits for the result. @type msg: L{int} @param msg: The request type (e.g., C{FXP_READ}). @type data: L{bytes} @param data: The body of the request. """ if not self.connected: return defer.fail(error.ConnectionLost()) data = struct.pack('!L', self.counter) + data d = defer.Deferred() self.openRequests[self.counter] = d self.counter += 1 self.sendPacket(msg, data) return d
def _disconnectSelectable(selectable, why, isRead, faildict={ error.ConnectionDone: failure.Failure(error.ConnectionDone()), error.ConnectionLost: failure.Failure(error.ConnectionLost()) }): """ Utility function for disconnecting a selectable. Supports half-close notification, isRead should be boolean indicating whether error resulted from doRead(). """ f = faildict.get(why.__class__) if f: if (isRead and why.__class__ == error.ConnectionDone and interfaces.IHalfCloseableDescriptor.providedBy(selectable)): selectable.readConnectionLost(f) else: selectable.connectionLost(f) else: selectable.connectionLost(failure.Failure(why))
def lostRemote(self, conn=None): # the worker went away. There are several possible reasons for this, # and they aren't necessarily fatal. For now, kill the build, but # TODO: see if we can resume the build when it reconnects. log.msg("%s.lostRemote" % self) self.conn = None self.text = ["lost", "connection"] self.results = RETRY if self.currentStep and self.currentStep.results is None: # this should cause the step to finish. log.msg(" stopping currentStep", self.currentStep) self.currentStep.interrupt(Failure(error.ConnectionLost())) else: self.text = ["lost", "connection"] self.stopped = True if self._acquiringLock: lock, access, d = self._acquiringLock lock.stopWaitingUntilAvailable(self, access, d) d.callback(None)
def connectionLost(self, reason): """ Called when connection to the remote subsystem was lost. Any pending requests are aborted. """ FileTransferBase.connectionLost(self, reason) # If there are still requests waiting for responses when the # connection is lost, fail them. if self.openRequests: # Even if our transport was lost "cleanly", our # requests were still not cancelled "cleanly". requestError = error.ConnectionLost() requestError.__cause__ = reason.value requestFailure = failure.Failure(requestError) while self.openRequests: _, deferred = self.openRequests.popitem() deferred.errback(requestFailure)
def doRead(self): """Poll the connection and process any notifications.""" with self._db_lock: try: self.connection.connection.poll() except Exception: # If the connection goes down then `OperationalError` is raised. # It contains no pgcode or pgerror to identify the reason so no # special consideration can be made for it. Hence all errors are # treated the same, and we assume that the connection is broken. # # We do NOT return a failure, which would signal to the reactor # that the connection is broken in some way, because the reactor # will end up removing this instance from its list of selectables # but not from its list of readable fds, or something like that. # The point is that the reactor's accounting gets muddled. Things # work correctly if we manage the disconnection ourselves. # self.loseConnection(Failure(error.ConnectionLost())) else: self._process_notifies()
def _handleWrite(self, rc, bytes, evt): """ Returns false if we should stop writing for now """ if self.disconnected or self._writeDisconnected: return False # XXX: not handling WSAEWOULDBLOCK # ("too many outstanding overlapped I/O requests") if rc: self.connectionLost( failure.Failure( error.ConnectionLost( "write error -- %s (%s)" % (errno.errorcode.get(rc, 'unknown'), rc)))) return False else: self.offset += bytes # If there is nothing left to send, if self.offset == len(self.dataBuffer) and not self._tempDataLen: self.dataBuffer = "" self.offset = 0 # stop writing self.stopWriting() # If I've got a producer who is supposed to supply me with data if self.producer is not None and ((not self.streamingProducer) or self.producerPaused): # tell them to supply some more. self.producerPaused = True self.producer.resumeProducing() elif self.disconnecting: # But if I was previously asked to let the connection die, # do so. self.connectionLost(failure.Failure(main.CONNECTION_DONE)) elif self._writeDisconnecting: # I was previously asked to half-close the connection. self._writeDisconnected = True self._closeWriteConnection() return False else: return True
def test_portalRejectedSenderAddress(self): """ Test that a C{MAIL FROM} command with an address rejected by an L{smtp.SMTP} instance's portal is responded to with the correct error code. """ class DisallowAnonymousAccess(object): """ Checker for L{IAnonymous} which rejects authentication attempts. """ implements(ICredentialsChecker) credentialInterfaces = (IAnonymous,) def requestAvatarId(self, credentials): return defer.fail(UnauthorizedLogin()) realm = SingletonRealm(smtp.IMessageDelivery, NotImplementedDelivery()) portal = Portal(realm, [DisallowAnonymousAccess()]) proto = smtp.SMTP() proto.portal = portal trans = StringTransport() proto.makeConnection(trans) # Deal with the necessary preliminaries proto.dataReceived('HELO example.com\r\n') trans.clear() # Try to specify our sender address proto.dataReceived('MAIL FROM:<*****@*****.**>\r\n') # Clean up the protocol before doing anything that might raise an # exception. proto.connectionLost(error.ConnectionLost()) # Make sure that we received exactly the correct response self.assertEqual( trans.value(), '550 Cannot receive from specified address ' '<*****@*****.**>: Sender not acceptable\r\n')
def dataReceived(self, data, request_counter=None): '''Original code from Twisted, hacked for request_counter proxying. request_counter is hack for HTTP transport, didn't found cleaner solution how to indicate end of request processing in asynchronous manner. TODO: This would deserve some unit test to be sure that future twisted versions will work nicely with this.''' if request_counter == None: request_counter = RequestCounter() #lines = (self._buffer+data).split(self.delimiter) # Python3 #self._buffer = lines.pop(-1) # Python3 # FIXME: need to check the matter of _buffer lines = (data).decode('utf-8').split(self.delimiter) # Python3 request_counter.set_count(len(lines)) self.on_finish = request_counter.on_finish for line in lines: if self.transport.disconnecting: request_counter.finish() return if len(line) > self.MAX_LENGTH: request_counter.finish() return self.lineLengthExceeded(line) elif line: try: self.lineReceived(line, request_counter) except Exception as exc: request_counter.finish() #log.exception("Processing of message failed") log.warning("Failed message: %s from %s" % (str(exc), self._get_ip())) return error.ConnectionLost('Processing of message failed') if len(self._buffer) > self.MAX_LENGTH: request_counter.finish() return self.lineLengthExceeded(self._buffer)
def _handleRead(self, rc, bytes, evt): """ Returns False if we should stop reading for now """ if self.disconnected: return False # graceful disconnection if (not (rc or bytes)) or rc in (errno.WSAEDISCON, ERROR_HANDLE_EOF): self.reactor.removeActiveHandle(self) self.readConnectionLost(failure.Failure(main.CONNECTION_DONE)) return False # XXX: not handling WSAEWOULDBLOCK # ("too many outstanding overlapped I/O requests") elif rc: self.connectionLost(failure.Failure( error.ConnectionLost("read error -- %s (%s)" % (errno.errorcode.get(rc, 'unknown'), rc)))) return False else: assert self._readSize == 0 assert self._readNextBuffer == 0 self._readSize = bytes return self._dispatchData()
def test_deliveryRejectedSenderAddress(self): """ Test that a C{MAIL FROM} command with an address rejected by a L{smtp.IMessageDelivery} instance is responded to with the correct error code. """ class RejectionDelivery(NotImplementedDelivery): """ Delivery object which rejects all senders as invalid. """ def validateFrom(self, helo, origin): raise smtp.SMTPBadSender(origin) realm = SingletonRealm(smtp.IMessageDelivery, RejectionDelivery()) portal = Portal(realm, [AllowAnonymousAccess()]) proto = smtp.SMTP() proto.portal = portal trans = StringTransport() proto.makeConnection(trans) # Deal with the necessary preliminaries proto.dataReceived('HELO example.com\r\n') trans.clear() # Try to specify our sender address proto.dataReceived('MAIL FROM:<*****@*****.**>\r\n') # Clean up the protocol before doing anything that might raise an # exception. proto.connectionLost(error.ConnectionLost()) # Make sure that we received exactly the correct response self.assertEqual( trans.value(), '550 Cannot receive from specified address ' '<*****@*****.**>: Sender not acceptable\r\n')
# hints for py2app import Carbon.CF import traceback import cfsupport as cf from twisted.python import log, threadable, failure from twisted.internet import posixbase, error from weakref import WeakKeyDictionary from Foundation import NSRunLoop from AppKit import NSApp # cache two extremely common "failures" without traceback info _faildict = { error.ConnectionDone: failure.Failure(error.ConnectionDone()), error.ConnectionLost: failure.Failure(error.ConnectionLost()), } class SelectableSocketWrapper(object): _objCache = WeakKeyDictionary() cf = None def socketWrapperForReactorAndObject(klass, reactor, obj): _objCache = klass._objCache if obj in _objCache: return _objCache[obj] v = _objCache[obj] = klass(reactor, obj) return v socketWrapperForReactorAndObject = classmethod(socketWrapperForReactorAndObject) def __init__(self, reactor, obj):
# -*- test-case-name: twisted.internet.test.test_main -*- # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Backwards compatibility, and utility functions. In general, this module should not be used, other than by reactor authors who need to use the 'installReactor' method. """ from __future__ import division, absolute_import from twisted.internet import error CONNECTION_DONE = error.ConnectionDone('Connection done') CONNECTION_LOST = error.ConnectionLost('Connection lost') def installReactor(reactor): """ Install reactor C{reactor}. @param reactor: An object that provides one or more IReactor* interfaces. """ # this stuff should be common to all reactors. import twisted.internet import sys if 'twisted.internet.reactor' in sys.modules: raise error.ReactorAlreadyInstalledError("reactor already installed") twisted.internet.reactor = reactor sys.modules['twisted.internet.reactor'] = reactor
def connectionLost(reason): """Catch disconnect and force a ConnectionLost.""" orig_connectionLost(failure.Failure(txerror.ConnectionLost())) d.callback(None)
# -*- test-case-name: twisted.internet.test.test_main -*- # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Backwards compatibility, and utility functions. In general, this module should not be used, other than by reactor authors who need to use the 'installReactor' method. """ from twisted.internet import error CONNECTION_DONE = error.ConnectionDone("Connection done") CONNECTION_LOST = error.ConnectionLost("Connection lost") def installReactor(reactor): """ Install reactor C{reactor}. @param reactor: An object that provides one or more IReactor* interfaces. """ # this stuff should be common to all reactors. import sys import twisted.internet if "twisted.internet.reactor" in sys.modules: raise error.ReactorAlreadyInstalledError("reactor already installed") twisted.internet.reactor = reactor sys.modules["twisted.internet.reactor"] = reactor
def connectionTimedOut(self): err = error.ConnectionLost("banana timeout: connection dropped") why = failure.Failure(err) self.shutdown(why)
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')
def connectionLost(self): self.factory.callback(failure.Failure(error.ConnectionLost()))