tlslite.sessioncache

Package tlslite :: Module sessioncache |
[hide private]
[frames] | no frames]

# Source Code for Module tlslite.sessioncache

      1  # Author: Trevor Perrin
      2  # See the LICENSE file for legal information regarding use of this file.
      3
      4  """Class for caching TLS sessions."""
      5
      6  import thread
      7  import time
      8
      9 -class SessionCache:
     10      """This class is used by the server to cache TLS sessions.
     11
     12      Caching sessions allows the client to use TLS session resumption
     13      and avoid the expense of a full handshake.  To use this class,
     14      simply pass a SessionCache instance into the server handshake
     15      function.
     16
     17      This class is thread-safe.
     18      """
     19
     20      #References to these instances
     21      #are also held by the caller, who may change the 'resumable'
     22      #flag, so the SessionCache must return the same instances
     23      #it was passed in.
     24
     25 -    def __init__(self, maxEntries=10000, maxAge=14400):
     26          """Create a new SessionCache.
     27
     28          @type maxEntries: int
     29          @param maxEntries: The maximum size of the cache.  When this
     30          limit is reached, the oldest sessions will be deleted as
     31          necessary to make room for new ones.  The default is 10000.
     32
     33          @type maxAge: int
     34          @param maxAge:  The number of seconds before a session expires
     35          from the cache.  The default is 14400 (i.e. 4 hours)."""
     36
     37          self.lock = thread.allocate_lock()
     38
     39          # Maps sessionIDs to sessions
     40          self.entriesDict = {}
     41
     42          #Circular list of (sessionID, timestamp) pairs
     43          self.entriesList = [(None,None)] * maxEntries
     44
     45          self.firstIndex = 0
     46          self.lastIndex = 0
     47          self.maxAge = maxAge
     48
     49 -    def __getitem__(self, sessionID):
     50          self.lock.acquire()
     51          try:
     52              self._purge() #Delete old items, so we're assured of a new one
     53              session = self.entriesDict[sessionID]
     54
     55              #When we add sessions they're resumable, but it's possible
     56              #for the session to be invalidated later on (if a fatal alert
     57              #is returned), so we have to check for resumability before
     58              #returning the session.
     59
     60              if session.valid():
     61                  return session
     62              else:
     63                  raise KeyError()
     64          finally:
     65              self.lock.release()
     66
     67
     68 -    def __setitem__(self, sessionID, session):
     69          self.lock.acquire()
     70          try:
     71              #Add the new element
     72              self.entriesDict[sessionID] = session
     73              self.entriesList[self.lastIndex] = (sessionID, time.time())
     74              self.lastIndex = (self.lastIndex+1) % len(self.entriesList)
     75
     76              #If the cache is full, we delete the oldest element to make an
     77              #empty space
     78              if self.lastIndex == self.firstIndex:
     79                  del(self.entriesDict[self.entriesList[self.firstIndex][0]])
     80                  self.firstIndex = (self.firstIndex+1) % len(self.entriesList)
     81          finally:
     82              self.lock.release()
     83
     84      #Delete expired items
     85 -    def _purge(self):
     86          currentTime = time.time()
     87
     88          #Search through the circular list, deleting expired elements until
     89          #we reach a non-expired element.  Since elements in list are
     90          #ordered in time, we can break once we reach the first non-expired
     91          #element
     92          index = self.firstIndex
     93          while index != self.lastIndex:
     94              if currentTime - self.entriesList[index][1] > self.maxAge:
     95                  del(self.entriesDict[self.entriesList[index][0]])
     96                  index = (index+1) % len(self.entriesList)
     97              else:
     98                  break
     99          self.firstIndex = index
    100
    101 -def _test():
    102      import doctest, SessionCache
    103      return doctest.testmod(SessionCache)
    104
    105  if __name__ == "__main__":
    106      _test()
    107