blob: f07cfc209dcc92609ed29ff079ebef19e0e9854f [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):
16 # This obviously has to be updated
Jim Shaverb2ff5be2015-04-30 08:26:29 -040017 certsubject = crypto.X509Name(cert.get_subject())
18 commonname = certsubject.commonName
19 print(('Got certificate: ' + commonname))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050020 return ok
21
22if len(sys.argv) < 2:
Jim Shaver8a4a7ae2015-04-29 01:17:33 -040023 print('Usage: python server.py PORT')
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050024 sys.exit(1)
25
26dir = os.path.dirname(sys.argv[0])
27if dir == '':
28 dir = os.curdir
29
30# Initialize context
31ctx = SSL.Context(SSL.SSLv23_METHOD)
32ctx.set_options(SSL.OP_NO_SSLv2)
33ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb) # Demand a certificate
34ctx.use_privatekey_file (os.path.join(dir, 'server.pkey'))
35ctx.use_certificate_file(os.path.join(dir, 'server.cert'))
36ctx.load_verify_locations(os.path.join(dir, 'CA.cert'))
37
38# Set up server
39server = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
40server.bind(('', int(sys.argv[1])))
41server.listen(3)
42server.setblocking(0)
43
44clients = {}
45writers = {}
46
47def dropClient(cli, errors=None):
48 if errors:
Jim Shaver71ad3682015-04-29 00:09:14 -040049 print('Client %s left unexpectedly:' % (clients[cli],))
50 print(' ', errors)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050051 else:
Jim Shaver71ad3682015-04-29 00:09:14 -040052 print('Client %s left politely' % (clients[cli],))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050053 del clients[cli]
Jim Shaver71ad3682015-04-29 00:09:14 -040054 if cli in writers:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050055 del writers[cli]
56 if not errors:
57 cli.shutdown()
58 cli.close()
59
60while 1:
61 try:
Jim Shaverb2ff5be2015-04-30 08:26:29 -040062 r, w, _ = select.select([server] + list(clients.keys()), list(writers.keys()), [])
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050063 except:
64 break
65
66 for cli in r:
67 if cli == server:
68 cli,addr = server.accept()
Jim Shaver71ad3682015-04-29 00:09:14 -040069 print('Connection from %s' % (addr,))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050070 clients[cli] = addr
71
72 else:
73 try:
Jim Shaverb2ff5be2015-04-30 08:26:29 -040074 ret = cli.recv(1024).decode('utf-8')
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050075 except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError):
76 pass
77 except SSL.ZeroReturnError:
78 dropClient(cli)
Jim Shaver71ad3682015-04-29 00:09:14 -040079 except SSL.Error as errors:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050080 dropClient(cli, errors)
81 else:
Jim Shaver71ad3682015-04-29 00:09:14 -040082 if cli not in writers:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050083 writers[cli] = ''
84 writers[cli] = writers[cli] + ret
85
86 for cli in w:
87 try:
88 ret = cli.send(writers[cli])
89 except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError):
90 pass
91 except SSL.ZeroReturnError:
92 dropClient(cli)
Jim Shaver71ad3682015-04-29 00:09:14 -040093 except SSL.Error as errors:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050094 dropClient(cli, errors)
95 else:
96 writers[cli] = writers[cli][ret:]
97 if writers[cli] == '':
98 del writers[cli]
99
Jim Shaver473fe6a2015-04-29 09:42:39 -0400100for cli in clients.keys():
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500101 cli.close()
102server.close()