blob: 19f6d214d948395b54548e32b6dc56e213d7df92 [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
70while 1:
71 try:
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010072 r, w, _ = select.select(
73 [server] + list(clients.keys()), list(writers.keys()), []
74 )
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050075 except:
76 break
77
78 for cli in r:
79 if cli == server:
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010080 cli, addr = server.accept()
Jim Shaver71ad3682015-04-29 00:09:14 -040081 print('Connection from %s' % (addr,))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050082 clients[cli] = addr
83
84 else:
85 try:
Jim Shaverb2ff5be2015-04-30 08:26:29 -040086 ret = cli.recv(1024).decode('utf-8')
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010087 except (SSL.WantReadError,
88 SSL.WantWriteError,
89 SSL.WantX509LookupError):
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050090 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:
Jim Shaver71ad3682015-04-29 00:09:14 -040096 if cli not in writers:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050097 writers[cli] = ''
98 writers[cli] = writers[cli] + ret
99
100 for cli in w:
101 try:
102 ret = cli.send(writers[cli])
Hynek Schlawack8b7e4552016-03-13 07:51:09 +0100103 except (SSL.WantReadError,
104 SSL.WantWriteError,
105 SSL.WantX509LookupError):
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500106 pass
107 except SSL.ZeroReturnError:
108 dropClient(cli)
Jim Shaver71ad3682015-04-29 00:09:14 -0400109 except SSL.Error as errors:
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500110 dropClient(cli, errors)
111 else:
112 writers[cli] = writers[cli][ret:]
113 if writers[cli] == '':
114 del writers[cli]
115
Jim Shaver473fe6a2015-04-29 09:42:39 -0400116for cli in clients.keys():
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500117 cli.close()
118server.close()