Logo Search packages:      
Sourcecode: m2crypto version File versions  Download package

dispatcher.py

#!/usr/local/bin/python -O
"""
   Implements a [hopefully] non-blocking SSL dispatcher on top of
   M2Crypto package.
   
   Written by Ilya Etingof <ilya@glas.net>, 05/2001
"""
import asyncore, socket

# M2Crypto
from M2Crypto import SSL

00013 class _nb_connection (SSL.Connection):
    """Functional equivalent of SSL.Connection class. Facilitates
       possibly delayed socket.connect() and socket.accept()
       termination.
    """
    def __init__ (self, ctx, sock):
        SSL.Connection.__init__ (self, ctx, sock)
        
    def connect(self, addr):
        self._setup_ssl(addr)
        return self._check_ssl_return(SSL.m2.ssl_connect(self.ssl))

    def accept(self, addr):
        self._setup_ssl(addr)
        self.accept_ssl()
                
00029 class dispatcher(asyncore.dispatcher_with_send):
    """A non-blocking SSL dispatcher that mimics the 
       asyncode.dispatcher API.
    """
    def __init__ (self, cert, key, sock=None, serving=None):
        asyncore.dispatcher_with_send.__init__ (self)
        
        self.__serving = serving

        # XXX
        if sock:
            if self.__serving:
                self.set_socket(sock)
        else:
            self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
            
        self.ctx = SSL.Context('sslv23')
        self.ctx.set_verify(SSL.verify_none, 10)
        self.ctx.load_cert(cert, key)
        self.ctx.set_info_callback()

        self.ssl = _nb_connection(self.ctx, self.socket)
        
        self.__output = ''
        self.__want_write = 1

    #
    # The following are asyncore overloaded methods
    #
    
00059     def handle_connect (self):
        """Initiate SSL connection negotiation
        """
        if self.__serving:
            self.ssl.accept (self.addr)

            self.peer = self.ssl.get_peer_cert()
        
            self.handle_ssl_accept()

        else:
            self.ssl.connect (self.addr)

            self.handle_ssl_connect()

00074     def handle_read(self):
        """Read user and/or SSL protocol data from SSL connection
        """
        ret = self.ssl._read_nbio()

        if ret:
            self.handle_ssl_read(ret)
        else:
            # Assume write is wanted
            self.__want_write = 1

00085     def handle_write(self):
        """Write pending user and/or SSL protocol data down to SSL
           connection
        """
        self.__want_write = 0

        ret = self.ssl._write_nbio(self.__output)
        
        if ret < 0:
            try:
                err = SSL.m2.ssl_get_error(self.ssl.ssl, ret)

            except SSL.SSLError:
                return
            
            if err == SSL.m2.ssl_error_want_write:
                self.__want_write = 1
        else:
            self.__output = self.__output[ret:]

00105     def writable (self):
        """Indicate that write is desired if here're some
           user and/or SSL protocol data.
        """
        if self.__output or self.__want_write:
            return 1

        return self.ssl_writable()

00114     def handle_close (self):
        """Shutdown SSL connection.
        """
        self.ssl = None
        
        self.ctx = None
        self.close ()

        self.handle_ssl_close()

00124     def handle_error (self, *info):
        """A trap for asyncore errors
        """
        self.handle_ssl_error(info)

    #
    # The following are ssl.dispatcher API
    #
    
00133     def ssl_connect(self, server):
        """Initiate SSL connection
        """
        self.connect(server)
    
00138     def ssl_write(self, data):
        """Write data to SSL connection
        """
        self.__output = self.__output + data

00143     def ssl_close(self):
        """Close SSL connection
        """
        self.handle_close()
        
00148     def handle_ssl_connect(self):
        """Invoked on SSL connection establishment (whilst
           in client mode)
        """
        print 'Unhandled handle_ssl_connect()'

00154     def handle_ssl_accept(self):
        """Invoked on SSL connection establishment (whilst
           in server mode)
        """
        print 'Unhandled handle_ssl_accept()'
        
00160     def handle_ssl_read(self, data):
        """Invoked on new data arrival to SSL connection
        """
        print 'Unhandled handle_ssl_read event'

00165     def handle_ssl_close(self):
        """Invoked on SSL connection termination
        """
        pass

00170     def ssl_writable(self):
        """Invoked prior to every select() call
        """
        return 0
    
if __name__=='__main__':
    """Give it a test run
    """
00178     class client(dispatcher):
        """SSL client class
        """
        def __init__ (self, cert, key):
            dispatcher.__init__(self, cert, key)
            
00184         def handle_ssl_read(self, data):
            print data            
            self.ssl_write('test write')

    ssl = client('test.cert', 'test.key')
    ssl.ssl_connect(('localhost', 7777))
    
    asyncore.loop()

Generated by  Doxygen 1.6.0   Back to index