Windows2003-3790/inetsrv/pop3/service/pop3svc/iolists.cpp
2020-09-30 16:53:55 +02:00

168 lines
5.1 KiB
C++

/************************************************************************************************
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 <IOLists.h>
#include "POP3Context.h"
CIOList::CIOList()
{
InitializeCriticalSection(&m_csListGuard);
m_dwListCount=0;
m_ListHead.Flink=&m_ListHead;
m_ListHead.Blink=&m_ListHead;
m_pCursor=&m_ListHead;
}
CIOList::~CIOList()
{
DeleteCriticalSection(&m_csListGuard);
}
void CIOList::AppendToList(PLIST_ENTRY pListEntry)
{
ASSERT(NULL != pListEntry);
EnterCriticalSection(&m_csListGuard);
pListEntry->Flink=&m_ListHead;
pListEntry->Blink=m_ListHead.Blink;
m_ListHead.Blink->Flink=pListEntry;
m_ListHead.Blink=pListEntry;
m_dwListCount++;
LeaveCriticalSection(&m_csListGuard);
}
DWORD CIOList::RemoveFromList(PLIST_ENTRY pListEntry)
{
if( (NULL == pListEntry) ||
(NULL == pListEntry->Flink) ||
(NULL == pListEntry->Blink) ||
(m_dwListCount ==0) )
{
return ERROR_INVALID_DATA;
}
EnterCriticalSection(&m_csListGuard);
pListEntry->Flink->Blink=pListEntry->Blink;
pListEntry->Blink->Flink=pListEntry->Flink;
m_dwListCount--;
//In case the Timeout checking is on going.
if(m_pCursor == pListEntry)
{
m_pCursor = pListEntry->Flink;
}
pListEntry->Flink=NULL;
pListEntry->Blink=NULL;
LeaveCriticalSection(&m_csListGuard);
return ERROR_SUCCESS;
}
// Returns the waiting time of the socket that waited the longest
// but not yet timed out.
DWORD CIOList::CheckTimeOut(DWORD dwTimeOutInterval,BOOL *pbIsAnyOneTimedOut)
{
DWORD dwTime;
DWORD dwNextTimeOut=0;
DWORD dwTimeOut=0;
PIO_CONTEXT pIoContext;
m_pCursor=m_ListHead.Flink;
while(m_pCursor!=&m_ListHead)
{
EnterCriticalSection(&m_csListGuard);
if(m_pCursor==&m_ListHead)
{
LeaveCriticalSection(&m_csListGuard);
break;
}
pIoContext=CONTAINING_RECORD(m_pCursor, IO_CONTEXT, m_ListEntry);
ASSERT(NULL != pIoContext);
if( UNLOCKED==InterlockedCompareExchange(&(pIoContext->m_lLock),LOCKED_FOR_TIMEOUT, UNLOCKED) )
{
if(DELETE_PENDING!=pIoContext->m_ConType)
{
dwTime=GetTickCount();
if(dwTime > pIoContext->m_dwLastIOTime )
{
dwTimeOut=dwTime - pIoContext->m_dwLastIOTime;
}
else
{
dwTimeOut=0;
}
if( ( dwTimeOut >= DEFAULT_TIME_OUT) || // Normal time out
( ( dwTimeOut >= dwTimeOutInterval) && // DoS Time out
( dwTimeOutInterval == SHORTENED_TIMEOUT) &&
( pIoContext->m_pPop3Context->Unauthenticated()) ) )
{
//This IO timed out
ASSERT(NULL != pIoContext->m_pPop3Context);
m_pCursor=m_pCursor->Flink;
pIoContext->m_pPop3Context->TimeOut(pIoContext);
if(pbIsAnyOneTimedOut)
*pbIsAnyOneTimedOut=TRUE;
}
else
{
if(dwNextTimeOut<dwTimeOut)
{
dwNextTimeOut=dwTimeOut;
}
m_pCursor=m_pCursor->Flink;
}
}
else
{
m_pCursor=m_pCursor->Flink;
}
InterlockedExchange(&(pIoContext->m_lLock),UNLOCKED);
}
else
{
m_pCursor=m_pCursor->Flink;
}
//Leave Critical Section so that other
//threads will get a chance to run.
LeaveCriticalSection(&m_csListGuard);
}
return dwNextTimeOut;
}
void CIOList::Cleanup()
{
PLIST_ENTRY pCursor=m_ListHead.Flink;
PIO_CONTEXT pIoContext;
EnterCriticalSection(&m_csListGuard);
while(pCursor!=&m_ListHead)
{
pIoContext=CONTAINING_RECORD(pCursor, IO_CONTEXT, m_ListEntry);
ASSERT(NULL != pIoContext);
ASSERT(NULL != pIoContext->m_pPop3Context);
pIoContext->m_pPop3Context->TimeOut(pIoContext);
pCursor->Flink->Blink=pCursor->Blink;
pCursor->Blink->Flink=pCursor->Flink;
pCursor=pCursor->Flink;
ASSERT(m_dwListCount >= 1);
m_dwListCount--;
//Delete the IO Context
delete(pIoContext->m_pPop3Context);
delete(pIoContext);
}
m_pCursor=&m_ListHead;
LeaveCriticalSection(&m_csListGuard);
}