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