1 from OpenSSL import SSL as orig_SSL
2 from OpenSSL.SSL import *
3 from eventlet.support import get_errno
4 from eventlet import greenio
5 from eventlet.hubs import trampoline
9 class GreenConnection(greenio.GreenSocket):
10 """ Nonblocking wrapper for SSL.Connection objects.
13 def __init__(self, ctx, sock=None):
15 fd = orig_SSL.Connection(ctx, sock)
17 # if we're given a Connection object directly, use it;
18 # this is used in the inherited accept() method
20 super(ConnectionType, self).__init__(fd)
22 def do_handshake(self):
23 """ Perform an SSL handshake (usually called after renegotiate or one of
24 set_accept_state or set_accept_state). This can raise the same exceptions as
26 if self.act_non_blocking:
27 return self.fd.do_handshake()
30 return self.fd.do_handshake()
32 trampoline(self.fd.fileno(),
34 timeout=self.gettimeout(),
35 timeout_exc=socket.timeout)
36 except WantWriteError:
37 trampoline(self.fd.fileno(),
39 timeout=self.gettimeout(),
40 timeout_exc=socket.timeout)
43 raise NotImplementedError("Dup not supported on SSL sockets")
45 def makefile(self, mode='r', bufsize=-1):
46 raise NotImplementedError("Makefile not supported on SSL sockets")
49 """Works like a blocking call to SSL_read(), whose behavior is
50 described here: http://www.openssl.org/docs/ssl/SSL_read.html"""
51 if self.act_non_blocking:
52 return self.fd.read(size)
55 return self.fd.read(size)
57 trampoline(self.fd.fileno(),
59 timeout=self.gettimeout(),
60 timeout_exc=socket.timeout)
61 except WantWriteError:
62 trampoline(self.fd.fileno(),
64 timeout=self.gettimeout(),
65 timeout_exc=socket.timeout)
66 except SysCallError as e:
67 if get_errno(e) == -1 or get_errno(e) > 0:
72 def write(self, data):
73 """Works like a blocking call to SSL_write(), whose behavior is
74 described here: http://www.openssl.org/docs/ssl/SSL_write.html"""
76 return 0 # calling SSL_write() with 0 bytes to be sent is undefined
77 if self.act_non_blocking:
78 return self.fd.write(data)
81 return self.fd.write(data)
83 trampoline(self.fd.fileno(),
85 timeout=self.gettimeout(),
86 timeout_exc=socket.timeout)
87 except WantWriteError:
88 trampoline(self.fd.fileno(),
90 timeout=self.gettimeout(),
91 timeout_exc=socket.timeout)
95 def sendall(self, data):
96 """Send "all" data on the connection. This calls send() repeatedly until
97 all data is sent. If an error occurs, it's impossible to tell how much data
101 tail = self.send(data)
102 while tail < len(data):
103 tail += self.send(data[tail:])
106 if self.act_non_blocking:
107 return self.fd.shutdown()
110 return self.fd.shutdown()
111 except WantReadError:
112 trampoline(self.fd.fileno(),
114 timeout=self.gettimeout(),
115 timeout_exc=socket.timeout)
116 except WantWriteError:
117 trampoline(self.fd.fileno(),
119 timeout=self.gettimeout(),
120 timeout_exc=socket.timeout)
122 Connection = ConnectionType = GreenConnection