1 """Class for caching TLS sessions."""
7 """This class is used by the server to cache TLS sessions.
9 Caching sessions allows the client to use TLS session resumption
10 and avoid the expense of a full handshake. To use this class,
11 simply pass a SessionCache instance into the server handshake
14 This class is thread-safe.
17 #References to these instances
18 #are also held by the caller, who may change the 'resumable'
19 #flag, so the SessionCache must return the same instances
22 def __init__(self, maxEntries=10000, maxAge=14400):
23 """Create a new SessionCache.
26 @param maxEntries: The maximum size of the cache. When this
27 limit is reached, the oldest sessions will be deleted as
28 necessary to make room for new ones. The default is 10000.
31 @param maxAge: The number of seconds before a session expires
32 from the cache. The default is 14400 (i.e. 4 hours)."""
34 self.lock = thread.allocate_lock()
36 # Maps sessionIDs to sessions
39 #Circular list of (sessionID, timestamp) pairs
40 self.entriesList = [(None,None)] * maxEntries
46 def __getitem__(self, sessionID):
49 self._purge() #Delete old items, so we're assured of a new one
50 session = self.entriesDict[sessionID]
52 #When we add sessions they're resumable, but it's possible
53 #for the session to be invalidated later on (if a fatal alert
54 #is returned), so we have to check for resumability before
55 #returning the session.
65 def __setitem__(self, sessionID, session):
69 self.entriesDict[sessionID] = session
70 self.entriesList[self.lastIndex] = (sessionID, time.time())
71 self.lastIndex = (self.lastIndex+1) % len(self.entriesList)
73 #If the cache is full, we delete the oldest element to make an
75 if self.lastIndex == self.firstIndex:
76 del(self.entriesDict[self.entriesList[self.firstIndex][0]])
77 self.firstIndex = (self.firstIndex+1) % len(self.entriesList)
83 currentTime = time.time()
85 #Search through the circular list, deleting expired elements until
86 #we reach a non-expired element. Since elements in list are
87 #ordered in time, we can break once we reach the first non-expired
89 index = self.firstIndex
90 while index != self.lastIndex:
91 if currentTime - self.entriesList[index][1] > self.maxAge:
92 del(self.entriesDict[self.entriesList[index][0]])
93 index = (index+1) % len(self.entriesList)
96 self.firstIndex = index
99 import doctest, SessionCache
100 return doctest.testmod(SessionCache)
102 if __name__ == "__main__":