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.

381 lines
7.2 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. DBG_ASSERT( ppConnection != NULL );
  147. *ppConnection = NULL;
  148. lkrc = sm_pConnectionTable->FindKey( ConnectionId,
  149. ppConnection );
  150. if ( lkrc != LK_SUCCESS )
  151. {
  152. if ( !fCreateIfNotFound )
  153. {
  154. //
  155. // Just return out now since the caller doesn't want us to create
  156. // the connection object
  157. //
  158. return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  159. }
  160. //
  161. // Create a new connection object
  162. //
  163. pNewConnection = new W3_CONNECTION( ConnectionId );
  164. if ( pNewConnection == NULL )
  165. {
  166. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  167. }
  168. //
  169. // Insert the object into connection table
  170. //
  171. lkrc = sm_pConnectionTable->InsertRecord( pNewConnection );
  172. if ( lkrc != LK_SUCCESS )
  173. {
  174. delete pNewConnection;
  175. return HRESULT_FROM_WIN32( lkrc );
  176. }
  177. //
  178. // Monitor when the connection goes away
  179. //
  180. hr = UlAtqWaitForDisconnect( ConnectionId,
  181. TRUE,
  182. pNewConnection );
  183. if ( FAILED( hr ) )
  184. {
  185. DBGPRINTF(( DBG_CONTEXT,
  186. "Error waiting for disconnect of connection '%p'. hr = %x\n",
  187. pNewConnection,
  188. hr ));
  189. //
  190. // OK. The connection must have gone away from under us. This
  191. // is not fatal. It just means that once the state machine has
  192. // completed, we should immediately destroy the connection
  193. // object.
  194. //
  195. pNewConnection->RemoveConnection();
  196. }
  197. *ppConnection = pNewConnection;
  198. }
  199. else
  200. {
  201. IF_DEBUG( CONN )
  202. {
  203. DBGPRINTF(( DBG_CONTEXT,
  204. "Request on existing W3_CONNECTION '%p'\n",
  205. *ppConnection ));
  206. }
  207. }
  208. return NO_ERROR;
  209. }
  210. VOID
  211. OnUlDisconnect(
  212. VOID * pvContext
  213. )
  214. /*++
  215. Routine Description:
  216. Completion routine called when a connection is closed
  217. Arguments:
  218. pvContext - Points to the W3_CONNECTION which was closed
  219. Return Value:
  220. None
  221. --*/
  222. {
  223. W3_CONNECTION * pConnection;
  224. DBG_ASSERT( pvContext != NULL );
  225. pConnection = (W3_CONNECTION*) pvContext;
  226. DBG_ASSERT( pConnection->CheckSignature() );
  227. pConnection->RemoveConnection();
  228. }
  229. VOID
  230. W3_CONNECTION::ReferenceConnection(
  231. VOID
  232. )
  233. /*++
  234. Routine Description:
  235. Reference the connection (duh)
  236. Arguments:
  237. None
  238. Return Value:
  239. None
  240. --*/
  241. {
  242. InterlockedIncrement( &_cRefs );
  243. }
  244. VOID
  245. W3_CONNECTION::DereferenceConnection(
  246. VOID
  247. )
  248. /*++
  249. Routine Description:
  250. Dereference and possibly cleanup the connection
  251. Arguments:
  252. None
  253. Return Value:
  254. None
  255. --*/
  256. {
  257. if ( InterlockedDecrement( &_cRefs ) == 0 )
  258. {
  259. delete this;
  260. }
  261. }
  262. VOID
  263. W3_CONNECTION::RemoveConnection(
  264. VOID
  265. )
  266. /*++
  267. Routine Description:
  268. Remove the connection from the hash table. This will indirectly
  269. dereference the connection so that it can await final cleanup
  270. Arguments:
  271. None
  272. Return Value:
  273. None
  274. --*/
  275. {
  276. _fConnected = FALSE;
  277. sm_pConnectionTable->DeleteRecord( this );
  278. }