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