Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.2 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // FILE
  4. //
  5. // EAPSessionTable.cpp
  6. //
  7. // SYNOPSIS
  8. //
  9. // This file defines the class EAPSessionTable.
  10. //
  11. // MODIFICATION HISTORY
  12. //
  13. // 04/28/1998 Original version.
  14. //
  15. ///////////////////////////////////////////////////////////////////////////////
  16. #include <ias.h>
  17. #include <eapsessiontable.h>
  18. //////////
  19. // Get the system time as a 64-bit integer.
  20. //////////
  21. inline DWORDLONG getCurrentTime() throw ()
  22. {
  23. ULARGE_INTEGER ft;
  24. GetSystemTimeAsFileTime((LPFILETIME)&ft);
  25. return ft.QuadPart;
  26. }
  27. // Session timeout defaults to 2 minutes.
  28. // Max. sessions defaults to 4096.
  29. EAPSessionTable::EAPSessionTable()
  30. : byID(0x400),
  31. sessionTimeout(1200000000ui64),
  32. maxSessions(0x1000)
  33. { }
  34. EAPSessionTable::~EAPSessionTable()
  35. {
  36. clear();
  37. }
  38. //////////
  39. // Externally the session timeout is expressed in milliseconds, but internally
  40. // we store it in 100 nsec intervals to facilitate working with FILETIME.
  41. //////////
  42. DWORD EAPSessionTable::getSessionTimeout() const throw ()
  43. {
  44. return (DWORD)(sessionTimeout / 10000);
  45. }
  46. void EAPSessionTable::setSessionTimeout(DWORD newVal) throw ()
  47. {
  48. sessionTimeout = 10000 * (DWORDLONG)newVal;
  49. }
  50. void EAPSessionTable::clear() throw ()
  51. {
  52. _serialize
  53. // Delete all the sessions.
  54. for (SessionTable::iterator i = byID.begin(); i.more(); ++i)
  55. {
  56. delete i->first;
  57. }
  58. // Clear the collections.
  59. byID.clear();
  60. byExpiry.clear();
  61. }
  62. void EAPSessionTable::insert(EAPSession* session)
  63. {
  64. _serialize
  65. // Make room for the new session.
  66. while (byExpiry.size() >= maxSessions)
  67. {
  68. evictOldest();
  69. }
  70. // Evict all expired sessions. We do this before the insert to avoid
  71. // unnecessary resizing of the session table.
  72. DWORDLONG now = getCurrentTime();
  73. evict(now);
  74. // Compute the expiry of this session.
  75. now += sessionTimeout;
  76. // It must be the most recent, so insert it at the front of the list.
  77. byExpiry.push_front(SessionList::value_type(now, session));
  78. // We can use multi_insert since the session ID is guaranteed to be unique.
  79. byID.multi_insert(SessionTable::value_type(session, byExpiry.begin()));
  80. }
  81. EAPSession* EAPSessionTable::remove(DWORD key) throw ()
  82. {
  83. _serialize
  84. // First evict all expired sessions since the requested session may have
  85. // expired.
  86. evict(getCurrentTime());
  87. const SessionEntry* entry = byID.find(key);
  88. if (entry)
  89. {
  90. // Save the session pointer we're going to return.
  91. EAPSession* session = entry->first;
  92. // Erase from the expiry list ...
  93. byExpiry.erase(entry->second);
  94. // ... and the session table.
  95. byID.erase(key);
  96. return session;
  97. }
  98. // Not found, so return NULL.
  99. return NULL;
  100. }
  101. void EAPSessionTable::evict(DWORDLONG now) throw ()
  102. {
  103. // Loop until the list is empty or the oldest session hasn't expired.
  104. while (!byExpiry.empty() && byExpiry.back().first <= now)
  105. {
  106. evictOldest();
  107. }
  108. }
  109. void EAPSessionTable::evictOldest() throw ()
  110. {
  111. // We have an expired session, so erase it from the table.
  112. byID.erase(byExpiry.back().second->getID());
  113. // Clean up the session object.
  114. delete byExpiry.back().second;
  115. // Remove from the list.
  116. byExpiry.pop_back();
  117. }