238 lines
6.4 KiB
C++
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
|