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

# Source Code for Module tlslite.sessioncache

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