2 A state machine for using TLS Lite with asynchronous I/O.
5 class AsyncStateMachine:
7 This is an abstract class that's used to integrate TLS Lite with
10 This class signals wantsReadsEvent() and wantsWriteEvent(). When
11 the underlying socket has become readable or writeable, the event
12 should be passed to this class by calling inReadEvent() or
13 inWriteEvent(). This class will then try to read or write through
14 the socket, and will update its state appropriately.
16 This class will forward higher-level events to its subclass. For
17 example, when a complete TLS record has been received,
18 outReadEvent() will be called with the decrypted data.
25 #These store the various asynchronous operations (i.e.
26 #generators). Only one of them, at most, is ever active at a
28 self.handshaker = None
33 #This stores the result from the last call to the
34 #currently active operation. If 0 it indicates that the
35 #operation wants to read, if 1 it indicates that the
36 #operation wants to write. If None, there is no active
40 def _checkAssert(self, maxActive=1):
41 #This checks that only one operation, at most, is
42 #active, and that self.result is set appropriately.
53 if self.result == None:
55 raise AssertionError()
56 elif self.result in (0,1):
58 raise AssertionError()
60 raise AssertionError()
61 if activeOps > maxActive:
62 raise AssertionError()
64 def wantsReadEvent(self):
65 """If the state machine wants to read.
67 If an operation is active, this returns whether or not the
68 operation wants to read from the socket. If an operation is
69 not active, this returns None.
72 @return: If the state machine wants to read.
74 if self.result != None:
75 return self.result == 0
78 def wantsWriteEvent(self):
79 """If the state machine wants to write.
81 If an operation is active, this returns whether or not the
82 operation wants to write to the socket. If an operation is
83 not active, this returns None.
86 @return: If the state machine wants to write.
88 if self.result != None:
89 return self.result == 1
92 def outConnectEvent(self):
93 """Called when a handshake operation completes.
95 May be overridden in subclass.
99 def outCloseEvent(self):
100 """Called when a close operation completes.
102 May be overridden in subclass.
106 def outReadEvent(self, readBuffer):
107 """Called when a read operation completes.
109 May be overridden in subclass."""
112 def outWriteEvent(self):
113 """Called when a write operation completes.
115 May be overridden in subclass."""
118 def inReadEvent(self):
119 """Tell the state machine it can read from the socket."""
123 self._doHandshakeOp()
131 self.reader = self.tlsConnection.readAsync(16384)
137 def inWriteEvent(self):
138 """Tell the state machine it can write to the socket."""
142 self._doHandshakeOp()
155 def _doHandshakeOp(self):
157 self.result = self.handshaker.next()
158 except StopIteration:
159 self.handshaker = None
161 self.outConnectEvent()
163 def _doCloseOp(self):
165 self.result = self.closer.next()
166 except StopIteration:
172 self.result = self.reader.next()
173 if not self.result in (0,1):
174 readBuffer = self.result
177 self.outReadEvent(readBuffer)
179 def _doWriteOp(self):
181 self.result = self.writer.next()
182 except StopIteration:
186 def setHandshakeOp(self, handshaker):
187 """Start a handshake operation.
189 @type handshaker: generator
190 @param handshaker: A generator created by using one of the
191 asynchronous handshake functions (i.e. handshakeServerAsync, or
192 handshakeClientxxx(..., async=True).
196 self.handshaker = handshaker
197 self._doHandshakeOp()
202 def setServerHandshakeOp(self, **args):
203 """Start a handshake operation.
205 The arguments passed to this function will be forwarded to
206 L{tlslite.TLSConnection.TLSConnection.handshakeServerAsync}.
208 handshaker = self.tlsConnection.handshakeServerAsync(**args)
209 self.setHandshakeOp(handshaker)
211 def setCloseOp(self):
212 """Start a close operation.
216 self.closer = self.tlsConnection.closeAsync()
222 def setWriteOp(self, writeBuffer):
223 """Start a write operation.
225 @type writeBuffer: str
226 @param writeBuffer: The string to transmit.
230 self.writer = self.tlsConnection.writeAsync(writeBuffer)