def _doReadOrWrite( self, source, condition, faildict={ error.ConnectionDone: failure.Failure(error.ConnectionDone()), error.ConnectionLost: failure.Failure(error.ConnectionLost()), }): why = None inRead = False if condition & POLL_DISCONNECTED and not (condition & gobject.IO_IN): if source in self._reads: why = main.CONNECTION_DONE inRead = True else: why = main.CONNECTION_LOST else: try: if condition & gobject.IO_IN: why = source.doRead() inRead = True if not why and condition & gobject.IO_OUT: # if doRead caused connectionLost, don't call doWrite # if doRead is doWrite, don't call it again. if not source.disconnected: why = source.doWrite() except: why = sys.exc_info()[1] log.msg('Error In %s' % source) log.deferr() if why: self._disconnectSelectable(source, why, inRead)
def _disconnectSelectable( self, 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(). """ self.removeReader(selectable) f = faildict.get(why.__class__) if f: if (isRead and why.__class__ == error.ConnectionDone and IHalfCloseableDescriptor.providedBy(selectable)): selectable.readConnectionLost(f) else: self.removeWriter(selectable) selectable.connectionLost(f) else: self.removeWriter(selectable) selectable.connectionLost(failure.Failure(why))
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 loopback(server, client, logFile=None): """Run session between server and client. DEPRECATED in Twisted 2.5. Use loopbackAsync instead. """ import warnings warnings.warn( 'loopback() is deprecated (since Twisted 2.5). ' 'Use loopbackAsync() instead.', stacklevel=2, category=DeprecationWarning) from reqs.twisted.internet import reactor serverToClient = LoopbackRelay(client, logFile) clientToServer = LoopbackRelay(server, logFile) server.makeConnection(serverToClient) client.makeConnection(clientToServer) while 1: reactor.iterate(0.01) # this is to clear any deferreds serverToClient.clearBuffer() clientToServer.clearBuffer() if serverToClient.shouldLose: serverToClient.clearBuffer() server.connectionLost(failure.Failure(main.CONNECTION_DONE)) break elif clientToServer.shouldLose: client.connectionLost(failure.Failure(main.CONNECTION_DONE)) break reactor.iterate() # last gasp before I go away
def errReceivedIsBad(self, text): if self.deferred is not None: self.onProcessEnded = defer.Deferred() err = _UnexpectedErrorOutput(text, self.onProcessEnded) self.deferred.errback(failure.Failure(err)) self.deferred = None self.transport.loseConnection()
def disconnectAll(self): """Disconnect every reader, and writer in the system. """ selectables = self.removeAll() for reader in selectables: log.callWithLogger(reader, reader.connectionLost, failure.Failure(main.CONNECTION_LOST))
def connectionLost(self, reason): """ Cleans up the socket. """ log.msg('(Port %s Closed)' % self._realPortNumber) self._realPortNumber = None d = None if hasattr(self, "deferred"): d = self.deferred del self.deferred self.disconnected = True self.reactor.removeActiveHandle(self) self.connected = False self._closeSocket() del self.socket del self.getFileHandle try: self.factory.doStop() except: self.disconnecting = False if d is not None: d.errback(failure.Failure()) else: raise else: self.disconnecting = False if d is not None: d.callback(None)
def startListening(self): try: self._bindSocket() self.socket.connect(self.remoteaddr) self._connectToProtocol() except: self.connectionFailed(failure.Failure())
def loseConnection(self, _connDone=failure.Failure(main.CONNECTION_DONE)): """ Close the connection at the next available opportunity. Call this to cause this FileDescriptor to lose its connection. It will first write any data that it has buffered. If there is data buffered yet to be written, this method will cause the transport to lose its connection as soon as it's done flushing its write buffer. If you have a producer registered, the connection won't be closed until the producer is finished. Therefore, make sure you unregister your producer when it's finished, or the connection will never close. """ if self.connected and not self.disconnecting: if self._writeDisconnected: # doWrite won't trigger the connection close anymore self.stopReading() self.stopWriting self.connectionLost(_connDone) else: self.stopReading() self.startWriting() self.disconnecting = 1
def maybeDeferred(f, *args, **kw): """ Invoke a function that may or may not return a L{Deferred}. Call the given function with the given arguments. If the returned object is a L{Deferred}, return it. If the returned object is a L{Failure}, wrap it with L{fail} and return it. Otherwise, wrap it in L{succeed} and return it. If an exception is raised, convert it to a L{Failure}, wrap it in L{fail}, and then return it. @type f: Any callable @param f: The callable to invoke @param args: The arguments to pass to C{f} @param kw: The keyword arguments to pass to C{f} @rtype: L{Deferred} @return: The result of the function call, wrapped in a L{Deferred} if necessary. """ try: result = f(*args, **kw) except: return fail(failure.Failure()) if isinstance(result, Deferred): return result elif isinstance(result, failure.Failure): return fail(result) else: return succeed(result)
def cancel(self): """ Cancel this L{Deferred}. If the L{Deferred} has not yet had its C{errback} or C{callback} method invoked, call the canceller function provided to the constructor. If that function does not invoke C{callback} or C{errback}, or if no canceller function was provided, errback with L{CancelledError}. If this L{Deferred} is waiting on another L{Deferred}, forward the cancellation to the other L{Deferred}. """ if not self.called: canceller = self._canceller if canceller: canceller(self) else: # Arrange to eat the callback that will eventually be fired # since there was no real canceller. self._suppressAlreadyCalled = 1 if not self.called: # There was no canceller, or the canceller didn't call # callback or errback. self.errback(failure.Failure(CancelledError())) elif isinstance(self.result, Deferred): # Waiting for another deferred -- cancel it instead. self.result.cancel()
def errback(self, fail=None): """ Run all error callbacks that have been added to this L{Deferred}. Each callback will have its result passed as the first argument to the next; this way, the callbacks act as a 'processing chain'. Also, if the error-callback returns a non-Failure or doesn't raise an L{Exception}, processing will continue on the *success*-callback chain. If the argument that's passed to me is not a L{failure.Failure} instance, it will be embedded in one. If no argument is passed, a L{failure.Failure} instance will be created based on the current traceback stack. Passing a string as `fail' is deprecated, and will be punished with a warning message. @raise NoCurrentExceptionError: If C{fail} is C{None} but there is no current exception state. """ if not isinstance(fail, failure.Failure): fail = failure.Failure(fail) self._startRunCallbacks(fail)
def runTest(self): packets=["FLAPON\r\n\r\n",\ flap(1,"\000\000\000\001\000\001\000\004test"),\ flap(2,"toc_signon null 9999 test 0x100000 english \"penguin 0.1\"\000"),\ flap(2,"toc_init_done\000"),\ flap(2,"toc_send_im test hi\000")] shouldbe=[[1,"\000\000\000\001"],\ [2,"SIGN_ON:TOC1.0\000"],\ [2,"NICK:test\000"],\ [2,"CONFIG:\000"],\ [2,"IM_IN:test:F:hi\000"]] data="" for i in packets: data=data+i s=StringIOWithoutClosing() d=DummyTOC() fac=toc.TOCFactory() d.factory=fac d.makeConnection(protocol.FileWrapper(s)) d.dataReceived(data) d.connectionLost(failure.Failure(main.CONNECTION_DONE)) value=s.getvalue() flaps=[] f,value=readFlap(value) while f: flaps.append(f) f,value=readFlap(value) if flaps!=shouldbe: for i in range(len(flaps)): if flaps[i]!=shouldbe[i]:raise AssertionError("MultiPacketTest Failed!\nactual:%s\nshould be:%s"%(flaps[i],shouldbe[i])) raise AssertionError("MultiPacketTest Failed with incorrect length!, printing both lists\nactual:%s\nshould be:%s"%(flaps,shouldbe))
def lookupUser(self, name): assert isinstance(name, unicode) name = name.lower() try: user = self.users[name] except KeyError: return defer.fail(failure.Failure(ewords.NoSuchUser(name))) else: return defer.succeed(user)
def lookupGroup(self, name): assert isinstance(name, unicode) name = name.lower() try: group = self.groups[name] except KeyError: return defer.fail(failure.Failure(ewords.NoSuchGroup(name))) else: return defer.succeed(group)
def readConnectionLost(self, reason): p = interfaces.IHalfCloseableProtocol(self.protocol, None) if p: try: p.readConnectionLost() except: log.err() self.connectionLost(failure.Failure()) else: self.connectionLost(reason)
def _cancelLock(): self._tryLockCall.cancel() self._tryLockCall = None self._timeoutCall = None if self.lock(): d.callback(None) else: d.errback( failure.Failure( TimeoutError("Timed out aquiring lock: %s after %fs" % (self.name, timeout))))
def _joinAddr2(self, interface, addr, join): addr = socket.inet_aton(addr) interface = socket.inet_aton(interface) if join: cmd = socket.IP_ADD_MEMBERSHIP else: cmd = socket.IP_DROP_MEMBERSHIP try: self.socket.setsockopt(socket.IPPROTO_IP, cmd, addr + interface) except socket.error, e: return failure.Failure( error.MulticastJoinError(addr, interface, *e.args))
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 to half-close the connection. self._closeWriteConnection() self._writeDisconnected = True return False else: return True
def _closeWriteConnection(self): try: getattr(self.socket, self._socketShutdownMethod)(1) except socket.error: pass p = interfaces.IHalfCloseableProtocol(self.protocol, None) if p: try: p.writeConnectionLost() except: f = failure.Failure() log.err() self.connectionLost(f)
def onStreamError(self, errelem): """ Called when a stream:error element has been received. Dispatches a L{STREAM_ERROR_EVENT} event with the error element to allow for cleanup actions and drops the connection. @param errelem: The received error element. @type errelem: L{domish.Element} """ self.dispatch(failure.Failure(error.exceptionFromStreamError(errelem)), STREAM_ERROR_EVENT) self.transport.loseConnection()
def _writeConnectionLost(self, reason): self._writer = None if self.disconnecting: self.connectionLost(reason) return p = interfaces.IHalfCloseableProtocol(self.protocol, None) if p: try: p.writeConnectionLost() except: log.err() self.connectionLost(failure.Failure())
def loseConnection(self, connDone=failure.Failure(main.CONNECTION_DONE)): """ Stop accepting connections on this port. This will shut down my socket and call self.connectionLost(). It returns a deferred which will fire successfully when the port is actually closed. """ self.disconnecting = True if self.connected: self.deferred = defer.Deferred() self.reactor.callLater(0, self.connectionLost, connDone) return self.deferred
def test_onError(self): """ An observer for stream errors should trigger onError to log it. """ self.xmlstream.dispatch(self.xmlstream, xmlstream.STREAM_CONNECTED_EVENT) class TestError(Exception): pass reason = failure.Failure(TestError()) self.xmlstream.dispatch(reason, xmlstream.STREAM_ERROR_EVENT) self.assertEqual(1, len(self.flushLoggedErrors(TestError)))
def loseConnection(self, connDone=failure.Failure(main.CONNECTION_DONE)): """ Stop accepting connections on this port. This will shut down the socket and call self.connectionLost(). It returns a deferred which will fire successfully when the port is actually closed, or with a failure if an error occurs shutting down. """ self.disconnecting = True self.stopReading() if self.connected: self.deferred = deferLater(self.reactor, 0, self.connectionLost, connDone) return self.deferred
def _finishReadOrWrite(self, fn, faildict=_faildict): try: why = fn() except: why = sys.exc_info()[1] log.err() if why: try: f = faildict.get(why.__class__) or failure.Failure(why) self.objConnectionLost(f) except: log.err() if self.reactor.running: self.reactor.simulate()
def failIfNotConnected(self, err): if (self.connected or self.disconnected or not hasattr(self, "connector")): return try: self._closeSocket() except AttributeError: pass else: del self.socket, self.getFileHandle self.reactor.removeActiveHandle(self) self.connector.connectionFailed(failure.Failure(err)) del self.connector
def dataReceived(self, data): """ Called whenever data is received. Passes the data to the XML parser. This can result in calls to the DOM handlers. If a parse error occurs, the L{STREAM_ERROR_EVENT} event is called to allow for cleanup actions, followed by dropping the connection. """ try: if self.rawDataInFn: self.rawDataInFn(data) self.stream.parse(data) except domish.ParserError: self.dispatch(failure.Failure(), STREAM_ERROR_EVENT) self.transport.loseConnection()
def lineReceived(self, line): parts = line.split(',') if len(parts) != 2: self.invalidQuery() else: try: portOnServer, portOnClient = map(int, parts) except ValueError: self.invalidQuery() else: if _MIN_PORT <= portOnServer <= _MAX_PORT and _MIN_PORT <= portOnClient <= _MAX_PORT: self.validQuery(portOnServer, portOnClient) else: self._ebLookup(failure.Failure(InvalidPort()), portOnServer, portOnClient)
def _doWriteOrRead(self, selectable, fd, filter): try: if filter == EVFILT_READ: why = selectable.doRead() if filter == EVFILT_WRITE: why = selectable.doWrite() if not selectable.fileno() == fd: why = main.CONNECTION_LOST except: why = sys.exc_info()[1] log.deferr() if why: self.removeReader(selectable) self.removeWriter(selectable) selectable.connectionLost(failure.Failure(why))