You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
677 lines
20 KiB
677 lines
20 KiB
/************************************************************************************************
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
File Name: SocketPool.cpp
|
|
Abstract: Implementation of the socket pool (CSocketPool class)
|
|
and the callback function for IO Context.
|
|
Notes:
|
|
History: 08/01/2001 Created by Hao Yu (haoyu)
|
|
|
|
************************************************************************************************/
|
|
|
|
#include <stdafx.h>
|
|
#include <ThdPool.hxx>
|
|
#include <SockPool.hxx>
|
|
#include <GlobalDef.h>
|
|
|
|
typedef int (*FUNCGETADDRINFO)(const char *, const char *, const struct addrinfo *, struct addrinfo **);
|
|
typedef void (*FUNCFREEADDRINFO)(struct addrinfo *);
|
|
|
|
//The call back function for IO Context
|
|
VOID IOCallBack(PULONG_PTR pCompletionKey ,LPOVERLAPPED pOverlapped, DWORD dwBytesRcvd)
|
|
{
|
|
ASSERT( NULL != pCompletionKey );
|
|
char szBuffer[MAX_PATH]="+OK Server Ready";
|
|
WSABUF wszBuf={MAX_PATH, szBuffer};
|
|
DWORD dwNumSent=0;
|
|
DWORD dwFlag=0;
|
|
long lLockValue;
|
|
PIO_CONTEXT pIoContext=(PIO_CONTEXT)pCompletionKey;
|
|
|
|
|
|
if(pIoContext->m_ConType == LISTEN_SOCKET)
|
|
{
|
|
ASSERT(pOverlapped != NULL);
|
|
//This is a new connection
|
|
g_PerfCounters.IncPerfCntr(e_gcTotConnection);
|
|
g_PerfCounters.IncPerfCntr(e_gcConnectionRate);
|
|
g_PerfCounters.IncPerfCntr(e_gcConnectedSocketCnt);
|
|
|
|
pIoContext=CONTAINING_RECORD(pOverlapped, IO_CONTEXT, m_Overlapped);
|
|
pIoContext->m_dwLastIOTime=GetTickCount();
|
|
pIoContext->m_dwConnectionTime=pIoContext->m_dwLastIOTime;
|
|
pIoContext->m_lLock=LOCKED_TO_PROCESS_POP3_CMD;
|
|
if(ERROR_SUCCESS!=g_FreeList.RemoveFromList( &(pIoContext->m_ListEntry) ))
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,POP3SVR_SOCKET_REQUEST_BEFORE_INIT);
|
|
|
|
}
|
|
g_BusyList.AppendToList( &(pIoContext->m_ListEntry) );
|
|
g_SocketPool.DecrementFreeSocketCount();
|
|
pIoContext->m_pPop3Context->Reset();
|
|
pIoContext->m_pPop3Context->ProcessRequest(pIoContext, pOverlapped, dwBytesRcvd);
|
|
if(DELETE_PENDING == pIoContext->m_ConType)
|
|
{
|
|
g_BusyList.RemoveFromList(&(pIoContext->m_ListEntry));
|
|
if(g_SocketPool.IsMoreSocketsNeeded())
|
|
{
|
|
if(g_SocketPool.ReuseIOContext(pIoContext))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
delete(pIoContext->m_pPop3Context);
|
|
delete(pIoContext);
|
|
}
|
|
else
|
|
{
|
|
InterlockedExchange(&(pIoContext->m_lLock), UNLOCKED);
|
|
}
|
|
if( g_SocketPool.IsMoreSocketsNeeded() )
|
|
{
|
|
if(!g_SocketPool.AddSockets())
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,POP3SVR_CREATE_ADDITIONAL_SOCKET_FAILED);
|
|
}
|
|
}
|
|
if( g_SocketPool.IsMaxSocketUsed())
|
|
{
|
|
SetEvent(g_hDoSEvent);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
lLockValue = InterlockedCompareExchange(&(pIoContext->m_lLock), LOCKED_TO_PROCESS_POP3_CMD, UNLOCKED);
|
|
while(UNLOCKED!=lLockValue)
|
|
{
|
|
//This thread have to wait for the previous command to finish
|
|
//Or the timeout thread to mark it as timed out
|
|
Sleep(10);
|
|
lLockValue = InterlockedCompareExchange(&(pIoContext->m_lLock), LOCKED_TO_PROCESS_POP3_CMD, UNLOCKED);
|
|
}
|
|
|
|
|
|
if(CONNECTION_SOCKET == pIoContext->m_ConType )
|
|
{
|
|
pIoContext->m_pPop3Context->ProcessRequest(pIoContext, pOverlapped, dwBytesRcvd);
|
|
}
|
|
if(DELETE_PENDING == pIoContext->m_ConType)
|
|
{
|
|
g_BusyList.RemoveFromList(&(pIoContext->m_ListEntry));
|
|
if(g_SocketPool.IsMoreSocketsNeeded())
|
|
{
|
|
if(g_SocketPool.ReuseIOContext(pIoContext))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
delete(pIoContext->m_pPop3Context);
|
|
delete(pIoContext);
|
|
|
|
}
|
|
else
|
|
{
|
|
pIoContext->m_dwLastIOTime=GetTickCount();
|
|
InterlockedExchange(&(pIoContext->m_lLock), UNLOCKED);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
CSocketPool::CSocketPool()
|
|
{
|
|
InitializeCriticalSection(&m_csInitGuard);
|
|
m_sMainSocket = INVALID_SOCKET;
|
|
m_lMaxSocketCount = 0;
|
|
m_lMinSocketCount = 0;
|
|
m_lThreshold = 0;
|
|
m_lTotalSocketCount = 0;
|
|
m_lFreeSocketCount = 0;
|
|
m_bInit = FALSE;
|
|
m_lAddThreadToken = 1l;
|
|
m_iSocketFamily = 0;
|
|
m_iSocketType = 0;
|
|
m_iSocketProtocol = 0;
|
|
}
|
|
|
|
CSocketPool::~CSocketPool()
|
|
{
|
|
if(m_bInit)
|
|
{
|
|
Uninitialize();
|
|
}
|
|
DeleteCriticalSection(&m_csInitGuard);
|
|
}
|
|
|
|
|
|
|
|
BOOL CSocketPool::CreateMainSocket(u_short usPort)
|
|
{
|
|
BOOL bRetVal = TRUE;
|
|
PSOCKADDR addr;
|
|
SOCKADDR_IN inAddr;
|
|
INT addrLength;
|
|
OSVERSIONINFOEX osVersion;
|
|
HMODULE hMd=NULL;
|
|
FUNCGETADDRINFO fgetaddrinfo=NULL;
|
|
FUNCFREEADDRINFO ffreeaddrinfo=NULL;
|
|
|
|
char szPort[33]; //max bytes of buffer for _ultoa
|
|
addrinfo aiHints,*paiList=NULL, *paiIndex=NULL;
|
|
int iRet;
|
|
|
|
osVersion.dwOSVersionInfoSize=sizeof(OSVERSIONINFOEX);
|
|
if( !GetVersionEx((LPOSVERSIONINFO)(&osVersion)) )
|
|
{
|
|
// This should never happen
|
|
return FALSE;
|
|
}
|
|
|
|
if( (osVersion.dwMajorVersion>=5) //Only work with XP
|
|
&&
|
|
(osVersion.dwMinorVersion >1)
|
|
&&
|
|
( (osVersion.wProductType == VER_NT_SERVER ) ||
|
|
(osVersion.wProductType == VER_NT_DOMAIN_CONTROLLER) )
|
|
&&
|
|
(!
|
|
((osVersion.wSuiteMask & VER_SUITE_SMALLBUSINESS ) ||
|
|
(osVersion.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED ) ||
|
|
(osVersion.wSuiteMask & VER_SUITE_PERSONAL ) ) ) )
|
|
{
|
|
//These are the SKUs we support
|
|
}
|
|
else
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_UNSUPPORTED_OS);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
if(osVersion.dwMinorVersion > 0 ) //XP
|
|
{
|
|
hMd=GetModuleHandle(_T("WS2_32.dll"));
|
|
if(NULL == hMd)
|
|
{
|
|
return FALSE;
|
|
}
|
|
fgetaddrinfo=(FUNCGETADDRINFO)GetProcAddress(hMd, "getaddrinfo");
|
|
ffreeaddrinfo=(FUNCFREEADDRINFO)GetProcAddress(hMd, "freeaddrinfo");
|
|
if( (NULL == fgetaddrinfo) ||
|
|
(NULL == ffreeaddrinfo))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
_ultoa(usPort, szPort, 10);
|
|
memset(&aiHints, 0, sizeof(aiHints));
|
|
aiHints.ai_socktype = SOCK_STREAM;
|
|
aiHints.ai_flags = AI_PASSIVE;
|
|
iRet=fgetaddrinfo(NULL, szPort, &aiHints, &paiList);
|
|
if(iRet!=0)
|
|
{
|
|
//Error case
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_FAILED_TO_CREATE_SOCKET,
|
|
WSAGetLastError());
|
|
bRetVal=FALSE;
|
|
goto EXIT;
|
|
|
|
}
|
|
for(paiIndex=paiList; paiIndex!=NULL; paiIndex=paiIndex->ai_next)
|
|
{
|
|
if( ( (paiIndex->ai_family == PF_INET ) && (g_dwIPVersion != 6 ) ) ||
|
|
( (g_dwIPVersion==6) && (paiIndex->ai_family == PF_INET6 ) ) )
|
|
{
|
|
//Find the first (usually the only) addrinfo
|
|
m_iSocketFamily=paiIndex->ai_family; //For create AcceptEx socket
|
|
m_iSocketType=paiIndex->ai_socktype;
|
|
m_iSocketProtocol=paiIndex->ai_protocol;
|
|
m_sMainSocket = WSASocket(
|
|
m_iSocketFamily,
|
|
m_iSocketType,
|
|
m_iSocketProtocol,
|
|
NULL, // protocol info
|
|
0, // Group ID = 0 => no constraints
|
|
WSA_FLAG_OVERLAPPED // completion port notifications
|
|
);
|
|
if(INVALID_SOCKET == m_sMainSocket)
|
|
{
|
|
//This is not the socket family supported by the machine.
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if(INVALID_SOCKET==m_sMainSocket)
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_FAILED_TO_CREATE_SOCKET,
|
|
WSAGetLastError());
|
|
bRetVal=FALSE;
|
|
goto EXIT;
|
|
}
|
|
if ( bind( m_sMainSocket, paiIndex->ai_addr, paiIndex->ai_addrlen) != 0)
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_FAILED_TO_BIND_MAIN_SOCKET,
|
|
WSAGetLastError());
|
|
bRetVal=FALSE;
|
|
goto EXIT;
|
|
}
|
|
|
|
}
|
|
else //Win2k
|
|
{
|
|
m_iSocketFamily=PF_INET;
|
|
m_iSocketType=SOCK_STREAM;
|
|
m_iSocketProtocol=IPPROTO_TCP;
|
|
m_sMainSocket = WSASocket(
|
|
m_iSocketFamily,
|
|
m_iSocketType,
|
|
m_iSocketProtocol,
|
|
NULL, // protocol info
|
|
0, // Group ID = 0 => no constraints
|
|
WSA_FLAG_OVERLAPPED // completion port notifications
|
|
);
|
|
if(INVALID_SOCKET == m_sMainSocket)
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_FAILED_TO_CREATE_SOCKET,
|
|
WSAGetLastError());
|
|
bRetVal=FALSE;
|
|
goto EXIT;
|
|
}
|
|
|
|
addr = (PSOCKADDR)&inAddr;
|
|
addrLength = sizeof(inAddr);
|
|
ZeroMemory(addr, addrLength);
|
|
|
|
inAddr.sin_family = AF_INET;
|
|
inAddr.sin_port = htons(usPort);
|
|
inAddr.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
|
|
if ( bind( m_sMainSocket, addr, addrLength) != 0)
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_FAILED_TO_BIND_MAIN_SOCKET,
|
|
WSAGetLastError());
|
|
bRetVal=FALSE;
|
|
goto EXIT;
|
|
}
|
|
}
|
|
|
|
|
|
if ( listen( m_sMainSocket, m_iBackLog) != 0)
|
|
{
|
|
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_FAILED_TO_LISTEN_ON_MAIN_SOCKET,
|
|
WSAGetLastError());
|
|
bRetVal=FALSE;
|
|
goto EXIT;
|
|
}
|
|
|
|
m_stMainIOContext.m_hAsyncIO = m_sMainSocket;
|
|
m_stMainIOContext.m_ConType = LISTEN_SOCKET;
|
|
m_stMainIOContext.m_pCallBack = IOCallBack;
|
|
m_stMainIOContext.m_pPop3Context = NULL;
|
|
m_stMainIOContext.m_dwLastIOTime = 0; //No Timeout on this socket
|
|
m_stMainIOContext.m_lLock = UNLOCKED;
|
|
// Associate the main socket to the completion port
|
|
bRetVal = g_ThreadPool.AssociateContext(&m_stMainIOContext);
|
|
|
|
EXIT:
|
|
if(!bRetVal)
|
|
{
|
|
//Clean up the main listening socket
|
|
if( INVALID_SOCKET != m_sMainSocket )
|
|
{
|
|
closesocket(m_sMainSocket);
|
|
m_sMainSocket=INVALID_SOCKET;
|
|
}
|
|
}
|
|
if(NULL != paiList)
|
|
{
|
|
ffreeaddrinfo(paiList);
|
|
}
|
|
return bRetVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CSocketPool::Initialize(DWORD dwMax, DWORD dwMin, DWORD dwThreshold, u_short usPort, int iBackLog)
|
|
{
|
|
|
|
BOOL bRetVal=FALSE;
|
|
|
|
|
|
EnterCriticalSection(&m_csInitGuard);
|
|
|
|
ASSERT( ( dwMax >= dwMin + dwThreshold ) &&
|
|
( dwMin > 0 ) );
|
|
if( !( (dwMax >= dwMin + dwThreshold ) &&
|
|
( dwMin > 0 ) ) )
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
EVENT_POP3_NO_CONFIG_DATA);
|
|
goto EXIT;
|
|
}
|
|
if(!m_bInit)
|
|
{
|
|
WSADATA wsaData;
|
|
INT iErr;
|
|
|
|
iErr = WSAStartup( MAKEWORD( 2, 0), &wsaData);
|
|
if( iErr != 0 )
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_WINSOCK_FAILED_TO_INIT,
|
|
iErr);
|
|
bRetVal=FALSE;
|
|
goto EXIT;
|
|
}
|
|
m_lMaxSocketCount = dwMax;
|
|
m_lMinSocketCount = dwMin;
|
|
m_lThreshold = dwThreshold;
|
|
m_lFreeSocketCount = 0;
|
|
m_lTotalSocketCount= 0;
|
|
m_iBackLog = iBackLog;
|
|
//First Create the Main socket
|
|
if( bRetVal = CreateMainSocket(usPort) )
|
|
{
|
|
//Now create the initial pool of AcceptEx sockets
|
|
bRetVal = AddSocketsP(m_lMinSocketCount);
|
|
}
|
|
m_bInit=bRetVal;
|
|
}
|
|
EXIT:
|
|
LeaveCriticalSection(&m_csInitGuard);
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
// Called after
|
|
BOOL CSocketPool::IsMoreSocketsNeeded()
|
|
{
|
|
if ( (g_dwServerStatus != SERVICE_RUNNING ) &&
|
|
(g_dwServerStatus != SERVICE_PAUSED ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
if ( ( m_lTotalSocketCount < m_lMinSocketCount) ||
|
|
(( m_lFreeSocketCount < m_lThreshold ) &&
|
|
( m_lTotalSocketCount <m_lMaxSocketCount )) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CSocketPool::MaintainSocketCount()
|
|
{
|
|
if ( g_dwServerStatus != SERVICE_RUNNING )
|
|
{
|
|
return FALSE;
|
|
}
|
|
if(
|
|
( ( m_lFreeSocketCount < m_lThreshold ) &&
|
|
( m_lTotalSocketCount+m_lThreshold >= m_lMaxSocketCount ) )
|
|
||
|
|
( m_lTotalSocketCount <= m_lMinSocketCount )
|
|
)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL CSocketPool::Uninitialize()
|
|
{
|
|
BOOL bRetVal=TRUE;
|
|
EnterCriticalSection(&m_csInitGuard);
|
|
if(m_bInit)
|
|
{
|
|
// Close the main socket here
|
|
closesocket(m_sMainSocket);
|
|
m_sMainSocket=INVALID_SOCKET;
|
|
//AcceptEx Sockes should already have been cleaned with IO Context,
|
|
if(WSACleanup () )
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_WINSOCK_FAILED_TO_CLEANUP,
|
|
WSAGetLastError());
|
|
return FALSE;
|
|
}
|
|
m_bInit=FALSE;
|
|
}
|
|
LeaveCriticalSection(&m_csInitGuard);
|
|
return bRetVal;
|
|
}
|
|
|
|
// For working threading to call when a new connection was established
|
|
BOOL CSocketPool::AddSockets()
|
|
{
|
|
BOOL bRetVal=TRUE;
|
|
if( g_dwServerStatus != SERVICE_RUNNING )
|
|
{
|
|
return TRUE;
|
|
}
|
|
ASSERT(TRUE == m_bInit);
|
|
|
|
// Make sure only one thread get to add the socket
|
|
if( InterlockedExchange(&m_lAddThreadToken,0) )
|
|
{
|
|
bRetVal = AddSocketsP(m_lThreshold);
|
|
InterlockedExchange(&m_lAddThreadToken,1);
|
|
}
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
BOOL CSocketPool::AddSocketsP(DWORD dwNumOfSocket)
|
|
{
|
|
int i;
|
|
BOOL bRetVal=TRUE;
|
|
PIO_CONTEXT pIoContext=NULL;
|
|
|
|
for(i=0; i<dwNumOfSocket; i++)
|
|
{
|
|
|
|
if( (g_dwServerStatus != SERVICE_RUNNING ) &&
|
|
(g_dwServerStatus != SERVICE_START_PENDING) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
if(m_lMaxSocketCount < InterlockedIncrement(&m_lTotalSocketCount) )
|
|
{
|
|
InterlockedDecrement(&m_lTotalSocketCount);
|
|
return TRUE;
|
|
}
|
|
|
|
pIoContext=new (IO_CONTEXT);
|
|
if(NULL==pIoContext)
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_NOT_ENOUGH_MEMORY);
|
|
bRetVal=FALSE;
|
|
break;
|
|
}
|
|
pIoContext->m_pPop3Context=new(POP3_CONTEXT);
|
|
pIoContext->m_pCallBack = IOCallBack;
|
|
if(NULL == pIoContext->m_pPop3Context )
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_NOT_ENOUGH_MEMORY);
|
|
bRetVal=FALSE;
|
|
delete(pIoContext);
|
|
break;
|
|
}
|
|
|
|
bRetVal=CreateAcceptSocket(pIoContext);
|
|
if(!bRetVal)
|
|
{
|
|
delete(pIoContext->m_pPop3Context);
|
|
delete(pIoContext);
|
|
break;
|
|
}
|
|
InterlockedIncrement(&m_lFreeSocketCount);
|
|
if(m_lTotalSocketCount >= m_lMaxSocketCount)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(!bRetVal)
|
|
{
|
|
InterlockedDecrement(&m_lTotalSocketCount);
|
|
}
|
|
return bRetVal;
|
|
}
|
|
|
|
//Called when a new connection is establised
|
|
//and a AcceptEx socket is used
|
|
void CSocketPool::DecrementFreeSocketCount()
|
|
{
|
|
if(0==InterlockedDecrement(&m_lFreeSocketCount))
|
|
{
|
|
AddSockets();
|
|
}
|
|
|
|
}
|
|
|
|
//Called when a socket is closed
|
|
void CSocketPool::DecrementTotalSocketCount()
|
|
{
|
|
if(0==InterlockedDecrement(&m_lTotalSocketCount))
|
|
{
|
|
//Some socket must be created to avoid
|
|
//this denial of service problem.
|
|
AddSockets();
|
|
}
|
|
}
|
|
|
|
//Called when a socked is closed, however, the a new
|
|
// AcceptEx socket should be created to maintain
|
|
// total socket count, but keep the IOContext
|
|
// to re-use
|
|
BOOL CSocketPool::ReuseIOContext(PIO_CONTEXT pIoContext)
|
|
{
|
|
ASSERT( NULL != pIoContext);
|
|
if(InterlockedIncrement(&m_lTotalSocketCount) > m_lMaxSocketCount)
|
|
{
|
|
InterlockedDecrement(&m_lTotalSocketCount);
|
|
return FALSE;
|
|
}
|
|
pIoContext->m_pPop3Context->Reset();
|
|
if( CreateAcceptSocket(pIoContext) )
|
|
{
|
|
InterlockedIncrement(&m_lFreeSocketCount);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
InterlockedDecrement(&m_lTotalSocketCount);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL CSocketPool::CreateAcceptSocket(PIO_CONTEXT pIoContext)
|
|
{
|
|
ASSERT(NULL != pIoContext);
|
|
SOCKET sNew;
|
|
DWORD dwRcvd;
|
|
int iErr;
|
|
BOOL bRetVal=FALSE;
|
|
BOOL bAddToList=FALSE;
|
|
|
|
sNew=WSASocket(m_iSocketFamily,
|
|
m_iSocketType,
|
|
m_iSocketProtocol,
|
|
NULL, // protocol info
|
|
0, // Group ID = 0 => no constraints
|
|
WSA_FLAG_OVERLAPPED // completion port notifications
|
|
);
|
|
if(INVALID_SOCKET == sNew)
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_FAILED_TO_CREATE_SOCKET,
|
|
WSAGetLastError());
|
|
goto EXIT;
|
|
}
|
|
|
|
pIoContext->m_hAsyncIO=sNew;
|
|
pIoContext->m_ConType=CONNECTION_SOCKET;
|
|
pIoContext->m_lLock=UNLOCKED;
|
|
|
|
ZeroMemory(&(pIoContext->m_Overlapped), sizeof(OVERLAPPED));
|
|
|
|
g_FreeList.AppendToList( &(pIoContext->m_ListEntry) );
|
|
bAddToList=TRUE;
|
|
// Now add the new Context to the Completion Port
|
|
if( bRetVal = g_ThreadPool.AssociateContext(pIoContext))
|
|
{
|
|
bRetVal=AcceptEx(m_sMainSocket,
|
|
sNew,
|
|
(LPVOID)(pIoContext->m_Buffer),
|
|
0,
|
|
MIN_SOCKADDR_SIZE,
|
|
MIN_SOCKADDR_SIZE,
|
|
&dwRcvd,
|
|
&(pIoContext->m_Overlapped));
|
|
if(!bRetVal)
|
|
{
|
|
iErr= WSAGetLastError();
|
|
if(ERROR_IO_PENDING!=iErr)
|
|
{
|
|
g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
|
|
POP3SVR_CALL_ACCEPTEX_FAILED,
|
|
iErr);
|
|
}
|
|
else
|
|
{
|
|
bRetVal=TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
EXIT:
|
|
if(!bRetVal)
|
|
{
|
|
if(INVALID_SOCKET != sNew)
|
|
{
|
|
closesocket(sNew);
|
|
}
|
|
if(bAddToList)
|
|
{
|
|
g_FreeList.RemoveFromList(&(pIoContext->m_ListEntry));
|
|
}
|
|
}
|
|
|
|
|
|
return bRetVal;
|
|
|
|
}
|
|
|
|
BOOL CSocketPool::IsMaxSocketUsed()
|
|
{
|
|
return ( (m_lTotalSocketCount==m_lMaxSocketCount) &&
|
|
(m_lFreeSocketCount == 0 ) );
|
|
}
|