windows-nt/Source/XPSP1/NT/inetsrv/iis/staxinc/asynccon.hxx
2020-09-26 16:20:57 +08:00

238 lines
6.4 KiB
C++

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name :
asynccon.hxx
Abstract:
This file contains type definitions for async connections
Author:
Rohan Phillips (Rohanp) Feb-26-1998
Revision History:
--*/
#ifndef _ASYNC_CONN_HXX_
#define _ASYNC_CONN_HXX_
#define ASYNCCON_SIGNATURE 'uASY'
#define ASYNCCON_SIGNATURE_FREE 'fASY'
//Based on the NT WAITORTIMERCALLBACKFUNC - only adds a return value
typedef BOOL (NTAPI * USERCALLBACKFUNC) (PVOID, BOOLEAN );
extern BOOL
WINAPI
SmtpUnregisterWait(
HANDLE WaitHandle
);
extern HANDLE
WINAPI
SmtpRegisterWaitForSingleObject(
HANDLE hObject,
WAITORTIMERCALLBACKFUNC Callback,
PVOID Context,
ULONG dwMilliseconds
);
class CAsyncConnection
{
private:
DWORD m_Signature; //Signature of Object
DWORD m_TimeOut; //The amount of time that we wait for a connect
DWORD m_IpAddress; //The connected IP Address
DWORD m_Port; //The port we are connected to
DWORD m_Error; //Holds any error that happened
DWORD NextIpToTry; //The next IP address to try to connect to
LONG m_cActiveThreads;
LONG m_cRefCount;
BOOL m_IsFirstTime; //Are we doing a gethostbyname() or a real connect
BOOL m_fCloseSocket; //Should this class close the socket in the destructor
BOOL m_fTimedOut; //Did we time out ?
HANDLE m_RegisterWaitHandle; //The NT thread pool handle
HANDLE m_SignalHandle; //The handle we give the thread pool to wait on
SOCKET AsyncSock; //The socket we are connected to
USERCALLBACKFUNC m_CallBackFunc; //The users callback function
char m_HostName[100]; //Holds the machine we are trying to conenct to
//
// Maximum IP address stored for the instance, 20 smmes to be a commonly
// used value both for DNS and remoteq
//
enum { _MAX_HOSTENT_IP_ADDRESSES = 20};
// A copy of the HOSTENT structure for the instance's own IP addresses
// We have other buffers to save the contents of HOSTENT
// We will not take more than _MAX_HOSTENT_IP_ADDRESSES addresses.
struct hostent m_Hostent;
struct in_addr *m_pLocalIpAddresses[_MAX_HOSTENT_IP_ADDRESSES + 1];
struct in_addr m_LocalIpAddresses[_MAX_HOSTENT_IP_ADDRESSES + 1];
public:
CAsyncConnection(DWORD PortNo, DWORD TimeOut, char * Host, USERCALLBACKFUNC CallBack);
virtual ~CAsyncConnection();
SOCKET GetSockethandle(void) const {return AsyncSock;}
BOOL IsFirstTime(void) const {return m_IsFirstTime;}
DWORD GetConnectedIpAddress(void) const {return m_IpAddress;}
DWORD GetPortNum(void) const {return m_Port;}
DWORD GetErrorCode(void) const {return m_Error;}
void SetErrorCode(DWORD ErrorCode) {m_Error = ErrorCode;}
void SetConnectedIpAddress (DWORD IpAddress) {m_IpAddress = IpAddress;}
void SetFirstTime(BOOL fFirstTime) {m_IsFirstTime = fFirstTime;}
void SetCloseSocketFlag(BOOL bCloseFlag) {m_fCloseSocket = bCloseFlag;}
void SetTimedOutFlag (BOOL bTimedOut) {m_fTimedOut = bTimedOut;}
void SignalObject(void)
{
IncRefCount();
SetEvent(m_SignalHandle);
}
void SetWaitHandleToNull (void) {m_RegisterWaitHandle = NULL;}
BOOL ConnectToHost(void);
BOOL IssueTcpConnect(SOCKADDR_IN &connect_addr);
BOOL GetTimedOutFlag (void) const {return m_fTimedOut;}
virtual BOOL SetSocketOptions(void) { return TRUE;}
virtual BOOL CheckIpAddress(DWORD IpAddress, DWORD PortNum) {return TRUE;}
void SetNewHost(const char * NewHost)
{
lstrcpyn(m_HostName, NewHost, sizeof(m_HostName) - 1);
m_IsFirstTime = TRUE;
NextIpToTry = 0;
}
char * GetHostName(void) {return m_HostName;}
BOOL AsyncConnectSuccessfull(void);
virtual void IncNextIpToTry (void) {NextIpToTry++;}
virtual BOOL IsMoreIpAddresses(void) const
{
return(m_Hostent.h_addr_list[NextIpToTry] != NULL);
}
BOOL ResetSocketToBlockingMode(void)
{
unsigned int Block = 1;
int fRet = FALSE;
if(AsyncSock != INVALID_SOCKET)
{
WSAEventSelect(AsyncSock, m_SignalHandle, 0);
fRet = ioctlsocket(AsyncSock, FIONBIO, (u_long FAR *) &Block);
}
return fRet;
}
BOOL ExecuteUserCallBackRoutine(PVOID ThisPtr, BOOLEAN fTimedOut)
{
return m_CallBackFunc(ThisPtr, fTimedOut);
}
virtual BOOL MakeFirstAsyncConnect(void);
BOOL MakeNewConnection(void);
BOOL DoGetHostByName(void);
static void AsyncConnectCallback(PVOID ThisPtr, BOOLEAN fTimedOut);
void CloseAsyncSocket(void)
{
int RetVal = 0;
int Error = 0;
TraceFunctEnterEx((LPARAM) this, "CAsyncConnection::CloseAsyncSocket");
if(AsyncSock != INVALID_SOCKET)
{
ResetSocketToBlockingMode();
RetVal = closesocket(AsyncSock);
if(RetVal != 0)
{
Error = GetLastError();
ErrorTrace((LPARAM) this, "%s had error %d closing the socket", m_HostName, Error);
}
AsyncSock = INVALID_SOCKET;
}
TraceFunctLeaveEx((LPARAM)this);
}
BOOL IsValid (void) const{return ( m_Signature == ASYNCCON_SIGNATURE); }
BOOL InitializeAsyncConnect(void)
{
BOOL fRet = FALSE;
m_SignalHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
if(m_SignalHandle != NULL)
{
m_RegisterWaitHandle = SmtpRegisterWaitForSingleObject(m_SignalHandle, AsyncConnectCallback, this, m_TimeOut);
if(m_RegisterWaitHandle != NULL)
{
fRet = TRUE;
//kick things off.
SignalObject();
}
}
return fRet;
}
BOOL UnRegisterCallback(void)
{
if(m_RegisterWaitHandle)
{
SmtpUnregisterWait(m_RegisterWaitHandle);
m_RegisterWaitHandle = NULL;
}
return TRUE;
}
BOOL RegisterCallbackInfo(HANDLE SigHandle, WAITORTIMERCALLBACKFUNC Callback, DWORD TimeOut)
{
m_SignalHandle = SigHandle;
m_TimeOut = TimeOut;
m_RegisterWaitHandle = SmtpRegisterWaitForSingleObject(m_SignalHandle, Callback, this, TimeOut);
return (m_RegisterWaitHandle != NULL);
}
BOOL ReStartAsyncConnect(void)
{
m_RegisterWaitHandle = SmtpRegisterWaitForSingleObject(m_SignalHandle, AsyncConnectCallback, this, m_TimeOut);
return (m_RegisterWaitHandle != NULL);
}
void StoreHostent(struct hostent *pHostent);
BOOL ConnectToHost(DWORD IpAddress);
LONG IncThreadCount(void) { return InterlockedIncrement( &m_cActiveThreads ); }
LONG DecThreadCount(void) { return InterlockedDecrement( &m_cActiveThreads ); }
LONG GetThreadCount(void) const {return m_cActiveThreads;}
LONG IncRefCount(void) { return InterlockedIncrement( &m_cRefCount ); }
LONG DecRefCount(void) { return InterlockedDecrement( &m_cRefCount ); }
LONG GetRefCount(void) const {return m_cRefCount;}
};
#endif