blob: df7c5a4e373e7d9aab65279599501c3a1de5b54c [file] [log] [blame]
Jean-Paul Calderone3de9f622008-03-12 14:12:19 -04001# -*- coding: latin-1 -*-
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05002#
Jean-Paul Calderonede0a71e2011-03-02 19:55:11 -05003# Copyright (C) AB Strakt
4# Copyright (C) Jean-Paul Calderone
5# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04006
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05007"""
8Simple echo server, using nonblocking I/O
9"""
10
Jim Shaverb2ff5be2015-04-30 08:26:29 -040011from OpenSSL import SSL, crypto
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050012import sys, os, select, socket
13
14
15def verify_cb(conn, cert, errnum, depth, ok):
Jim Shaverb2ff5be2015-04-30 08:26:29 -040016 certsubject = crypto.X509Name(cert.get_subject())
17 commonname = certsubject.commonName
18 print(('Got certificate: ' + commonname))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050019 return ok
20
21if len(sys.argv) < 2:
Jim Shaver8a4a7ae2015-04-29 01:17:33 -040022 print('Usage: python server.py PORT')
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050023 sys.exit(1)
24
25dir = os.path.dirname(sys.argv[0])
26if dir == '':
27 dir = os.curdir
28
29# Initialize context
30ctx = SSL.Context(SSL.SSLv23_METHOD)
31ctx.set_options(SSL.OP_NO_SSLv2)
32ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb) # Demand a certificate
33ctx.use_privatekey_file (os.path.join(dir, 'server.pkey'))
34ctx.use_certificate_file(os.path.join(dir, 'server.cert'))
35ctx.load_verify_locations(os.path.join(dir, 'CA.cert'))
36
37# Set up server
38server = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
39server.bind(('', int(sys.argv[1])))
40server.listen(3)
41server.setblocking(0)
42
43clients = {}
44writers = {}
45
46def dropClient(cli, errors=None):
47 if errors:
Jim Shaver71ad3682015-04-29 00:09:14 -040048 print('Client %s left unexpectedly:' % (clients[cli],))
49 print(' ', errors)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050050 else:
Jim Shaver71ad3682015-04-29 00:09:14 -040051 print('Client %s left politely' % (clients[cli],))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050052 del clients[cli]
Jim Shaver71ad3682015-04-29 00:09:14 -040053 if cli in writers:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050054 del writers[cli]
55 if not errors:
56 cli.shutdown()
57 cli.close()
58
59while 1:
60 try:
Jim Shaverb2ff5be2015-04-30 08:26:29 -040061 r, w, _ = select.select([server] + list(clients.keys()), list(writers.keys()), [])
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050062 except:
63 break
64
65 for cli in r:
66 if cli == server:
67 cli,addr = server.accept()
Jim Shaver71ad3682015-04-29 00:09:14 -040068 print('Connection from %s' % (addr,))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050069 clients[cli] = addr
70
71 else:
72 try:
Jim Shaverb2ff5be2015-04-30 08:26:29 -040073 ret = cli.recv(1024).decode('utf-8')
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050074 except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError):
75 pass
76 except SSL.ZeroReturnError:
77 dropClient(cli)
Jim Shaver71ad3682015-04-29 00:09:14 -040078 except SSL.Error as errors:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050079 dropClient(cli, errors)
80 else:
Jim Shaver71ad3682015-04-29 00:09:14 -040081 if cli not in writers:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050082 writers[cli] = ''
83 writers[cli] = writers[cli] + ret
84
85 for cli in w:
86 try:
87 ret = cli.send(writers[cli])
88 except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError):
89 pass
90 except SSL.ZeroReturnError:
91 dropClient(cli)
Jim Shaver71ad3682015-04-29 00:09:14 -040092 except SSL.Error as errors:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050093 dropClient(cli, errors)
94 else:
95 writers[cli] = writers[cli][ret:]
96 if writers[cli] == '':
97 del writers[cli]
98
Jim Shaver473fe6a2015-04-29 09:42:39 -040099for cli in clients.keys():
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500100 cli.close()
101server.close()