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.

387 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name :
  4. w3conn.cxx
  5. Abstract:
  6. Http Connection management
  7. Author:
  8. Bilal Alam (balam) 6-Jan-2000
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. ULW3.DLL
  13. --*/
  14. #include "precomp.hxx"
  15. ALLOC_CACHE_HANDLER * W3_CONNECTION::sm_pachW3Connections;
  16. W3_CONNECTION_HASH * W3_CONNECTION::sm_pConnectionTable;
  17. W3_CONNECTION::W3_CONNECTION(
  18. HTTP_CONNECTION_ID connectionId
  19. )
  20. : _cRefs( 1 ),
  21. _pUserContext( NULL ),
  22. _fConnected( TRUE )
  23. {
  24. LK_RETCODE lkrc;
  25. _connId = connectionId;
  26. _dwSignature = W3_CONNECTION_SIGNATURE;
  27. ZeroMemory( _rgConnectionState, sizeof( _rgConnectionState ) );
  28. IF_DEBUG( CONN )
  29. {
  30. DBGPRINTF(( DBG_CONTEXT,
  31. "New W3_CONNECTION '%p' created\n",
  32. this ));
  33. }
  34. }
  35. W3_CONNECTION::~W3_CONNECTION()
  36. {
  37. IF_DEBUG( CONN )
  38. {
  39. DBGPRINTF(( DBG_CONTEXT,
  40. "W3_CONNECTION '%p' deleted\n",
  41. this ));
  42. }
  43. //
  44. // Cleanup state associated with connection
  45. //
  46. for ( DWORD i = 0; i < STATE_COUNT; i++ )
  47. {
  48. if ( _rgConnectionState[ i ] != NULL )
  49. {
  50. _rgConnectionState[ i ]->Cleanup();
  51. _rgConnectionState[ i ] = NULL;
  52. }
  53. }
  54. //
  55. // Release the user context associated
  56. //
  57. if ( _pUserContext != NULL )
  58. {
  59. _pUserContext->DereferenceUserContext();
  60. _pUserContext = NULL;
  61. }
  62. _dwSignature = W3_CONNECTION_SIGNATURE_FREE;
  63. }
  64. HRESULT
  65. W3_CONNECTION::Initialize(
  66. VOID
  67. )
  68. /*++
  69. Routine Description:
  70. Global W3_CONNECTION initialization
  71. Arguments:
  72. None
  73. Return Value:
  74. HRESULT
  75. --*/
  76. {
  77. HRESULT hr = NO_ERROR;
  78. ALLOC_CACHE_CONFIGURATION acConfig;
  79. //
  80. // Initialize allocation lookaside
  81. //
  82. acConfig.nConcurrency = 1;
  83. acConfig.nThreshold = 100;
  84. acConfig.cbSize = sizeof( W3_CONNECTION );
  85. DBG_ASSERT( sm_pachW3Connections == NULL );
  86. sm_pachW3Connections = new ALLOC_CACHE_HANDLER( "W3_CONNECTION",
  87. &acConfig );
  88. if ( sm_pachW3Connections == NULL )
  89. {
  90. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  91. }
  92. //
  93. // Allocate table
  94. //
  95. sm_pConnectionTable = new W3_CONNECTION_HASH;
  96. if ( sm_pConnectionTable == NULL )
  97. {
  98. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  99. }
  100. return hr;
  101. }
  102. VOID
  103. W3_CONNECTION::Terminate(
  104. VOID
  105. )
  106. /*++
  107. Routine Description:
  108. Destroy W3_CONNECTION globals
  109. Arguments:
  110. None
  111. Return Value:
  112. None
  113. --*/
  114. {
  115. if ( sm_pConnectionTable != NULL )
  116. {
  117. delete sm_pConnectionTable;
  118. sm_pConnectionTable = NULL;
  119. }
  120. delete sm_pachW3Connections;
  121. sm_pachW3Connections = NULL;
  122. }
  123. HRESULT
  124. W3_CONNECTION::RetrieveConnection(
  125. HTTP_CONNECTION_ID ConnectionId,
  126. BOOL fCreateIfNotFound,
  127. W3_CONNECTION ** ppConnection
  128. )
  129. /*++
  130. Routine Description:
  131. Given, a UL_HTTP_REQUEST (and thus a UL_HTTP_CONNECTION_ID), determine
  132. whether there is an associated W3_CONNECTION with that ID. If not,
  133. create a new W3_CONNECTION. This function will also call into ULATQ to
  134. get an asynchronous notification when the connection goes away.
  135. Arguments:
  136. ConnectionId - Connection ID
  137. fCreateIfNotFound - Create if not found in hash table
  138. ppConnection - Receives a pointer to a W3_CONNECTION for this request
  139. Return Value:
  140. HRESULT
  141. --*/
  142. {
  143. W3_CONNECTION * pNewConnection;
  144. HRESULT hr;
  145. LK_RETCODE lkrc;
  146. BOOL fAlreadyDisconnected;
  147. DBG_ASSERT( ppConnection != NULL );
  148. *ppConnection = NULL;
  149. lkrc = sm_pConnectionTable->FindKey( &ConnectionId,
  150. ppConnection );
  151. if ( lkrc != LK_SUCCESS )
  152. {
  153. if ( !fCreateIfNotFound )
  154. {
  155. //
  156. // Just return out now since the caller doesn't want us to create
  157. // the connection object
  158. //
  159. return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  160. }
  161. //
  162. // Create a new connection object
  163. //
  164. pNewConnection = new W3_CONNECTION( ConnectionId );
  165. if ( pNewConnection == NULL )
  166. {
  167. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  168. }
  169. //
  170. // Insert the object into connection table
  171. //
  172. lkrc = sm_pConnectionTable->InsertRecord( pNewConnection );
  173. if ( lkrc != LK_SUCCESS )
  174. {
  175. delete pNewConnection;
  176. return HRESULT_FROM_WIN32( lkrc );
  177. }
  178. //
  179. // Monitor when the connection goes away
  180. //
  181. hr = UlAtqWaitForDisconnect( ConnectionId,
  182. TRUE,
  183. pNewConnection,
  184. &fAlreadyDisconnected );
  185. if ( FAILED( hr ) )
  186. {
  187. DBGPRINTF(( DBG_CONTEXT,
  188. "Error waiting for disconnect of connection '%p'. hr = %x\n",
  189. pNewConnection,
  190. hr ));
  191. //
  192. // OK. The connection must have gone away from under us. This
  193. // is not fatal. It just means that once the state machine has
  194. // completed, we should immediately destroy the connection
  195. // object.
  196. //
  197. pNewConnection->RemoveConnection();
  198. }
  199. else if ( fAlreadyDisconnected )
  200. {
  201. pNewConnection->_fConnected = FALSE;
  202. }
  203. *ppConnection = pNewConnection;
  204. }
  205. else
  206. {
  207. IF_DEBUG( CONN )
  208. {
  209. DBGPRINTF(( DBG_CONTEXT,
  210. "Request on existing W3_CONNECTION '%p'\n",
  211. *ppConnection ));
  212. }
  213. }
  214. return NO_ERROR;
  215. }
  216. VOID
  217. OnUlDisconnect(
  218. VOID * pvContext
  219. )
  220. /*++
  221. Routine Description:
  222. Completion routine called when a connection is closed
  223. Arguments:
  224. pvContext - Points to the W3_CONNECTION which was closed
  225. Return Value:
  226. None
  227. --*/
  228. {
  229. W3_CONNECTION * pConnection;
  230. DBG_ASSERT( pvContext != NULL );
  231. pConnection = (W3_CONNECTION*) pvContext;
  232. DBG_ASSERT( pConnection->CheckSignature() );
  233. pConnection->RemoveConnection();
  234. }
  235. VOID
  236. W3_CONNECTION::ReferenceConnection(
  237. VOID
  238. )
  239. /*++
  240. Routine Description:
  241. Reference the connection (duh)
  242. Arguments:
  243. None
  244. Return Value:
  245. None
  246. --*/
  247. {
  248. InterlockedIncrement( &_cRefs );
  249. }
  250. VOID
  251. W3_CONNECTION::DereferenceConnection(
  252. VOID
  253. )
  254. /*++
  255. Routine Description:
  256. Dereference and possibly cleanup the connection
  257. Arguments:
  258. None
  259. Return Value:
  260. None
  261. --*/
  262. {
  263. if ( InterlockedDecrement( &_cRefs ) == 0 )
  264. {
  265. delete this;
  266. }
  267. }
  268. VOID
  269. W3_CONNECTION::RemoveConnection(
  270. VOID
  271. )
  272. /*++
  273. Routine Description:
  274. Remove the connection from the hash table. This will indirectly
  275. dereference the connection so that it can await final cleanup
  276. Arguments:
  277. None
  278. Return Value:
  279. None
  280. --*/
  281. {
  282. _fConnected = FALSE;
  283. sm_pConnectionTable->DeleteRecord( this );
  284. }