1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00
Files
winscp/source/filezilla/AsyncSocketExLayer.cpp
Martin Prikryl 3f4e41fee0 Clang imposed changes that should be noop and have no effect on classic compiler
Mostly:
– incorrectly identified uninitialized variables
– explicit static global variables
– const, sign and down casts and safety
– typename use
– semicolon after function implementation
– unused variables, fields, arguments and macros
– field initialization order
– exact include filename case
– redundant in code macros already defined at project level

(cherry picked from commit f7f00c631e)

Source commit: 90ad9390853aba308abe73cf02e0281238c53c87
2025-03-13 16:46:26 +01:00

991 lines
25 KiB
C++

// CAsyncSocketEx by Tim Kosse (Tim.Kosse@gmx.de)
// Version 1.1 (2002-11-01)
//---------------------------------------------------------------------------
// Feel free to use this class, as long as you don't claim that you wrote it
// and this copyright notice stays intact in the source files.
// If you use this class in commercial applications, please send a short message
// to tim.kosse@gmx.de
//---------------------------------------------------------------------------
#include "stdafx.h"
#include "AsyncSocketExLayer.h"
#include "AsyncSocketEx.h"
#define WM_SOCKETEX_NOTIFY (WM_USER+3)
//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////
CAsyncSocketExLayer::CAsyncSocketExLayer()
{
m_pOwnerSocket = NULL;
m_pNextLayer = NULL;
m_pPrevLayer = NULL;
m_nLayerState = notsock;
m_nCriticalError=0;
m_nPendingEvents = 0;
m_nFamily = AF_UNSPEC;
m_lEvent = 0;
m_lpszSocketAddress = 0;
m_nSocketPort = 0;
m_nextAddr = 0;
m_addrInfo = 0;
}
CAsyncSocketExLayer::~CAsyncSocketExLayer()
{
delete [] m_lpszSocketAddress;
}
CAsyncSocketExLayer *CAsyncSocketExLayer::AddLayer(CAsyncSocketExLayer *pLayer, CAsyncSocketEx *pOwnerSocket)
{
DebugAssert(pLayer);
DebugAssert(pOwnerSocket);
if (m_pNextLayer)
{
return m_pNextLayer->AddLayer(pLayer, pOwnerSocket);
}
else
{
DebugAssert(m_pOwnerSocket==pOwnerSocket);
pLayer->Init(this, m_pOwnerSocket);
m_pNextLayer=pLayer;
}
return m_pNextLayer;
}
int CAsyncSocketExLayer::Receive(void* lpBuf, int nBufLen, int nFlags /*=0*/)
{
return ReceiveNext(lpBuf, nBufLen, nFlags);
}
int CAsyncSocketExLayer::Send(const void* lpBuf, int nBufLen, int nFlags /*=0*/)
{
return SendNext(lpBuf, nBufLen, nFlags);
}
void CAsyncSocketExLayer::OnReceive(int nErrorCode)
{
if (m_pPrevLayer)
{
m_pPrevLayer->OnReceive(nErrorCode);
}
else
{
if (m_pOwnerSocket->m_lEvent&FD_READ)
{
m_pOwnerSocket->OnReceive(nErrorCode);
}
}
}
void CAsyncSocketExLayer::OnSend(int nErrorCode)
{
if (m_pPrevLayer)
{
m_pPrevLayer->OnSend(nErrorCode);
}
else
{
if (m_pOwnerSocket->m_lEvent&FD_WRITE)
{
m_pOwnerSocket->OnSend(nErrorCode);
}
}
}
void CAsyncSocketExLayer::OnConnect(int nErrorCode)
{
TriggerEvent(FD_CONNECT, nErrorCode, TRUE);
}
void CAsyncSocketExLayer::OnAccept(int nErrorCode)
{
if (m_pPrevLayer)
m_pPrevLayer->OnAccept(nErrorCode);
else
if (m_pOwnerSocket->m_lEvent&FD_ACCEPT)
m_pOwnerSocket->OnAccept(nErrorCode);
}
void CAsyncSocketExLayer::OnClose(int nErrorCode)
{
if (m_pPrevLayer)
m_pPrevLayer->OnClose(nErrorCode);
else
if (m_pOwnerSocket->m_lEvent&FD_CLOSE)
m_pOwnerSocket->OnClose(nErrorCode);
}
BOOL CAsyncSocketExLayer::TriggerEvent(long lEvent, int nErrorCode, BOOL bPassThrough /*=FALSE*/ )
{
DebugAssert(m_pOwnerSocket);
if (m_pOwnerSocket->m_SocketData.hSocket==INVALID_SOCKET)
{
return FALSE;
}
if (!bPassThrough)
{
if (m_nPendingEvents & lEvent)
{
return TRUE;
}
m_nPendingEvents |= lEvent;
}
if (lEvent & FD_CONNECT)
{
DebugAssert(bPassThrough);
if (!nErrorCode)
{
DebugAssert(bPassThrough && (GetLayerState()==connected || GetLayerState()==attached));
}
else if (nErrorCode)
{
SetLayerState(aborted);
m_nCriticalError=nErrorCode;
}
}
else if (lEvent & FD_CLOSE)
{
if (!nErrorCode)
{
SetLayerState(closed);
}
else
{
SetLayerState(aborted);
m_nCriticalError = nErrorCode;
}
}
DebugAssert(m_pOwnerSocket->m_pLocalAsyncSocketExThreadData);
DebugAssert(m_pOwnerSocket->m_pLocalAsyncSocketExThreadData->m_pHelperWindow);
DebugAssert(m_pOwnerSocket->m_SocketData.nSocketIndex!=-1);
t_LayerNotifyMsg *pMsg=new t_LayerNotifyMsg;
pMsg->hSocket = m_pOwnerSocket->m_SocketData.hSocket;
pMsg->lEvent = ( lEvent % 0xffff ) + ( nErrorCode << 16);
pMsg->pLayer=bPassThrough?m_pPrevLayer:this;
BOOL res=PostMessage(m_pOwnerSocket->GetHelperWindowHandle(), WM_USER, (WPARAM)m_pOwnerSocket->m_SocketData.nSocketIndex, (LPARAM)pMsg);
if (!res)
{
delete pMsg;
}
return res;
}
void CAsyncSocketExLayer::Close()
{
CloseNext();
}
void CAsyncSocketExLayer::CloseNext()
{
if (m_addrInfo)
freeaddrinfo(m_addrInfo);
m_nextAddr = 0;
m_addrInfo = 0;
m_nPendingEvents = 0;
SetLayerState(notsock);
if (m_pNextLayer)
m_pNextLayer->Close();
}
BOOL CAsyncSocketExLayer::Connect(LPCTSTR lpszHostAddress, UINT nHostPort)
{
return ConnectNext(lpszHostAddress, nHostPort);
}
BOOL CAsyncSocketExLayer::Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen )
{
return ConnectNext(lpSockAddr, nSockAddrLen);
}
int CAsyncSocketExLayer::SendNext(const void *lpBuf, int nBufLen, int nFlags /*=0*/)
{
if (m_nCriticalError)
{
WSASetLastError(m_nCriticalError);
return SOCKET_ERROR;
}
else if (GetLayerState()==notsock)
{
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
else if (GetLayerState()==unconnected || GetLayerState()==connecting || GetLayerState()==listening)
{
WSASetLastError(WSAENOTCONN);
return SOCKET_ERROR;
}
if (!m_pNextLayer)
{
DebugAssert(m_pOwnerSocket);
int sent = send(m_pOwnerSocket->GetSocketHandle(), (LPSTR)lpBuf, nBufLen, nFlags);
return sent;
}
else
{
return m_pNextLayer->Send(lpBuf, nBufLen, nFlags);
}
}
int CAsyncSocketExLayer::ReceiveNext(void *lpBuf, int nBufLen, int nFlags /*=0*/)
{
if (m_nCriticalError)
{
WSASetLastError(m_nCriticalError);
return SOCKET_ERROR;
}
else if (GetLayerState()==notsock)
{
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
else if (GetLayerState()==unconnected || GetLayerState()==connecting || GetLayerState()==listening)
{
WSASetLastError(WSAENOTCONN);
return SOCKET_ERROR;
}
if (!m_pNextLayer)
{
DebugAssert(m_pOwnerSocket);
return recv(m_pOwnerSocket->GetSocketHandle(), (LPSTR)lpBuf, nBufLen, nFlags);
}
else
{
return m_pNextLayer->Receive(lpBuf, nBufLen, nFlags);
}
}
BOOL CAsyncSocketExLayer::ConnectNext(LPCTSTR lpszHostAddress, UINT nHostPort)
{
DebugAssert(GetLayerState()==unconnected);
DebugAssert(m_pOwnerSocket);
BOOL res = FALSE;
if (m_pNextLayer)
res = m_pNextLayer->Connect(lpszHostAddress, nHostPort);
else if (m_nFamily == AF_INET)
{
USES_CONVERSION;
DebugAssert(lpszHostAddress != NULL);
SOCKADDR_IN sockAddr;
memset(&sockAddr,0,sizeof(sockAddr));
LPSTR lpszAscii = T2A((LPTSTR)lpszHostAddress);
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(lpszAscii);
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
WSASetLastError(WSAEINVAL);
res = FALSE;
}
}
sockAddr.sin_port = htons((u_short)nHostPort);
res = (SOCKET_ERROR != connect(m_pOwnerSocket->GetSocketHandle(), (SOCKADDR*)&sockAddr, sizeof(sockAddr)) );
}
else if (m_nFamily == AF_INET6 || m_nFamily == AF_UNSPEC)
{
USES_CONVERSION;
DebugAssert(lpszHostAddress != NULL);
addrinfo hints, *res0, *res1;
SOCKET hSocket;
int error;
char port[10];
freeaddrinfo(m_addrInfo);
m_nextAddr = 0;
m_addrInfo = 0;
memset(&hints, 0, sizeof(addrinfo));
hints.ai_family = m_nFamily;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
_snprintf(port, 9, "%u", nHostPort);
error = getaddrinfo(T2CA(lpszHostAddress), port, &hints, &res0);
if (error)
return FALSE;
for (res1 = res0; res1; res1 = res1->ai_next)
{
if (m_nFamily == AF_UNSPEC)
hSocket = socket(res1->ai_family, res1->ai_socktype, res1->ai_protocol);
else
hSocket = m_pOwnerSocket->GetSocketHandle();
if (INVALID_SOCKET == hSocket)
{
res = FALSE;
continue;
}
if (m_nFamily == AF_UNSPEC)
{
m_pOwnerSocket->m_SocketData.hSocket = hSocket;
m_pOwnerSocket->AttachHandle(hSocket);
if (!m_pOwnerSocket->AsyncSelect(m_lEvent))
{
m_pOwnerSocket->Close();
res = FALSE;
continue ;
}
if (m_pOwnerSocket->m_pFirstLayer)
{
if (WSAAsyncSelect(m_pOwnerSocket->m_SocketData.hSocket, m_pOwnerSocket->GetHelperWindowHandle(), m_pOwnerSocket->m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE) )
{
m_pOwnerSocket->Close();
res = FALSE;
continue;
}
}
if (m_pOwnerSocket->m_pendingCallbacks.size())
PostMessage(m_pOwnerSocket->GetHelperWindowHandle(), WM_USER + 2, (WPARAM)m_pOwnerSocket->m_SocketData.nSocketIndex, 0);
}
if (m_nFamily == AF_UNSPEC)
{
m_pOwnerSocket->m_SocketData.nFamily = m_nFamily = res1->ai_family;
if (!m_pOwnerSocket->Bind(m_nSocketPort, m_lpszSocketAddress))
{
m_pOwnerSocket->m_SocketData.nFamily = m_nFamily = AF_UNSPEC;
Close();
continue;
}
}
if (!( res = ( SOCKET_ERROR != connect(m_pOwnerSocket->GetSocketHandle(), res1->ai_addr, res1->ai_addrlen) ) )
&& WSAGetLastError() != WSAEWOULDBLOCK)
{
if (hints.ai_family == AF_UNSPEC)
{
m_nFamily = AF_UNSPEC;
Close();
}
continue ;
}
m_nFamily = res1->ai_family;
m_pOwnerSocket->m_SocketData.nFamily = res1->ai_family;
res = TRUE;
break;
}
if (res1)
res1 = res0->ai_next;
if (res1)
{
m_addrInfo = res0;
m_nextAddr = res1;
}
else
freeaddrinfo(res0);
if (INVALID_SOCKET == m_pOwnerSocket->GetSocketHandle())
res = FALSE ;
}
if (res || WSAGetLastError() == WSAEWOULDBLOCK)
{
SetLayerState(connecting);
}
return res;
}
BOOL CAsyncSocketExLayer::ConnectNext( const SOCKADDR* lpSockAddr, int nSockAddrLen )
{
DebugAssert(GetLayerState()==unconnected);
DebugAssert(m_pOwnerSocket);
BOOL res;
if (m_pNextLayer)
res=m_pNextLayer->Connect(lpSockAddr, nSockAddrLen);
else
res = (SOCKET_ERROR!=connect(m_pOwnerSocket->GetSocketHandle(), lpSockAddr, nSockAddrLen));
if (res || WSAGetLastError()==WSAEWOULDBLOCK)
SetLayerState(connecting);
return res;
}
//Gets the address of the peer socket to which the socket is connected
BOOL CAsyncSocketExLayer::GetPeerName( CString& rPeerAddress, UINT& rPeerPort )
{
return GetPeerNameNext(rPeerAddress, rPeerPort);
}
BOOL CAsyncSocketExLayer::GetPeerNameNext( CString& rPeerAddress, UINT& rPeerPort )
{
if (m_pNextLayer)
{
return m_pNextLayer->GetPeerName(rPeerAddress, rPeerPort);
}
else
{
SOCKADDR* sockAddr;
int nSockAddrLen;
if (m_nFamily == AF_INET6)
{
sockAddr = (SOCKADDR*)new SOCKADDR_IN6;
nSockAddrLen = sizeof(SOCKADDR_IN6);
}
else if (m_nFamily == AF_INET)
{
sockAddr = (SOCKADDR*)new SOCKADDR_IN;
nSockAddrLen = sizeof(SOCKADDR_IN);
}
memset(sockAddr, 0, nSockAddrLen);
BOOL bResult = GetPeerName(sockAddr, &nSockAddrLen);
if (bResult)
{
if (m_nFamily == AF_INET6)
{
rPeerPort = ntohs(((SOCKADDR_IN6*)sockAddr)->sin6_port);
LPTSTR buf = Inet6AddrToString(((SOCKADDR_IN6*)sockAddr)->sin6_addr);
rPeerAddress = buf;
delete [] buf;
}
else if (m_nFamily == AF_INET)
{
rPeerPort = ntohs(((SOCKADDR_IN*)sockAddr)->sin_port);
rPeerAddress = inet_ntoa(((SOCKADDR_IN*)sockAddr)->sin_addr);
}
else
{
delete sockAddr;
return FALSE;
}
}
delete sockAddr;
return bResult;
}
}
BOOL CAsyncSocketExLayer::GetPeerName( SOCKADDR* lpSockAddr, int* lpSockAddrLen )
{
return GetPeerNameNext(lpSockAddr, lpSockAddrLen);
}
BOOL CAsyncSocketExLayer::GetPeerNameNext( SOCKADDR* lpSockAddr, int* lpSockAddrLen )
{
if (m_pNextLayer)
{
return m_pNextLayer->GetPeerName(lpSockAddr, lpSockAddrLen);
}
else
{
DebugAssert(m_pOwnerSocket);
if ( !getpeername(m_pOwnerSocket->GetSocketHandle(), lpSockAddr, lpSockAddrLen) )
{
return TRUE;
}
else
{
return FALSE;
}
}
}
//Gets the address of the sock socket to which the socket is connected
BOOL CAsyncSocketExLayer::GetSockName( CString& rSockAddress, UINT& rSockPort )
{
return GetSockNameNext(rSockAddress, rSockPort);
}
BOOL CAsyncSocketExLayer::GetSockNameNext( CString& rSockAddress, UINT& rSockPort )
{
if (m_pNextLayer)
return m_pNextLayer->GetSockName(rSockAddress, rSockPort);
else
{
SOCKADDR* sockAddr;
int nSockAddrLen;
if (m_nFamily == AF_INET6)
{
sockAddr = (SOCKADDR*)new SOCKADDR_IN6;
nSockAddrLen = sizeof(SOCKADDR_IN6);
}
else if (m_nFamily == AF_INET)
{
sockAddr = (SOCKADDR*)new SOCKADDR_IN;
nSockAddrLen = sizeof(SOCKADDR_IN);
}
memset(sockAddr, 0, nSockAddrLen);
BOOL bResult = GetSockName(sockAddr, &nSockAddrLen);
if (bResult)
{
if (m_nFamily == AF_INET6)
{
rSockPort = ntohs(((SOCKADDR_IN6*)sockAddr)->sin6_port);
LPTSTR buf = Inet6AddrToString(((SOCKADDR_IN6*)sockAddr)->sin6_addr);
rSockAddress = buf;
delete [] buf;
}
else if (m_nFamily == AF_INET)
{
rSockPort = ntohs(((SOCKADDR_IN*)sockAddr)->sin_port);
rSockAddress = inet_ntoa(((SOCKADDR_IN*)sockAddr)->sin_addr);
}
else
{
delete sockAddr;
return FALSE;
}
}
delete sockAddr;
return bResult;
}
}
BOOL CAsyncSocketExLayer::GetSockName( SOCKADDR* lpSockAddr, int* lpSockAddrLen )
{
return GetSockNameNext(lpSockAddr, lpSockAddrLen);
}
BOOL CAsyncSocketExLayer::GetSockNameNext( SOCKADDR* lpSockAddr, int* lpSockAddrLen )
{
if (m_pNextLayer)
return m_pNextLayer->GetSockName(lpSockAddr, lpSockAddrLen);
else
{
DebugAssert(m_pOwnerSocket);
if ( !getsockname(m_pOwnerSocket->GetSocketHandle(), lpSockAddr, lpSockAddrLen) )
return TRUE;
else
return FALSE;
}
}
void CAsyncSocketExLayer::Init(CAsyncSocketExLayer *pPrevLayer, CAsyncSocketEx *pOwnerSocket)
{
DebugAssert(pOwnerSocket);
m_pPrevLayer=pPrevLayer;
m_pOwnerSocket=pOwnerSocket;
m_pNextLayer=0;
SetLayerState(pOwnerSocket->GetState());
}
int CAsyncSocketExLayer::GetLayerState()
{
return m_nLayerState;
}
void CAsyncSocketExLayer::SetLayerState(int nLayerState)
{
DebugAssert(m_pOwnerSocket);
int nOldLayerState=GetLayerState();
m_nLayerState=nLayerState;
if (nOldLayerState!=nLayerState)
DoLayerCallback(LAYERCALLBACK_STATECHANGE, GetLayerState(), nOldLayerState);
}
void CAsyncSocketExLayer::CallEvent(int nEvent, int nErrorCode)
{
if (m_nCriticalError)
{
return;
}
m_nCriticalError = nErrorCode;
switch (nEvent)
{
case FD_READ:
case FD_FORCEREAD:
if (GetLayerState()==connecting && !nErrorCode)
{
m_nPendingEvents |= nEvent;
break;
}
else if (GetLayerState()==attached)
SetLayerState(connected);
if (nEvent & FD_READ)
m_nPendingEvents &= ~FD_READ;
else
m_nPendingEvents &= ~FD_FORCEREAD;
if (GetLayerState()==connected || nErrorCode)
{
if (nErrorCode)
SetLayerState(aborted);
OnReceive(nErrorCode);
}
break;
case FD_WRITE:
if (GetLayerState()==connecting && !nErrorCode)
{
m_nPendingEvents |= nEvent;
break;
}
else if (GetLayerState()==attached)
SetLayerState(connected);
m_nPendingEvents &= ~FD_WRITE;
if (GetLayerState()==connected || nErrorCode)
{
if (nErrorCode)
SetLayerState(aborted);
OnSend(nErrorCode);
}
break;
case FD_CONNECT:
if (GetLayerState()==connecting || GetLayerState() == attached)
{
if (!nErrorCode)
SetLayerState(connected);
else
{
if (!m_pNextLayer && m_nextAddr)
if (TryNextProtocol())
{
m_nCriticalError = 0;
return;
}
SetLayerState(aborted);
}
m_nPendingEvents &= ~FD_CONNECT;
OnConnect(nErrorCode);
if (!nErrorCode)
{
if ((m_nPendingEvents & FD_READ) && GetLayerState()==connected)
OnReceive(0);
if ((m_nPendingEvents & FD_FORCEREAD) && GetLayerState()==connected)
OnReceive(0);
if ((m_nPendingEvents & FD_WRITE) && GetLayerState()==connected)
OnSend(0);
}
m_nPendingEvents = 0;
}
break;
case FD_ACCEPT:
if (GetLayerState()==listening)
{
if (nErrorCode)
SetLayerState(aborted);
m_nPendingEvents &= ~FD_ACCEPT;
OnAccept(nErrorCode);
}
break;
case FD_CLOSE:
if (GetLayerState()==connected || GetLayerState()==attached)
{
if (nErrorCode)
SetLayerState(aborted);
else
SetLayerState(closed);
m_nPendingEvents &= ~FD_CLOSE;
OnClose(nErrorCode);
}
break;
}
}
//Creates a socket
BOOL CAsyncSocketExLayer::Create(UINT nSocketPort, int nSocketType,
long lEvent, LPCTSTR lpszSocketAddress, int nFamily /*=AF_INET*/)
{
return CreateNext(nSocketPort, nSocketType, lEvent, lpszSocketAddress, nFamily);
}
BOOL CAsyncSocketExLayer::CreateNext(UINT nSocketPort, int nSocketType, long lEvent, LPCTSTR lpszSocketAddress, int nFamily /*=AF_INET*/)
{
DebugAssert((GetLayerState() == notsock) || (GetLayerState() == unconnected));
BOOL res = FALSE;
m_nFamily = nFamily;
if (m_pNextLayer)
res = m_pNextLayer->Create(nSocketPort, nSocketType, lEvent, lpszSocketAddress, nFamily);
else if (m_nFamily == AF_UNSPEC)
{
m_lEvent = lEvent;
delete [] m_lpszSocketAddress;
if (lpszSocketAddress && *lpszSocketAddress)
{
m_lpszSocketAddress = new TCHAR[_tcslen(lpszSocketAddress) + 1];
_tcscpy(m_lpszSocketAddress, lpszSocketAddress);
}
else
m_lpszSocketAddress = 0;
m_nSocketPort = nSocketPort;
res = TRUE;
}
else
{
SOCKET hSocket=socket(nFamily, nSocketType, 0);
if (hSocket == INVALID_SOCKET)
{
m_pOwnerSocket->Close();
return FALSE;
}
m_pOwnerSocket->m_SocketData.hSocket=hSocket;
m_pOwnerSocket->AttachHandle(hSocket);
if (!m_pOwnerSocket->AsyncSelect(lEvent))
{
m_pOwnerSocket->Close();
return FALSE;
}
if (m_pOwnerSocket->m_pFirstLayer)
{
if (WSAAsyncSelect(m_pOwnerSocket->m_SocketData.hSocket, m_pOwnerSocket->GetHelperWindowHandle(), m_pOwnerSocket->m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE) )
{
m_pOwnerSocket->Close();
return FALSE;
}
}
if (!m_pOwnerSocket->Bind(nSocketPort, lpszSocketAddress))
{
m_pOwnerSocket->Close();
return FALSE;
}
res = TRUE;
}
if (res)
SetLayerState(unconnected);
return res;
}
int CAsyncSocketExLayer::DoLayerCallback(int nType, int nParam1, int nParam2, char* str /*=0*/)
{
if (!m_pOwnerSocket)
return 0;
int nError = WSAGetLastError();
t_callbackMsg msg;
msg.pLayer = this;
msg.nType = nType;
msg.nParam1 = nParam1;
msg.nParam2 = nParam2;
msg.str = str;
m_pOwnerSocket->AddCallbackNotification(msg);
WSASetLastError(nError);
return 0;
}
BOOL CAsyncSocketExLayer::Listen( int nConnectionBacklog)
{
return ListenNext( nConnectionBacklog);
}
BOOL CAsyncSocketExLayer::ListenNext( int nConnectionBacklog)
{
DebugAssert(GetLayerState()==unconnected);
BOOL res;
if (m_pNextLayer)
res=m_pNextLayer->Listen(nConnectionBacklog);
else
res=listen(m_pOwnerSocket->GetSocketHandle(), nConnectionBacklog);
if (res!=SOCKET_ERROR)
{
SetLayerState(listening);
}
return res!=SOCKET_ERROR;
}
BOOL CAsyncSocketExLayer::Accept( CAsyncSocketEx& rConnectedSocket, SOCKADDR* lpSockAddr /*=NULL*/, int* lpSockAddrLen /*=NULL*/ )
{
return AcceptNext(rConnectedSocket, lpSockAddr, lpSockAddrLen);
}
BOOL CAsyncSocketExLayer::AcceptNext( CAsyncSocketEx& rConnectedSocket, SOCKADDR* lpSockAddr /*=NULL*/, int* lpSockAddrLen /*=NULL*/ )
{
DebugAssert(GetLayerState()==listening);
BOOL res;
if (m_pNextLayer)
res=m_pNextLayer->Accept(rConnectedSocket, lpSockAddr, lpSockAddrLen);
else
{
SOCKET hTemp = accept(m_pOwnerSocket->m_SocketData.hSocket, lpSockAddr, lpSockAddrLen);
if (hTemp == INVALID_SOCKET)
return FALSE;
DebugCheck(rConnectedSocket.InitAsyncSocketExInstance());
rConnectedSocket.m_SocketData.hSocket=hTemp;
rConnectedSocket.AttachHandle(hTemp);
rConnectedSocket.SetFamily(GetFamily());
rConnectedSocket.SetState(connected);
}
return TRUE;
}
BOOL CAsyncSocketExLayer::ShutDown(int nHow /*=sends*/)
{
return ShutDownNext(nHow);
}
BOOL CAsyncSocketExLayer::ShutDownNext(int nHow /*=sends*/)
{
if (m_nCriticalError)
{
WSASetLastError(m_nCriticalError);
return FALSE;
}
else if (GetLayerState()==notsock)
{
WSASetLastError(WSAENOTSOCK);
return FALSE;
}
else if (GetLayerState()==unconnected || GetLayerState()==connecting || GetLayerState()==listening)
{
WSASetLastError(WSAENOTCONN);
return FALSE;
}
if (!m_pNextLayer)
{
DebugAssert(m_pOwnerSocket);
return (shutdown(m_pOwnerSocket->GetSocketHandle(), nHow) == 0);
}
else
{
return m_pNextLayer->ShutDown(nHow);
}
}
int CAsyncSocketExLayer::GetFamily() const
{
return m_nFamily;
}
bool CAsyncSocketExLayer::SetFamily(int nFamily)
{
if (m_nFamily != AF_UNSPEC)
return false;
m_nFamily = nFamily;
return true;
}
bool CAsyncSocketExLayer::TryNextProtocol()
{
m_pOwnerSocket->DetachHandle(m_pOwnerSocket->m_SocketData.hSocket);
closesocket(m_pOwnerSocket->m_SocketData.hSocket);
m_pOwnerSocket->m_SocketData.hSocket = INVALID_SOCKET;
BOOL ret = FALSE;
for (; m_nextAddr; m_nextAddr = m_nextAddr->ai_next)
{
m_pOwnerSocket->m_SocketData.hSocket = socket(m_nextAddr->ai_family, m_nextAddr->ai_socktype, m_nextAddr->ai_protocol);
if (m_pOwnerSocket->m_SocketData.hSocket == INVALID_SOCKET)
continue;
m_pOwnerSocket->AttachHandle(m_pOwnerSocket->m_SocketData.hSocket);
if (!m_pOwnerSocket->AsyncSelect(m_lEvent))
{
m_pOwnerSocket->DetachHandle(m_pOwnerSocket->m_SocketData.hSocket);
closesocket(m_pOwnerSocket->m_SocketData.hSocket);
m_pOwnerSocket->m_SocketData.hSocket = INVALID_SOCKET;
continue;
}
if (m_pOwnerSocket->m_pFirstLayer)
{
if (WSAAsyncSelect(m_pOwnerSocket->m_SocketData.hSocket, m_pOwnerSocket->GetHelperWindowHandle(), m_pOwnerSocket->m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE))
{
m_pOwnerSocket->DetachHandle(m_pOwnerSocket->m_SocketData.hSocket);
closesocket(m_pOwnerSocket->m_SocketData.hSocket);
m_pOwnerSocket->m_SocketData.hSocket = INVALID_SOCKET;
continue;
}
}
m_pOwnerSocket->m_SocketData.nFamily = m_nextAddr->ai_family;
m_nFamily = m_nextAddr->ai_family;
if (!m_pOwnerSocket->Bind(m_nSocketPort, m_lpszSocketAddress))
{
m_pOwnerSocket->DetachHandle(m_pOwnerSocket->m_SocketData.hSocket);
closesocket(m_pOwnerSocket->m_SocketData.hSocket);
m_pOwnerSocket->m_SocketData.hSocket = INVALID_SOCKET;
continue;
}
if (connect(m_pOwnerSocket->GetSocketHandle(), m_nextAddr->ai_addr, m_nextAddr->ai_addrlen) == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
{
m_pOwnerSocket->DetachHandle(m_pOwnerSocket->m_SocketData.hSocket);
closesocket(m_pOwnerSocket->m_SocketData.hSocket);
m_pOwnerSocket->m_SocketData.hSocket = INVALID_SOCKET;
continue;
}
SetLayerState(connecting);
ret = true;
break;
}
if (m_nextAddr)
m_nextAddr = m_nextAddr->ai_next;
if (!m_nextAddr)
{
freeaddrinfo(m_addrInfo);
m_nextAddr = 0;
m_addrInfo = 0;
}
if (m_pOwnerSocket->m_SocketData.hSocket == INVALID_SOCKET || !ret)
return FALSE;
else
return TRUE;
}
void CAsyncSocketExLayer::LogSocketMessageRaw(int nMessageType, LPCTSTR pMsg)
{
if (m_pPrevLayer)
m_pPrevLayer->LogSocketMessageRaw(nMessageType, pMsg);
else
m_pOwnerSocket->LogSocketMessageRaw(nMessageType, pMsg);
}
bool CAsyncSocketExLayer::LoggingSocketMessage(int nMessageType)
{
if (m_pPrevLayer)
return m_pPrevLayer->LoggingSocketMessage(nMessageType);
else
return m_pOwnerSocket->LoggingSocketMessage(nMessageType);
}
int CAsyncSocketExLayer::GetSocketOptionVal(int OptionID) const
{
if (m_pPrevLayer)
return m_pPrevLayer->GetSocketOptionVal(OptionID);
else
return m_pOwnerSocket->GetSocketOptionVal(OptionID);
}