blob: 9cce9e006a229efa0bcf7f1abcbc99102745e702 [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
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010011from __future__ import print_function
12
13import os
14import select
15import socket
16import sys
17
Jim Shaverb2ff5be2015-04-30 08:26:29 -040018from OpenSSL import SSL, crypto
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050019
20
21def verify_cb(conn, cert, errnum, depth, ok):
Jim Shaverb2ff5be2015-04-30 08:26:29 -040022 certsubject = crypto.X509Name(cert.get_subject())
23 commonname = certsubject.commonName
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010024 print('Got certificate: ' + commonname)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050025 return ok
26
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010027
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050028if len(sys.argv) < 2:
Jim Shaver8a4a7ae2015-04-29 01:17:33 -040029 print('Usage: python server.py PORT')
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050030 sys.exit(1)
31
32dir = os.path.dirname(sys.argv[0])
33if dir == '':
34 dir = os.curdir
35
36# Initialize context
37ctx = SSL.Context(SSL.SSLv23_METHOD)
38ctx.set_options(SSL.OP_NO_SSLv2)
Daniƫl van Eedenae8243d2016-01-16 18:00:52 +010039ctx.set_options(SSL.OP_NO_SSLv3)
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010040ctx.set_verify(
41 SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
42) # Demand a certificate
43ctx.use_privatekey_file(os.path.join(dir, 'server.pkey'))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050044ctx.use_certificate_file(os.path.join(dir, 'server.cert'))
45ctx.load_verify_locations(os.path.join(dir, 'CA.cert'))
46
47# Set up server
48server = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
49server.bind(('', int(sys.argv[1])))
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010050server.listen(3)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050051server.setblocking(0)
52
53clients = {}
54writers = {}
55
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010056
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050057def dropClient(cli, errors=None):
58 if errors:
Jim Shaver71ad3682015-04-29 00:09:14 -040059 print('Client %s left unexpectedly:' % (clients[cli],))
60 print(' ', errors)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050061 else:
Jim Shaver71ad3682015-04-29 00:09:14 -040062 print('Client %s left politely' % (clients[cli],))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050063 del clients[cli]
Jim Shaver71ad3682015-04-29 00:09:14 -040064 if cli in writers:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050065 del writers[cli]
66 if not errors:
67 cli.shutdown()
68 cli.close()
69
Alex Chanc6077062016-11-18 13:53:39 +000070
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050071while 1:
72 try:
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010073 r, w, _ = select.select(
74 [server] + list(clients.keys()), list(writers.keys()), []
75 )
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050076 except:
77 break
78
79 for cli in r:
80 if cli == server:
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010081 cli, addr = server.accept()
Jim Shaver71ad3682015-04-29 00:09:14 -040082 print('Connection from %s' % (addr,))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050083 clients[cli] = addr
84
85 else:
86 try:
Jim Shaverb2ff5be2015-04-30 08:26:29 -040087 ret = cli.recv(1024).decode('utf-8')
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010088 except (SSL.WantReadError,
89 SSL.WantWriteError,
90 SSL.WantX509LookupError):
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050091 pass
92 except SSL.ZeroReturnError:
93 dropClient(cli)
Jim Shaver71ad3682015-04-29 00:09:14 -040094 except SSL.Error as errors:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050095 dropClient(cli, errors)
96 else:
Jim Shaver71ad3682015-04-29 00:09:14 -040097 if cli not in writers:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050098 writers[cli] = ''
99 writers[cli] = writers[cli] + ret
100
101 for cli in w:
102 try:
103 ret = cli.send(writers[cli])
Hynek Schlawack8b7e4552016-03-13 07:51:09 +0100104 except (SSL.WantReadError,
105 SSL.WantWriteError,
106 SSL.WantX509LookupError):
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500107 pass
108 except SSL.ZeroReturnError:
109 dropClient(cli)
Jim Shaver71ad3682015-04-29 00:09:14 -0400110 except SSL.Error as errors:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500111 dropClient(cli, errors)
112 else:
113 writers[cli] = writers[cli][ret:]
114 if writers[cli] == '':
115 del writers[cli]
116
Jim Shaver473fe6a2015-04-29 09:42:39 -0400117for cli in clients.keys():
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500118 cli.close()
119server.close()