[Python-Dev] ssl module integration with asyncore

Bill Janssen janssen at parc.com
Thu Nov 29 03:27:33 CET 2007


> It does raise the same exception.

Hmmm, not in my version.

> Are there plans for fixing this?

Yes, it's fixed in my CVS, and I'll upload a new version to PyPI when
I get a chance.

> Using that kind of workaround is not acceptable in any case (select
> module shouldn't even get imported when using asyncore).

Well, that's what the fix in the SSL module will do under the covers,
so if there's a reason not to do it, or a better way of doing it,
speak now.  It really has nothing to do with asyncore; it's just a way
of safely handling a socket which may or may not be non-blocking.

A more extended example, more true to the asyncore way of doing
things, would in fact keep track of the connection state in a local
variable, and would consult that in "handle_read_event" and
"handle_write_event", calling do_handshake again if it's still not
completed.  That way you could get rid of the select.

Here's my (working) version of your code.  Note that I inherit from
dispatcher_with_send to make sure I have a working "handle_write"
method.

Bill

--- snippet ---
import asyncore, asynchat, socket, ssl, select

class Handler(asyncore.dispatcher_with_send):

    def __init__(self, conn):
        asyncore.dispatcher_with_send.__init__(self, conn)
        self.socket = ssl.wrap_socket(conn, server_side=True,
                                      certfile='keycert.pem',
                                      do_handshake_on_connect=False)
        while True:
            try:
                self.socket.do_handshake()
                break
            except ssl.SSLError, err:
                if err.args[0] == ssl.SSL_ERROR_WANT_READ:
                    select.select([self.socket], [], [])
                elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
                    select.select([], [self.socket], [])
                else:
                    raise
        self.send("hello there!")        

    def readable(self):
        if isinstance(self.socket, ssl.SSLSocket):
            while self.socket.pending() > 0:
                self.handle_read_event()
        return True

    def handle_read(self):
        data = self.recv(1024)
        print data

    def handle_error(self):
        raise

class Server(asyncore.dispatcher):

    def __init__(self):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind(('', 54321))
        self.listen(5)

    def handle_accept(self):
        sock_obj, addr = self.accept()
        print "[]%s:%s Connected." %addr
        Handler(sock_obj)

    def handle_error(self):
        raise

Server()
asyncore.loop(timeout=1)
--- /snippet ---


More information about the Python-Dev mailing list