Package tlslite :: Package integration :: Module asyncstatemachine
[hide private]
[frames] | no frames]

Source Code for Module tlslite.integration.asyncstatemachine

  1  # Author: Trevor Perrin 
  2  # See the LICENSE file for legal information regarding use of this file. 
  3   
  4  """ 
  5  A state machine for using TLS Lite with asynchronous I/O. 
  6  """ 
  7   
8 -class AsyncStateMachine:
9 """ 10 This is an abstract class that's used to integrate TLS Lite with 11 asyncore and Twisted. 12 13 This class signals wantsReadsEvent() and wantsWriteEvent(). When 14 the underlying socket has become readable or writeable, the event 15 should be passed to this class by calling inReadEvent() or 16 inWriteEvent(). This class will then try to read or write through 17 the socket, and will update its state appropriately. 18 19 This class will forward higher-level events to its subclass. For 20 example, when a complete TLS record has been received, 21 outReadEvent() will be called with the decrypted data. 22 """ 23
24 - def __init__(self):
25 self.result = None 26 self.handshaker = None 27 self.closer = None 28 self.reader = None 29 self.writer = None 30 self._clear()
31
32 - def _clear(self):
33 #These store the various asynchronous operations (i.e. 34 #generators). Only one of them, at most, is ever active at a 35 #time. 36 self.handshaker = None 37 self.closer = None 38 self.reader = None 39 self.writer = None 40 41 #This stores the result from the last call to the 42 #currently active operation. If 0 it indicates that the 43 #operation wants to read, if 1 it indicates that the 44 #operation wants to write. If None, there is no active 45 #operation. 46 self.result = None
47
48 - def _checkAssert(self, maxActive=1):
49 #This checks that only one operation, at most, is 50 #active, and that self.result is set appropriately. 51 activeOps = 0 52 if self.handshaker: 53 activeOps += 1 54 if self.closer: 55 activeOps += 1 56 if self.reader: 57 activeOps += 1 58 if self.writer: 59 activeOps += 1 60 61 if self.result == None: 62 if activeOps != 0: 63 raise AssertionError() 64 elif self.result in (0,1): 65 if activeOps != 1: 66 raise AssertionError() 67 else: 68 raise AssertionError() 69 if activeOps > maxActive: 70 raise AssertionError()
71
72 - def wantsReadEvent(self):
73 """If the state machine wants to read. 74 75 If an operation is active, this returns whether or not the 76 operation wants to read from the socket. If an operation is 77 not active, this returns None. 78 79 @rtype: bool or None 80 @return: If the state machine wants to read. 81 """ 82 if self.result != None: 83 return self.result == 0 84 return None
85
86 - def wantsWriteEvent(self):
87 """If the state machine wants to write. 88 89 If an operation is active, this returns whether or not the 90 operation wants to write to the socket. If an operation is 91 not active, this returns None. 92 93 @rtype: bool or None 94 @return: If the state machine wants to write. 95 """ 96 if self.result != None: 97 return self.result == 1 98 return None
99
100 - def outConnectEvent(self):
101 """Called when a handshake operation completes. 102 103 May be overridden in subclass. 104 """ 105 pass
106
107 - def outCloseEvent(self):
108 """Called when a close operation completes. 109 110 May be overridden in subclass. 111 """ 112 pass
113
114 - def outReadEvent(self, readBuffer):
115 """Called when a read operation completes. 116 117 May be overridden in subclass.""" 118 pass
119
120 - def outWriteEvent(self):
121 """Called when a write operation completes. 122 123 May be overridden in subclass.""" 124 pass
125
126 - def inReadEvent(self):
127 """Tell the state machine it can read from the socket.""" 128 try: 129 self._checkAssert() 130 if self.handshaker: 131 self._doHandshakeOp() 132 elif self.closer: 133 self._doCloseOp() 134 elif self.reader: 135 self._doReadOp() 136 elif self.writer: 137 self._doWriteOp() 138 else: 139 self.reader = self.tlsConnection.readAsync(16384) 140 self._doReadOp() 141 except: 142 self._clear() 143 raise
144
145 - def inWriteEvent(self):
146 """Tell the state machine it can write to the socket.""" 147 try: 148 self._checkAssert() 149 if self.handshaker: 150 self._doHandshakeOp() 151 elif self.closer: 152 self._doCloseOp() 153 elif self.reader: 154 self._doReadOp() 155 elif self.writer: 156 self._doWriteOp() 157 else: 158 self.outWriteEvent() 159 except: 160 self._clear() 161 raise
162
163 - def _doHandshakeOp(self):
164 try: 165 self.result = next(self.handshaker) 166 except StopIteration: 167 self.handshaker = None 168 self.result = None 169 self.outConnectEvent()
170
171 - def _doCloseOp(self):
172 try: 173 self.result = next(self.closer) 174 except StopIteration: 175 self.closer = None 176 self.result = None 177 self.outCloseEvent()
178
179 - def _doReadOp(self):
180 self.result = next(self.reader) 181 if not self.result in (0,1): 182 readBuffer = self.result 183 self.reader = None 184 self.result = None 185 self.outReadEvent(readBuffer)
186
187 - def _doWriteOp(self):
188 try: 189 self.result = next(self.writer) 190 except StopIteration: 191 self.writer = None 192 self.result = None
193
194 - def setHandshakeOp(self, handshaker):
195 """Start a handshake operation. 196 197 @type handshaker: generator 198 @param handshaker: A generator created by using one of the 199 asynchronous handshake functions (i.e. handshakeServerAsync, or 200 handshakeClientxxx(..., async=True). 201 """ 202 try: 203 self._checkAssert(0) 204 self.handshaker = handshaker 205 self._doHandshakeOp() 206 except: 207 self._clear() 208 raise
209
210 - def setServerHandshakeOp(self, **args):
211 """Start a handshake operation. 212 213 The arguments passed to this function will be forwarded to 214 L{tlslite.tlsconnection.TLSConnection.handshakeServerAsync}. 215 """ 216 handshaker = self.tlsConnection.handshakeServerAsync(**args) 217 self.setHandshakeOp(handshaker)
218
219 - def setCloseOp(self):
220 """Start a close operation. 221 """ 222 try: 223 self._checkAssert(0) 224 self.closer = self.tlsConnection.closeAsync() 225 self._doCloseOp() 226 except: 227 self._clear() 228 raise
229
230 - def setWriteOp(self, writeBuffer):
231 """Start a write operation. 232 233 @type writeBuffer: str 234 @param writeBuffer: The string to transmit. 235 """ 236 try: 237 self._checkAssert(0) 238 self.writer = self.tlsConnection.writeAsync(writeBuffer) 239 self._doWriteOp() 240 except: 241 self._clear() 242 raise
243