|
|
/**********************************************************************/ /** Microsoft Windows NT **/ /** Copyright(c) Microsoft Corp., 1994 **/ /**********************************************************************/
/*
conn.hxx
This module contains the connection class
FILE HISTORY: Johnl 15-Aug-1994 Created
*/
#ifndef _CONN_HXX_
#define _CONN_HXX_
# include "w3inst.hxx"
# include "rdns.hxx"
# include <reftrace.h>
//
// Determines if client connection reference count tracking is enabled
//
#if DBG && !defined(_WIN64)
#define CC_REF_TRACKING 1
#else
#define CC_REF_TRACKING 0
#endif
//
// The default timeout to wait for the completion of an Atq IO request (in sec)
//
#define W3_IO_TIMEOUT (5*60)
//
// The initial size of the buffer to receive the client request
//
#define W3_DEFAULT_BUFFSIZE 4096
//
// The end of a line is considered to be the linefeed character
//
#define W3_EOL 0x0A
//
// Valid signature of a CLIENT_CONN_STATE
//
#define CLIENT_CONN_SIGNATURE ((DWORD) ' SCC')
//
// Invalid signature of a CLIENT_CONN_STATE
//
#define CLIENT_CONN_SIGNATURE_FREE ((DWORD) 'xssc')
//
// The various states a CLIENT_CONN object can be in
//
enum CLIENT_CONN_STATE { //
// We've just accepted the TCP connection from the client but we have
// no other information.
//
CCS_STARTUP = 0,
//
// We are in the process of receiving the client's HTTP request buffer
//
CCS_GETTING_CLIENT_REQ,
//
// We are reading data from the client socket meant for a gateway
//
CCS_GATHERING_GATEWAY_DATA,
//
// We're executing the clients HTTP request
//
CCS_PROCESSING_CLIENT_REQ,
//
// The server or client has initiated a disconnect. We have to
// wait till all outstanding IO requests are completed before
// cleaning up
//
CCS_DISCONNECTING,
//
// All pending requests have been completed. Finish cleaning
// up.
//
CCS_SHUTDOWN };
//
// parameter block used to initialize connections
//
typedef struct _CLIENT_CONN_PARAMS { SOCKET sClient; PSOCKADDR pAddrLocal; PSOCKADDR pAddrRemote; PATQ_CONTEXT pAtqContext; PVOID pEndpointObject; PIIS_ENDPOINT pEndpoint; PVOID pvInitialBuff; DWORD cbInitialBuff;
} CLIENT_CONN_PARAMS, *PCLIENT_CONN_PARAMS;
class CLIENT_CONN { public:
BOOL IsValid( VOID ) { return _fIsValid; }
//
// This is the work entry point that is driven by the completion of the
// async IO.
//
BOOL DoWork( DWORD BytesWritten, DWORD CompletionStatus, BOOL fIOCompletion);
#if CC_REF_TRACKING
//
// ATQ notification trace
//
// Notification of ATQ completion, for debugging purpose only.
//
VOID NotifyAtqProcessContext( DWORD BytesWritten, DWORD CompletionStatus, DWORD dwSig );
#endif
//
// Optionally sends a status response then initiates the disconnect
//
// HTResponse - HTTP status code
// ErrorResponse - System error or resource ID of response
//
// If this function fails, then the connection will be aborted
//
dllexp VOID Disconnect( HTTP_REQ_BASE * pRequest = NULL, DWORD HTResponse = 0, DWORD ErrorResponse = NO_ERROR, BOOL fDoShutdown = TRUE, LPBOOL pfFinished =NULL );
dllexp BOOL OnSessionStartup( BOOL *pfDoAgain, PVOID pvInitial = NULL, DWORD cbInitial = 0, BOOL fFirst = FALSE);
//
// Walks the connection list and calls disconnect on each connection
//
static VOID DisconnectAllUsers( PIIS_SERVER_INSTANCE Instance = NULL );
//
// Increments and decrements the reference count
//
UINT Reference( VOID );
UINT Dereference( VOID );
UINT QueryRefCount( VOID ) const { return _cRef; }
PIIS_ENDPOINT QueryW3Endpoint( VOID ) const { return m_pW3Endpoint; }
PW3_SERVER_INSTANCE QueryW3Instance( VOID ) const { return m_pInstance; }
BOOL IsW3Instance( VOID ) const { return m_pInstance != NULL; }
VOID SetW3Instance( IN PW3_SERVER_INSTANCE pInstance ) { DBG_ASSERT(m_pInstance == NULL); m_pInstance = pInstance; }
W3_SERVER_STATISTICS * QueryW3StatsObj( VOID ) const { return m_pW3Stats; }
VOID SetW3StatsObj( IN LPW3_SERVER_STATISTICS pW3Stats ) { m_pW3Stats = pW3Stats; }
DWORD QueryLocalIPAddress( VOID ) const { return m_localIpAddress; }
DWORD QueryRemoteIPAddress( VOID ) const { return m_remoteIpAddress; }
BOOL RequestAbortiveClose( VOID ); BOOL CloseConnection( VOID );
//
// Simple wrappers to the corresponding Atq functions
//
BOOL ReadFile( LPVOID lpBuffer, DWORD nBytesToRead ); BOOL WriteFile( LPVOID lpBuffer, DWORD nBytesToRead ); BOOL SyncWsaSend( WSABUF * rgWsaBuffers, DWORD cWsaBuffers, LPDWORD pcbWritten ); BOOL TransmitFile( HANDLE hFile, DWORD Offset, DWORD BytesToWrite, DWORD dwFlags, PVOID pHead = NULL, DWORD HeadLength = 0, PVOID pTail = NULL, DWORD TailLength = 0 ); BOOL TransmitFileAndRecv( HANDLE hFile, DWORD Offset, DWORD BytesToWrite, DWORD dwFlags, PVOID pHead = NULL, DWORD HeadLength = 0, PVOID pTail = NULL, DWORD TailLength = 0, LPVOID lpBuffer = NULL, DWORD BytesToRead = 0); BOOL WriteFileAndRecv( LPVOID lpSendBuffer, DWORD BytesToWrite, LPVOID lpRecvBuffer = NULL, DWORD BytesToRead = 0);
BOOL PostCompletionStatus( DWORD BytesTransferred );
//
// This list entry is put on the client connection list
//
LIST_ENTRY ListEntry;
SOCKET QuerySocket( VOID ) const { return _sClient; }
PATQ_CONTEXT QueryAtqContext( VOID ) const { return _AtqContext; }
USHORT QueryPort( VOID ) const { return _sPort; }
USHORT QueryRemotePort( VOID ) const { return _sRemotePort; }
BOOL IsSecurePort( VOID ) const { return _fSecurePort; }
//
// Make sure the next state is set before an async IO call is made
//
enum CLIENT_CONN_STATE QueryState( VOID ) const { return _ccState; }
VOID SetState( CLIENT_CONN_STATE ccState ) { _ccState = ccState; }
BOOL CheckSignature( VOID ) const { return _Signature == CLIENT_CONN_SIGNATURE; }
TCHAR * QueryRemoteAddr( VOID ) const { return (TCHAR *) _achRemoteAddr; }
TCHAR * QueryLocalAddr( VOID ) const { return (TCHAR *) _achLocalAddr; }
VOID SetAtqReuseContextFlag( BOOL fReuseContext ) { _fReuseContext = fReuseContext; } static DWORD QueryFreeListSize( VOID ) { return _cFree; }
static DWORD Initialize( VOID ); static VOID Terminate( VOID ); static CLIENT_CONN * Alloc( PCLIENT_CONN_PARAMS ); dllexp static VOID Free( CLIENT_CONN * pConn ); static VOID TrimFreeList( VOID );
BOOL QueryDnsName( LPBOOL pfSync, ADDRCHECKFUNCEX pFunc, ADDRCHECKARG pArg, LPSTR * ppName ) { return _acCheck.QueryDnsName( pfSync, pFunc, pArg, ppName ); }
AC_RESULT CheckIpAccess( LPBOOL pfNeedDns ) { return _acCheck.CheckIpAccess( pfNeedDns ); }
AC_RESULT CheckDnsAccess() { return _acCheck.CheckDnsAccess(); }
BOOL BindAccessCheckList( LPBYTE p, DWORD dw ) { return _acCheck.BindCheckList( p, dw ); }
VOID UnbindAccessCheckList() { _acCheck.UnbindCheckList(); }
LPSTR QueryResolvedDnsName() { return _acCheck.QueryResolvedDnsName(); }
BOOL IsDnsResolved() { return _acCheck.IsDnsResolved(); }
HTTP_REQ_BASE * QueryHttpReq( VOID) const { return (_phttpReq); }
protected:
//
// Constructor and destructor
//
CLIENT_CONN( PCLIENT_CONN_PARAMS ); VOID Initialize( PCLIENT_CONN_PARAMS );
~CLIENT_CONN( VOID );
VOID Reset( VOID );
BOOL IsCleaningUp( VOID ) const { return QueryState() == CCS_DISCONNECTING || QueryState() == CCS_SHUTDOWN; }
private:
//
// Contains the CLIENT_CONN signature
//
ULONG _Signature;
//
// Construction success indicator
//
BOOL _fIsValid;
//
// Contains the client socket connection openned by the connection thread
//
SOCKET _sClient;
enum CLIENT_CONN_STATE _ccState;
//
// Reference count. Can't go away until the count reaches 0
//
LONG _cRef;
//
// Contains an ASCII representation of the client's remote address
// and the adapter local address
//
CHAR _achRemoteAddr[20]; CHAR _achLocalAddr[20];
//
// Port this connection is on
//
USHORT _sPort;
//
// Remote port
//
USHORT _sRemotePort;
//
// This request came in through the secure port
//
BOOL _fSecurePort;
//
// Parses the data and determines the appropriate action
//
HTTP_REQ_BASE * _phttpReq;
//
// server instance. Both are referenced.
//
PW3_SERVER_INSTANCE m_pInstance; PIIS_ENDPOINT m_pW3Endpoint;
//
// server instance - statistics object.
//
LPW3_SERVER_STATISTICS m_pW3Stats;
//
// local ip address
//
DWORD m_localIpAddress;
//
// remote sockaddr
//
DWORD m_remoteIpAddress;
//
// context returned on a non-acceptex completion
//
PVOID m_atqEndpointObject;
//
// Initial receive buffer if we're doing AcceptEx processing
//
PVOID _pvInitial; DWORD _cbInitial;
PATQ_CONTEXT _AtqContext;
//
// If FALSE, the Atq Context should not be reused because the calling
// thread will be exiting soon
//
BOOL _fReuseContext:1;
BOOL _fAbortiveClose:1;
//
// Response string for disconnect notifications.
//
// NOTE: If the server handles non-serial requests, then two request completing at
// the same time could use this string
//
STR _strResponse;
//
// These are for the lookaside buffer list
//
static CRITICAL_SECTION _csBuffList; static LIST_ENTRY _BuffListHead; static BOOL _fGlobalInit; static DWORD _cFree; static DWORD _FreeListScavengerCookie;
LIST_ENTRY _BuffListEntry;
//
// Address check object for IP / DNS
//
ADDRESS_CHECK _acCheck;
#if CC_REF_TRACKING
public:
//
// For object local refcount tracing
//
PTRACE_LOG _pDbgCCRefTraceLog;
private: #endif
};
//
// Functions for connection reference counts
//
inline VOID ReferenceConn( CLIENT_CONN * pConn ) { pConn->Reference(); }
inline VOID DereferenceConn( CLIENT_CONN * pConn ) { if ( !pConn->Dereference() ) {
CLIENT_CONN::Free( pConn ); } }
/*******************************************************************
Support for CLIENT_CONN debug ref trace logging
SYNOPSIS: Macro for writing to debug ref trace log.
HISTORY: DaveK 10-Sep-1997 Created
********************************************************************/
//
// NOTE we avoid compile failure by hokey double typecast, below
// (since htrState is an enum, we must first cast it to int).
//
#define SHARED_LOG_REF_COUNT( \
cRefs \ , pClientConn \ , pHttpRequest \ , pWamRequest \ , htrState \ ) \ \ if( g_pDbgCCRefTraceLog != NULL ) { \ \ ULONG_PTR i = (ULONG_PTR)htrState; \ PVOID pv = (PVOID) i; \ \ WriteRefTraceLogEx( \ g_pDbgCCRefTraceLog \ , cRefs \ , pClientConn \ , pHttpRequest \ , pWamRequest \ , pv \ ); \ } \
//
// This macro logs the CLIENT_CONN specific ref trace log
//
#define LOCAL_LOG_REF_COUNT( \
cRefs \ , pClientConn \ , pHttpRequest \ , pWamRequest \ , htrState \ ) \ \ if( _pDbgCCRefTraceLog != NULL ) { \ \ ULONG_PTR i = (ULONG_PTR)htrState; \ PVOID pv = (PVOID) i; \ \ WriteRefTraceLogEx( \ _pDbgCCRefTraceLog \ , cRefs \ , pClientConn \ , pHttpRequest \ , pWamRequest \ , pv \ ); \ } \
#if CC_REF_TRACKING
inline VOID LogRefCountCCLocal( IN LONG cRefs , IN PVOID pClientConn , IN PVOID pHttpRequest , IN PVOID pWamRequest , IN int htrState ) { if( pClientConn && ((CLIENT_CONN *)pClientConn)->_pDbgCCRefTraceLog ) { WriteRefTraceLogEx( ((CLIENT_CONN *) pClientConn)->_pDbgCCRefTraceLog , cRefs , pClientConn , pHttpRequest , pWamRequest , (PVOID) htrState ); } } #endif
#if DBG
VOID DBG_CHECK_UnbalancedThreadToken( IN const char * pszFilePath, IN int nLineNum ); #endif //DBG
#endif // !_CONN_HXX_
|