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 lib.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 _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 _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 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 startListening(self): try: self._bindSocket() self.socket.connect(self.remoteaddr) self._connectToProtocol() except: self.connectionFailed(failure.Failure())
def connectionLost(self, reason): """ Cleans up the socket. """ self._logConnectionLostMsg() 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 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 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 _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 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 _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 _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 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 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 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 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 clearBuffer(self): if self.shouldLose == -1: return if self.producer: self.producer.resumeProducing() if self.buffer: if self.logFile: self.logFile.write("loopback receiving %s\n" % repr(self.buffer)) buffer = self.buffer self.buffer = '' self.target.dataReceived(buffer) if self.shouldLose == 1: self.shouldLose = -1 self.target.connectionLost(failure.Failure(main.CONNECTION_DONE))
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))
def _runWrite(self, fd): closed = 0 try: closed = fd.doWrite() except: closed = sys.exc_info()[1] log.deferr() if closed: self.removeReader(fd) self.removeWriter(fd) try: fd.connectionLost(failure.Failure(closed)) except: log.deferr() elif closed is None: return 1
def _callEventCallback(self, rc, bytes, evt): owner = evt.owner why = None try: evt.callback(rc, bytes, evt) handfn = getattr(owner, 'getFileHandle', None) if not handfn: why = _NO_GETHANDLE elif handfn() == -1: why = _NO_FILEDESC if why: return # ignore handles that were closed except: why = sys.exc_info()[1] log.err() if why: owner.loseConnection(failure.Failure(why))
def _worker(self): """ Method used as target of the created threads: retrieve task to run from the threadpool, run it, and proceed to the next task until threadpool is stopped. """ ct = self.currentThread() o = self.q.get() while o is not WorkerStop: self.working.append(ct) ctx, function, args, kwargs, onResult = o del o try: result = context.call(ctx, function, *args, **kwargs) success = True except: success = False if onResult is None: context.call(ctx, log.err) result = None else: result = failure.Failure() del function, args, kwargs self.working.remove(ct) if onResult is not None: try: context.call(ctx, onResult, success, result) except: context.call(ctx, log.err) del ctx, onResult, result self.waiters.append(ct) o = self.q.get() self.waiters.remove(ct) self.threads.remove(ct)
def failIfNotConnected(self, err): """ Generic method called when the attemps to connect failed. It basically cleans everything it can: call connectionFailed, stop read and write, delete socket related members. """ if (self.connected or self.disconnected or not hasattr(self, "connector")): return self.connector.connectionFailed(failure.Failure(err)) if hasattr(self, "reactor"): # this doesn't happen if we failed in __init__ self.stopReading() self.stopWriting() del self.connector try: self._closeSocket() except AttributeError: pass else: del self.socket, self.fileno
def _fail(self, name, err): err = error.DNSLookupError("address %r not found: %s" % (name, err)) return failure.Failure(err)
def _ebUserCall(self, err, p): return failure.Failure(Exception(p, err))