/*++ 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