Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / third_party / tlslite / tlslite / SessionCache.py
1 """Class for caching TLS sessions."""
2
3 import thread
4 import time
5
6 class SessionCache:
7     """This class is used by the server to cache TLS sessions.
8
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
12     function.
13
14     This class is thread-safe.
15     """
16
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
20     #it was passed in.
21
22     def __init__(self, maxEntries=10000, maxAge=14400):
23         """Create a new SessionCache.
24
25         @type maxEntries: int
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.
29
30         @type maxAge: int
31         @param maxAge:  The number of seconds before a session expires
32         from the cache.  The default is 14400 (i.e. 4 hours)."""
33
34         self.lock = thread.allocate_lock()
35
36         # Maps sessionIDs to sessions
37         self.entriesDict = {}
38
39         #Circular list of (sessionID, timestamp) pairs
40         self.entriesList = [(None,None)] * maxEntries
41
42         self.firstIndex = 0
43         self.lastIndex = 0
44         self.maxAge = maxAge
45
46     def __getitem__(self, sessionID):
47         self.lock.acquire()
48         try:
49             self._purge() #Delete old items, so we're assured of a new one
50             session = self.entriesDict[sessionID]
51
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.
56
57             if session.valid():
58                 return session
59             else:
60                 raise KeyError()
61         finally:
62             self.lock.release()
63
64
65     def __setitem__(self, sessionID, session):
66         self.lock.acquire()
67         try:
68             #Add the new element
69             self.entriesDict[sessionID] = session
70             self.entriesList[self.lastIndex] = (sessionID, time.time())
71             self.lastIndex = (self.lastIndex+1) % len(self.entriesList)
72
73             #If the cache is full, we delete the oldest element to make an
74             #empty space
75             if self.lastIndex == self.firstIndex:
76                 del(self.entriesDict[self.entriesList[self.firstIndex][0]])
77                 self.firstIndex = (self.firstIndex+1) % len(self.entriesList)
78         finally:
79             self.lock.release()
80
81     #Delete expired items
82     def _purge(self):
83         currentTime = time.time()
84
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
88         #element
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)
94             else:
95                 break
96         self.firstIndex = index
97
98 def _test():
99     import doctest, SessionCache
100     return doctest.testmod(SessionCache)
101
102 if __name__ == "__main__":
103     _test()