Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / tlslite / tlslite / sessioncache.py
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()