Add python-eventlet 0.16.1
[packages/trusty/python-eventlet.git] / eventlet / eventlet / green / OpenSSL / SSL.py
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
6 import socket
7
8
9 class GreenConnection(greenio.GreenSocket):
10     """ Nonblocking wrapper for SSL.Connection objects.
11     """
12
13     def __init__(self, ctx, sock=None):
14         if sock is not None:
15             fd = orig_SSL.Connection(ctx, sock)
16         else:
17             # if we're given a Connection object directly, use it;
18             # this is used in the inherited accept() method
19             fd = ctx
20         super(ConnectionType, self).__init__(fd)
21
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
25         send and recv. """
26         if self.act_non_blocking:
27             return self.fd.do_handshake()
28         while True:
29             try:
30                 return self.fd.do_handshake()
31             except WantReadError:
32                 trampoline(self.fd.fileno(),
33                            read=True,
34                            timeout=self.gettimeout(),
35                            timeout_exc=socket.timeout)
36             except WantWriteError:
37                 trampoline(self.fd.fileno(),
38                            write=True,
39                            timeout=self.gettimeout(),
40                            timeout_exc=socket.timeout)
41
42     def dup(self):
43         raise NotImplementedError("Dup not supported on SSL sockets")
44
45     def makefile(self, mode='r', bufsize=-1):
46         raise NotImplementedError("Makefile not supported on SSL sockets")
47
48     def read(self, size):
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)
53         while True:
54             try:
55                 return self.fd.read(size)
56             except WantReadError:
57                 trampoline(self.fd.fileno(),
58                            read=True,
59                            timeout=self.gettimeout(),
60                            timeout_exc=socket.timeout)
61             except WantWriteError:
62                 trampoline(self.fd.fileno(),
63                            write=True,
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:
68                     return ''
69
70     recv = read
71
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"""
75         if not data:
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)
79         while True:
80             try:
81                 return self.fd.write(data)
82             except WantReadError:
83                 trampoline(self.fd.fileno(),
84                            read=True,
85                            timeout=self.gettimeout(),
86                            timeout_exc=socket.timeout)
87             except WantWriteError:
88                 trampoline(self.fd.fileno(),
89                            write=True,
90                            timeout=self.gettimeout(),
91                            timeout_exc=socket.timeout)
92
93     send = write
94
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
98         has been sent.
99
100         No return value."""
101         tail = self.send(data)
102         while tail < len(data):
103             tail += self.send(data[tail:])
104
105     def shutdown(self):
106         if self.act_non_blocking:
107             return self.fd.shutdown()
108         while True:
109             try:
110                 return self.fd.shutdown()
111             except WantReadError:
112                 trampoline(self.fd.fileno(),
113                            read=True,
114                            timeout=self.gettimeout(),
115                            timeout_exc=socket.timeout)
116             except WantWriteError:
117                 trampoline(self.fd.fileno(),
118                            write=True,
119                            timeout=self.gettimeout(),
120                            timeout_exc=socket.timeout)
121
122 Connection = ConnectionType = GreenConnection
123
124 del greenio