| # -*- coding: latin-1 -*- | 
 | # | 
 | # Copyright (C) AB Strakt | 
 | # Copyright (C) Jean-Paul Calderone | 
 | # See LICENSE for details. | 
 |  | 
 | """ | 
 | Simple echo server, using nonblocking I/O | 
 | """ | 
 |  | 
 | from OpenSSL import SSL, crypto | 
 | import sys, os, select, socket | 
 |  | 
 |  | 
 | def verify_cb(conn, cert, errnum, depth, ok): | 
 |     certsubject = crypto.X509Name(cert.get_subject()) | 
 |     commonname = certsubject.commonName | 
 |     print(('Got certificate: ' + commonname)) | 
 |     return ok | 
 |  | 
 | if len(sys.argv) < 2: | 
 |     print('Usage: python server.py PORT') | 
 |     sys.exit(1) | 
 |  | 
 | dir = os.path.dirname(sys.argv[0]) | 
 | if dir == '': | 
 |     dir = os.curdir | 
 |  | 
 | # Initialize context | 
 | ctx = SSL.Context(SSL.SSLv23_METHOD) | 
 | ctx.set_options(SSL.OP_NO_SSLv2) | 
 | ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb) # Demand a certificate | 
 | ctx.use_privatekey_file (os.path.join(dir, 'server.pkey')) | 
 | ctx.use_certificate_file(os.path.join(dir, 'server.cert')) | 
 | ctx.load_verify_locations(os.path.join(dir, 'CA.cert')) | 
 |  | 
 | # Set up server | 
 | server = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM)) | 
 | server.bind(('', int(sys.argv[1]))) | 
 | server.listen(3)  | 
 | server.setblocking(0) | 
 |  | 
 | clients = {} | 
 | writers = {} | 
 |  | 
 | def dropClient(cli, errors=None): | 
 |     if errors: | 
 |         print('Client %s left unexpectedly:' % (clients[cli],)) | 
 |         print('  ', errors) | 
 |     else: | 
 |         print('Client %s left politely' % (clients[cli],)) | 
 |     del clients[cli] | 
 |     if cli in writers: | 
 |         del writers[cli] | 
 |     if not errors: | 
 |         cli.shutdown() | 
 |     cli.close() | 
 |  | 
 | while 1: | 
 |     try: | 
 |         r, w, _ = select.select([server] + list(clients.keys()), list(writers.keys()), []) | 
 |     except: | 
 |         break | 
 |  | 
 |     for cli in r: | 
 |         if cli == server: | 
 |             cli,addr = server.accept() | 
 |             print('Connection from %s' % (addr,)) | 
 |             clients[cli] = addr | 
 |  | 
 |         else: | 
 |             try: | 
 |                 ret = cli.recv(1024).decode('utf-8') | 
 |             except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError): | 
 |                 pass | 
 |             except SSL.ZeroReturnError: | 
 |                 dropClient(cli) | 
 |             except SSL.Error as errors: | 
 |                 dropClient(cli, errors) | 
 |             else: | 
 |                 if cli not in writers: | 
 |                     writers[cli] = '' | 
 |                 writers[cli] = writers[cli] + ret | 
 |  | 
 |     for cli in w: | 
 |         try: | 
 |             ret = cli.send(writers[cli]) | 
 |         except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError): | 
 |             pass | 
 |         except SSL.ZeroReturnError: | 
 |             dropClient(cli) | 
 |         except SSL.Error as errors: | 
 |             dropClient(cli, errors) | 
 |         else: | 
 |             writers[cli] = writers[cli][ret:] | 
 |             if writers[cli] == '': | 
 |                 del writers[cli] | 
 |  | 
 | for cli in clients.keys(): | 
 |     cli.close() | 
 | server.close() |