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.

177 lines
3.6 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // FILE
  4. //
  5. // ldapsrv.cpp
  6. //
  7. // SYNOPSIS
  8. //
  9. // Defines the clas LDAPServer.
  10. //
  11. // MODIFICATION HISTORY
  12. //
  13. // 05/07/1998 Original version.
  14. //
  15. ///////////////////////////////////////////////////////////////////////////////
  16. #include <ias.h>
  17. #include <iasutil.h>
  18. #include <ldapcxn.h>
  19. #include <ldapsrv.h>
  20. #include <new>
  21. //////////
  22. // Utility function for getting the current system time as a 64-bit integer.
  23. //////////
  24. inline DWORDLONG GetSystemTimeAsDWORDLONG() throw ()
  25. {
  26. ULARGE_INTEGER ft;
  27. GetSystemTimeAsFileTime((LPFILETIME)&ft);
  28. return ft.QuadPart;
  29. }
  30. //////////
  31. // Number of 100 nsec intervals in one second.
  32. //////////
  33. const DWORDLONG ONE_SECOND = 10000000ui64;
  34. //////////
  35. // Defaults for retry interval and idle timeout.
  36. //////////
  37. DWORDLONG LDAPServer::retryInterval = 1 * 60 * ONE_SECOND;
  38. DWORDLONG LDAPServer::idleTimeout = 30 * 60 * ONE_SECOND;
  39. void LDAPServer::Release() throw ()
  40. {
  41. if (!InterlockedDecrement(&refCount))
  42. {
  43. delete this;
  44. }
  45. }
  46. // Forces open a cached connection.
  47. void LDAPServer::forceOpen() throw ()
  48. {
  49. Lock();
  50. if (connection)
  51. {
  52. // Probe the exisiting connection.
  53. probe();
  54. }
  55. else
  56. {
  57. // No connection, so open a new one.
  58. open();
  59. }
  60. Unlock();
  61. }
  62. // Forces closed the cached connection. Note that we do not need to update
  63. // 'status'. Since we're setting expiry to zero, the next call to
  64. // getConnection will always force an open which will in turn set the status.
  65. void LDAPServer::forceClosed() throw ()
  66. {
  67. Lock();
  68. if (connection)
  69. {
  70. // Release the current connection.
  71. connection->Release();
  72. connection = NULL;
  73. // Allow immediate retry.
  74. expiry = 0;
  75. }
  76. Unlock();
  77. }
  78. DWORD LDAPServer::getConnection(LDAPConnection** cxn) throw ()
  79. {
  80. Lock();
  81. if (connection)
  82. {
  83. // Probe the exisiting connection.
  84. probe();
  85. }
  86. else if (expiry <= GetSystemTimeAsDWORDLONG())
  87. {
  88. // We don't have a connection, but we've reached the retry interval.
  89. open();
  90. }
  91. *cxn = connection;
  92. if (*cxn)
  93. {
  94. // We have a good connection to return to the caller, so addref ...
  95. (*cxn)->AddRef();
  96. // ... and bump the expiration time for this server.
  97. expiry = GetSystemTimeAsDWORDLONG() + idleTimeout;
  98. }
  99. // Return the result of our last open attempt.
  100. DWORD retval = status;
  101. Unlock();
  102. return retval;
  103. }
  104. LDAPServer* LDAPServer::createInstance(PCWSTR host) throw ()
  105. {
  106. // We copy the hostname here, so that we don't have to throw an
  107. // exception from the constructor.
  108. PWSTR hostCopy = ias_wcsdup(host);
  109. if (!hostCopy) { return NULL; }
  110. return new (std::nothrow) LDAPServer(hostCopy);
  111. }
  112. LDAPServer::LDAPServer(PWSTR host) throw ()
  113. : refCount(1),
  114. hostname(host),
  115. connection(NULL),
  116. status(ERROR_INVALID_HANDLE),
  117. expiry(0)
  118. {
  119. open();
  120. }
  121. LDAPServer::~LDAPServer() throw ()
  122. {
  123. if (connection) { connection->Release(); }
  124. delete[] hostname;
  125. }
  126. void LDAPServer::open() throw ()
  127. {
  128. // Try to create a new connection to the server.
  129. status = LDAPConnection::createInstance(hostname, &connection);
  130. expiry = GetSystemTimeAsDWORDLONG();
  131. // Adjust the expiry based on the result of the open attempt.
  132. expiry += (status == NO_ERROR) ? idleTimeout : retryInterval;
  133. }
  134. void LDAPServer::probe() throw ()
  135. {
  136. if (connection->isDisabled())
  137. {
  138. // If our current connection is disabled, then release it ...
  139. connection->Release();
  140. connection = NULL;
  141. // ... and try again.
  142. open();
  143. }
  144. }