|
|
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name : w3conn.cxx
Abstract: Http Connection management Author: Bilal Alam (balam) 6-Jan-2000
Environment: Win32 - User Mode
Project: ULW3.DLL --*/
#include "precomp.hxx"
ALLOC_CACHE_HANDLER * W3_CONNECTION::sm_pachW3Connections; W3_CONNECTION_HASH * W3_CONNECTION::sm_pConnectionTable;
W3_CONNECTION::W3_CONNECTION( HTTP_CONNECTION_ID connectionId ) : _cRefs( 1 ), _pUserContext( NULL ), _fConnected( TRUE ) { LK_RETCODE lkrc; _connId = connectionId; _dwSignature = W3_CONNECTION_SIGNATURE; ZeroMemory( _rgConnectionState, sizeof( _rgConnectionState ) );
IF_DEBUG( CONN ) { DBGPRINTF(( DBG_CONTEXT, "New W3_CONNECTION '%p' created\n", this )); } }
W3_CONNECTION::~W3_CONNECTION() { IF_DEBUG( CONN ) { DBGPRINTF(( DBG_CONTEXT, "W3_CONNECTION '%p' deleted\n", this )); } //
// Cleanup state associated with connection
//
for ( DWORD i = 0; i < STATE_COUNT; i++ ) { if ( _rgConnectionState[ i ] != NULL ) { _rgConnectionState[ i ]->Cleanup(); _rgConnectionState[ i ] = NULL; } } //
// Release the user context associated
//
if ( _pUserContext != NULL ) { _pUserContext->DereferenceUserContext(); _pUserContext = NULL; }
_dwSignature = W3_CONNECTION_SIGNATURE_FREE; }
HRESULT W3_CONNECTION::Initialize( VOID ) /*++
Routine Description: Global W3_CONNECTION initialization
Arguments:
None Return Value:
HRESULT
--*/ { HRESULT hr = NO_ERROR; ALLOC_CACHE_CONFIGURATION acConfig;
//
// Initialize allocation lookaside
//
acConfig.nConcurrency = 1; acConfig.nThreshold = 100; acConfig.cbSize = sizeof( W3_CONNECTION );
DBG_ASSERT( sm_pachW3Connections == NULL ); sm_pachW3Connections = new ALLOC_CACHE_HANDLER( "W3_CONNECTION", &acConfig );
if ( sm_pachW3Connections == NULL ) { return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); } //
// Allocate table
//
sm_pConnectionTable = new W3_CONNECTION_HASH; if ( sm_pConnectionTable == NULL ) { hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); } return hr; }
VOID W3_CONNECTION::Terminate( VOID ) /*++
Routine Description:
Destroy W3_CONNECTION globals
Arguments:
None Return Value:
None
--*/ { if ( sm_pConnectionTable != NULL ) { delete sm_pConnectionTable; sm_pConnectionTable = NULL; }
delete sm_pachW3Connections; sm_pachW3Connections = NULL; }
HRESULT W3_CONNECTION::RetrieveConnection( HTTP_CONNECTION_ID ConnectionId, BOOL fCreateIfNotFound, W3_CONNECTION ** ppConnection ) /*++
Routine Description:
Given, a UL_HTTP_REQUEST (and thus a UL_HTTP_CONNECTION_ID), determine whether there is an associated W3_CONNECTION with that ID. If not, create a new W3_CONNECTION. This function will also call into ULATQ to get an asynchronous notification when the connection goes away.
Arguments:
ConnectionId - Connection ID fCreateIfNotFound - Create if not found in hash table ppConnection - Receives a pointer to a W3_CONNECTION for this request Return Value:
HRESULT
--*/ { W3_CONNECTION * pNewConnection; HRESULT hr; LK_RETCODE lkrc; BOOL fAlreadyDisconnected; DBG_ASSERT( ppConnection != NULL );
*ppConnection = NULL;
lkrc = sm_pConnectionTable->FindKey( &ConnectionId, ppConnection ); if ( lkrc != LK_SUCCESS ) { if ( !fCreateIfNotFound ) { //
// Just return out now since the caller doesn't want us to create
// the connection object
//
return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ); } //
// Create a new connection object
//
pNewConnection = new W3_CONNECTION( ConnectionId ); if ( pNewConnection == NULL ) { return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); }
//
// Insert the object into connection table
//
lkrc = sm_pConnectionTable->InsertRecord( pNewConnection ); if ( lkrc != LK_SUCCESS ) { delete pNewConnection; return HRESULT_FROM_WIN32( lkrc ); } //
// Monitor when the connection goes away
//
hr = UlAtqWaitForDisconnect( ConnectionId, TRUE, pNewConnection, &fAlreadyDisconnected ); if ( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error waiting for disconnect of connection '%p'. hr = %x\n", pNewConnection, hr ));
//
// OK. The connection must have gone away from under us. This
// is not fatal. It just means that once the state machine has
// completed, we should immediately destroy the connection
// object.
//
pNewConnection->RemoveConnection(); } else if ( fAlreadyDisconnected ) { pNewConnection->_fConnected = FALSE; } *ppConnection = pNewConnection; } else { IF_DEBUG( CONN ) { DBGPRINTF(( DBG_CONTEXT, "Request on existing W3_CONNECTION '%p'\n", *ppConnection )); } } return NO_ERROR; }
VOID OnUlDisconnect( VOID * pvContext ) /*++
Routine Description:
Completion routine called when a connection is closed
Arguments:
pvContext - Points to the W3_CONNECTION which was closed Return Value:
None
--*/ { W3_CONNECTION * pConnection; DBG_ASSERT( pvContext != NULL ); pConnection = (W3_CONNECTION*) pvContext; DBG_ASSERT( pConnection->CheckSignature() ); pConnection->RemoveConnection(); }
VOID W3_CONNECTION::ReferenceConnection( VOID ) /*++
Routine Description:
Reference the connection (duh)
Arguments:
None Return Value:
None
--*/ { InterlockedIncrement( &_cRefs ); } VOID W3_CONNECTION::DereferenceConnection( VOID ) /*++
Routine Description:
Dereference and possibly cleanup the connection
Arguments:
None Return Value:
None
--*/ { if ( InterlockedDecrement( &_cRefs ) == 0 ) { delete this; } }
VOID W3_CONNECTION::RemoveConnection( VOID ) /*++
Routine Description:
Remove the connection from the hash table. This will indirectly dereference the connection so that it can await final cleanup
Arguments:
None Return Value:
None
--*/ { _fConnected = FALSE; sm_pConnectionTable->DeleteRecord( this ); }
|