Leaked source code of windows server 2003
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.

152 lines
3.5 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. try
  79. {
  80. // We can use multi_insert since the session ID is guaranteed to be unique.
  81. byID.multi_insert(SessionTable::value_type(session, byExpiry.begin()));
  82. }
  83. catch (const std::bad_alloc&)
  84. {
  85. byExpiry.pop_front();
  86. throw;
  87. }
  88. }
  89. EAPSession* EAPSessionTable::remove(DWORD key) throw ()
  90. {
  91. _serialize
  92. // First evict all expired sessions since the requested session may have
  93. // expired.
  94. evict(getCurrentTime());
  95. const SessionEntry* entry = byID.find(key);
  96. if (entry)
  97. {
  98. // Save the session pointer we're going to return.
  99. EAPSession* session = entry->first;
  100. // Erase from the expiry list ...
  101. byExpiry.erase(entry->second);
  102. // ... and the session table.
  103. byID.erase(key);
  104. return session;
  105. }
  106. // Not found, so return NULL.
  107. return NULL;
  108. }
  109. void EAPSessionTable::evict(DWORDLONG now) throw ()
  110. {
  111. // Loop until the list is empty or the oldest session hasn't expired.
  112. while (!byExpiry.empty() && byExpiry.back().first <= now)
  113. {
  114. evictOldest();
  115. }
  116. }
  117. void EAPSessionTable::evictOldest() throw ()
  118. {
  119. // We have an expired session, so erase it from the table.
  120. byID.erase(byExpiry.back().second->getID());
  121. // Clean up the session object.
  122. delete byExpiry.back().second;
  123. // Remove from the list.
  124. byExpiry.pop_back();
  125. }