def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log,
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:
log.deferr()
why = sys.exc_info()[1]
if why:
self._disconnectSelectable(selectable, why, inRead)
python类ConnectionLost()的实例源码
def _cbLostConns(self, results):
(sSuccess, sResult), (cSuccess, cResult) = results
self.failIf(sSuccess)
self.failIf(cSuccess)
acceptableErrors = [SSL.Error]
# Rather than getting a verification failure on Windows, we are getting
# a connection failure. Without something like sslverify proxying
# in-between we can't fix up the platform's errors, so let's just
# specifically say it is only OK in this one case to keep the tests
# passing. Normally we'd like to be as strict as possible here, so
# we're not going to allow this to report errors incorrectly on any
# other platforms.
if platform.isWindows():
from twisted.internet.error import ConnectionLost
acceptableErrors.append(ConnectionLost)
sResult.trap(*acceptableErrors)
cResult.trap(*acceptableErrors)
return self.serverPort.stopListening()
def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log,
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:
log.deferr()
why = sys.exc_info()[1]
if why:
self._disconnectSelectable(selectable, why, inRead)
def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log,
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:
log.deferr()
why = sys.exc_info()[1]
if why:
self._disconnectSelectable(selectable, why, inRead)
def _cbLostConns(self, results):
(sSuccess, sResult), (cSuccess, cResult) = results
self.failIf(sSuccess)
self.failIf(cSuccess)
acceptableErrors = [SSL.Error]
# Rather than getting a verification failure on Windows, we are getting
# a connection failure. Without something like sslverify proxying
# in-between we can't fix up the platform's errors, so let's just
# specifically say it is only OK in this one case to keep the tests
# passing. Normally we'd like to be as strict as possible here, so
# we're not going to allow this to report errors incorrectly on any
# other platforms.
if platform.isWindows():
from twisted.internet.error import ConnectionLost
acceptableErrors.append(ConnectionLost)
sResult.trap(*acceptableErrors)
cResult.trap(*acceptableErrors)
return self.serverPort.stopListening()
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:
log.deferr()
why = sys.exc_info()[1]
if why:
self._disconnectSelectable(selectable, why, inRead)
def test_someResponseButNotAll(self):
"""
If a partial response was received and the connection is lost, the
resulting error is L{ResponseFailed}, but not
L{ResponseNeverReceived}.
"""
protocol = HTTPClientParser(
Request(b'HEAD', b'/', _boringHeaders, None),
lambda ign: None)
d = protocol._responseDeferred
protocol.makeConnection(StringTransport())
protocol.dataReceived(b'2')
protocol.connectionLost(ConnectionLost())
return self.assertFailure(d, ResponseFailed).addCallback(
self.assertIsInstance, ResponseFailed)
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 _cbLostConns(self, results):
(sSuccess, sResult), (cSuccess, cResult) = results
self.assertFalse(sSuccess)
self.assertFalse(cSuccess)
acceptableErrors = [SSL.Error]
# Rather than getting a verification failure on Windows, we are getting
# a connection failure. Without something like sslverify proxying
# in-between we can't fix up the platform's errors, so let's just
# specifically say it is only OK in this one case to keep the tests
# passing. Normally we'd like to be as strict as possible here, so
# we're not going to allow this to report errors incorrectly on any
# other platforms.
if platform.isWindows():
from twisted.internet.error import ConnectionLost
acceptableErrors.append(ConnectionLost)
sResult.trap(*acceptableErrors)
cResult.trap(*acceptableErrors)
return self.serverPort.stopListening()
def test_unexpectedEOF(self):
"""
Unexpected disconnects get converted to ConnectionLost errors.
"""
tlsClient, tlsServer, handshakeDeferred, disconnectDeferred = (
self.handshakeProtocols())
serverProtocol = tlsServer.wrappedProtocol
data = []
reason = []
serverProtocol.dataReceived = data.append
serverProtocol.connectionLost = reason.append
# Write data, then disconnect *underlying* transport, resulting in an
# unexpected TLS disconnect:
def handshakeDone(ign):
tlsClient.write(b"hello")
tlsClient.transport.loseConnection()
handshakeDeferred.addCallback(handshakeDone)
# Receiver should be disconnected, with ConnectionLost notification
# (masking the Unexpected EOF SSL error):
def disconnected(ign):
self.assertTrue(reason[0].check(ConnectionLost), reason[0])
disconnectDeferred.addCallback(disconnected)
return disconnectDeferred
def sendBox(self, box):
"""
Send a amp.Box to my peer.
Note: transport.write is never called outside of this method.
@param box: an AmpBox.
@raise ProtocolSwitched: if the protocol has previously been switched.
@raise ConnectionLost: if the connection has previously been lost.
"""
if self._locked:
raise ProtocolSwitched(
"This connection has switched: no AMP traffic allowed.")
if self.transport is None:
raise ConnectionLost()
if self._startingTLSBuffer is not None:
self._startingTLSBuffer.append(box)
else:
self.transport.write(box.serialize())
def test_cancelledIsEatenOnConnectionLost(self):
app = self.app
request = requestMock(b"/")
@app.route("/")
def root(request):
_d = Deferred()
request.notifyFinish().addErrback(lambda _: _d.cancel())
return _d
d = _render(self.kr, request)
self.assertNotFired(d)
request.connectionLost(ConnectionLost())
def _cb(result):
self.assertEqual(request.processingFailed.call_count, 0)
d.addErrback(lambda f: f.trap(ConnectionLost))
d.addCallback(_cb)
self.assertFired(d)
def test_cancelsOnConnectionLost(self):
app = self.app
request = requestMock(b"/")
handler_d = Deferred()
@app.route("/")
def root(request):
return handler_d
d = _render(self.kr, request)
self.assertNotFired(d)
request.connectionLost(ConnectionLost())
handler_d.addErrback(lambda f: f.trap(CancelledError))
d.addErrback(lambda f: f.trap(ConnectionLost))
d.addCallback(lambda _: handler_d)
self.assertFired(d)
def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log,
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:
log.deferr()
why = sys.exc_info()[1]
if why:
self._disconnectSelectable(selectable, why, inRead)
def _invoke_callback(self, fd, events):
if fd not in self._fds:
return
(reader, writer) = self._fds[fd]
if reader:
err = None
if reader.fileno() == -1:
err = error.ConnectionLost()
elif events & IOLoop.READ:
err = log.callWithLogger(reader, reader.doRead)
if err is None and events & IOLoop.ERROR:
err = error.ConnectionLost()
if err is not None:
self.removeReader(reader)
reader.readConnectionLost(failure.Failure(err))
if writer:
err = None
if writer.fileno() == -1:
err = error.ConnectionLost()
elif events & IOLoop.WRITE:
err = log.callWithLogger(writer, writer.doWrite)
if err is None and events & IOLoop.ERROR:
err = error.ConnectionLost()
if err is not None:
self.removeWriter(writer)
writer.writeConnectionLost(failure.Failure(err))
def _invoke_callback(self, fd, events):
if fd not in self._fds:
return
(reader, writer) = self._fds[fd]
if reader:
err = None
if reader.fileno() == -1:
err = error.ConnectionLost()
elif events & IOLoop.READ:
err = log.callWithLogger(reader, reader.doRead)
if err is None and events & IOLoop.ERROR:
err = error.ConnectionLost()
if err is not None:
self.removeReader(reader)
reader.readConnectionLost(failure.Failure(err))
if writer:
err = None
if writer.fileno() == -1:
err = error.ConnectionLost()
elif events & IOLoop.WRITE:
err = log.callWithLogger(writer, writer.doWrite)
if err is None and events & IOLoop.ERROR:
err = error.ConnectionLost()
if err is not None:
self.removeWriter(writer)
writer.writeConnectionLost(failure.Failure(err))
def _invoke_callback(self, fd, events):
if fd not in self._fds:
return
(reader, writer) = self._fds[fd]
if reader:
err = None
if reader.fileno() == -1:
err = error.ConnectionLost()
elif events & IOLoop.READ:
err = log.callWithLogger(reader, reader.doRead)
if err is None and events & IOLoop.ERROR:
err = error.ConnectionLost()
if err is not None:
self.removeReader(reader)
reader.readConnectionLost(failure.Failure(err))
if writer:
err = None
if writer.fileno() == -1:
err = error.ConnectionLost()
elif events & IOLoop.WRITE:
err = log.callWithLogger(writer, writer.doWrite)
if err is None and events & IOLoop.ERROR:
err = error.ConnectionLost()
if err is not None:
self.removeWriter(writer)
writer.writeConnectionLost(failure.Failure(err))
def testDisconnectCleanup(self):
"""
Test if deferreds for iq's that haven't yet received a response
have their errback called on stream disconnect.
"""
d = self.iq.send()
xs = self.xmlstream
xs.connectionLost("Closed by peer")
self.assertFailure(d, ConnectionLost)
return d
def testDisconnectTimeoutCancellation(self):
"""
Test if timeouts for iq's that haven't yet received a response
are cancelled on stream disconnect.
"""
self.iq.timeout = 60
d = self.iq.send()
xs = self.xmlstream
xs.connectionLost("Closed by peer")
self.assertFailure(d, ConnectionLost)
self.failIf(self.clock.calls)
return d
def _doReadOrWrite(self, source, condition, faildict={
error.ConnectionDone: failure.Failure(error.ConnectionDone()),
error.ConnectionLost: failure.Failure(error.ConnectionLost()),
}):
why = None
didRead = None
if condition & POLL_DISCONNECTED and \
not (condition & gobject.IO_IN):
why = main.CONNECTION_LOST
else:
try:
if condition & gobject.IO_IN:
why = source.doRead()
didRead = source.doRead
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 and source.doWrite != didRead:
why = source.doWrite()
didRead = source.doWrite # if failed it was in write
except:
why = sys.exc_info()[1]
log.msg('Error In %s' % source)
log.deferr()
if why:
self._disconnectSelectable(source, why, didRead == source.doRead)
def tearDown(self):
"""
Deliver disconnection notification to the client so that it can
perform any cleanup which may be required.
"""
self.client.connectionLost(error.ConnectionLost())
def _loseAndPass(err, proto):
# be specific, pass on the error to the client.
err.trap(error.ConnectionLost, error.ConnectionDone)
del proto.connectionLost
proto.connectionLost(err)
def testLostConnection(self):
p = ident.IdentClient()
L = []
d = defer.Deferred()
d.addErrback(L.append)
p.queries.append((d, 765, 432))
p.connectionLost(failure.Failure(error.ConnectionLost()))
self.failUnless(L[0].value.__class__ is ident.IdentError)
def testLineTooLong(self):
"""
Test sending a line too long: it should close the connection.
"""
t = StringIOWithoutClosing()
a = LineOnlyTester()
a.makeConnection(protocol.FileWrapper(t))
res = a.dataReceived('x'*200)
self.assertTrue(isinstance(res, error.ConnectionLost))
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, ae:
if "'NoneType' object has no attribute 'writeHeaders'" not in ae.message:
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 abortConnection(self):
if not self.connected:
return
self.connected = False
self.aborted = True
self.client.connectionLost(Failure(ConnectionLost()))
def test_connection_lost(self):
"""Test closing a client after the connection is lost."""
channel = self.successResultOf(self.protocol.channel(0))
d = channel.basic_consume(queue="test-queue")
self.transport.abortConnection()
self.assertTrue(self.protocol.closed)
failure = self.failureResultOf(d)
self.assertIsInstance(failure.value, Closed)
self.assertIsInstance(failure.value.args[0].value, ConnectionLost)
def testDisconnectCleanup(self):
"""
Test if deferreds for iq's that haven't yet received a response
have their errback called on stream disconnect.
"""
d = self.iq.send()
xs = self.xmlstream
xs.connectionLost("Closed by peer")
self.assertFailure(d, ConnectionLost)
return d
def testDisconnectTimeoutCancellation(self):
"""
Test if timeouts for iq's that haven't yet received a response
are cancelled on stream disconnect.
"""
self.iq.timeout = 60
d = self.iq.send()
xs = self.xmlstream
xs.connectionLost("Closed by peer")
self.assertFailure(d, ConnectionLost)
self.failIf(self.clock.calls)
return d
def _doReadOrWrite(self, source, condition, faildict={
error.ConnectionDone: failure.Failure(error.ConnectionDone()),
error.ConnectionLost: failure.Failure(error.ConnectionLost()),
}):
why = None
didRead = None
if condition & POLL_DISCONNECTED and \
not (condition & gobject.IO_IN):
why = main.CONNECTION_LOST
else:
try:
if condition & gobject.IO_IN:
why = source.doRead()
didRead = source.doRead
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 and source.doWrite != didRead:
why = source.doWrite()
didRead = source.doWrite # if failed it was in write
except:
why = sys.exc_info()[1]
log.msg('Error In %s' % source)
log.deferr()
if why:
self._disconnectSelectable(source, why, didRead == source.doRead)