[Twisted-Python] half-closing SSL connection, unexpected connectionLost() error

Denis Bilenko denis.bilenko at gmail.com
Fri Feb 13 09:35:33 EST 2009


Hi,

What's the correct way to call loseWriteConnection on SSL connection?
I keep getting "Connection was closed in a non-clean fashion" errors
when I do that.

Here's a minimal server and a client that trigger the error. Note that
the server
does not implement IHalfCloseableProtocol and I'd like to keep it that way
(primarily because I'm building a client, not a server, so I'd like my client to
work with as many servers as possible)

---------------------------------------------------------------------------
server.py

from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor

class MyProtocol(Protocol):

    def connectionMade(self):
        print self.transport.getHost(), self.transport.getPeer()

    def connectionLost(self, reason):
        print 'connectionLost %r' % reason.value

class MyFactory(Factory):
    protocol = MyProtocol

from twisted.internet import ssl
contextFactory = ssl.DefaultOpenSSLContextFactory('valid.key',
'valid.crt', sslmethod=ssl.SSL.SSLv3_METHOD)
reactor.listenSSL(10000, MyFactory(), contextFactory)
reactor.run()


---------------------------------------------------------------------------
client.py

import sys
from zope.interface import implements

from twisted.internet.protocol import ClientFactory, Protocol
from twisted.internet.interfaces import IHalfCloseableProtocol
from twisted.internet import reactor

class MyProtocol(Protocol):

    implements(IHalfCloseableProtocol)

    def connectionMade(self):
        print 'connectionMade %s -> %s' % (self.transport.getHost(),
self.transport.getPeer())
        self.transport.loseWriteConnection()

    def readConnectionLost(self):
        print 'readConnectionLost'

    def writeConnectionLost(self):
        print 'writeConnectionLost'

    def connectionLost(self, reason):
        print 'connectionLost %r' % reason.value

class MyFactory(ClientFactory):
    protocol = MyProtocol

    def clientConnectionFailed(self, connector, err):
        print err.value
        reactor.stop()

from twisted.internet import ssl
contextFactory = ssl.ClientContextFactory()
reactor.connectSSL(sys.argv[1], int(sys.argv[2]), MyFactory(), contextFactory)
reactor.run()


---------------------------------------------------------------------------
console1

$ python server.py
IPv4Address(TCP, '127.0.0.1', 10000) IPv4Address(TCP, '127.0.0.1', 40291)
connectionLost ConnectionDone()


---------------------------------------------------------------------------
console2

$ python client.py localhost 10000
connectionMade IPv4Address(TCP, '127.0.0.1', 40291) ->
IPv4Address(TCP, 'localhost', 10000)
writeConnectionLost
connectionLost ConnectionLost()

The question is why it's not ConnectionDone but ConnectionLost that
client receives
in connectionLost callback?
If I convert the examples to use TCP, I get ConnectionDone, as expected.

Thank you for your time.




More information about the Twisted-Python mailing list