blob: 37e36ddfc63cf19c2681e3bf4e21c44f201ddd10 [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
11from OpenSSL import SSL
12import sys, os, select, socket
13
14
15def verify_cb(conn, cert, errnum, depth, ok):
16 # This obviously has to be updated
17 print 'Got certificate: %s' % cert.get_subject()
18 return ok
19
20if len(sys.argv) < 2:
21 print 'Usage: python[2] server.py PORT'
22 sys.exit(1)
23
24dir = os.path.dirname(sys.argv[0])
25if dir == '':
26 dir = os.curdir
27
28# Initialize context
29ctx = SSL.Context(SSL.SSLv23_METHOD)
30ctx.set_options(SSL.OP_NO_SSLv2)
31ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb) # Demand a certificate
32ctx.use_privatekey_file (os.path.join(dir, 'server.pkey'))
33ctx.use_certificate_file(os.path.join(dir, 'server.cert'))
34ctx.load_verify_locations(os.path.join(dir, 'CA.cert'))
35
36# Set up server
37server = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
38server.bind(('', int(sys.argv[1])))
39server.listen(3)
40server.setblocking(0)
41
42clients = {}
43writers = {}
44
45def dropClient(cli, errors=None):
46 if errors:
47 print 'Client %s left unexpectedly:' % (clients[cli],)
48 print ' ', errors
49 else:
50 print 'Client %s left politely' % (clients[cli],)
51 del clients[cli]
52 if writers.has_key(cli):
53 del writers[cli]
54 if not errors:
55 cli.shutdown()
56 cli.close()
57
58while 1:
59 try:
60 r,w,_ = select.select([server]+clients.keys(), writers.keys(), [])
61 except:
62 break
63
64 for cli in r:
65 if cli == server:
66 cli,addr = server.accept()
67 print 'Connection from %s' % (addr,)
68 clients[cli] = addr
69
70 else:
71 try:
72 ret = cli.recv(1024)
73 except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError):
74 pass
75 except SSL.ZeroReturnError:
76 dropClient(cli)
77 except SSL.Error, errors:
78 dropClient(cli, errors)
79 else:
80 if not writers.has_key(cli):
81 writers[cli] = ''
82 writers[cli] = writers[cli] + ret
83
84 for cli in w:
85 try:
86 ret = cli.send(writers[cli])
87 except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError):
88 pass
89 except SSL.ZeroReturnError:
90 dropClient(cli)
91 except SSL.Error, errors:
92 dropClient(cli, errors)
93 else:
94 writers[cli] = writers[cli][ret:]
95 if writers[cli] == '':
96 del writers[cli]
97
98for cli in clients.keys():
99 cli.close()
100server.close()