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.
506 lines
10 KiB
506 lines
10 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
queue.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of CQueue class.
|
|
|
|
|
|
Revision History:
|
|
|
|
06 Dec 2000 manishap
|
|
Created.
|
|
|
|
--*/
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Include files //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#include <Queue.h>
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// CQueue Implementation //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CQueue::CQueue(
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CQueue class.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
{
|
|
HKEY hk = NULL;
|
|
DWORD dwType = 0,dwSize = 0;
|
|
m_pHead = NULL;
|
|
m_pTail = NULL;
|
|
DWORD dwDisp = 0;
|
|
|
|
if( !TnSecureRegCreateKeyEx( HKEY_LOCAL_MACHINE, REG_PARAMS_KEY, NULL, NULL,
|
|
REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED , NULL, &hk, &dwDisp, 0) )
|
|
{
|
|
if( RegQueryValueEx( hk, L"MaxConnections", NULL, &dwType,
|
|
( LPBYTE )& m_dwMaxUnauthenticatedConnections,&dwSize)
|
|
)
|
|
{
|
|
m_dwMaxUnauthenticatedConnections = DEFAULT_MAX_CONNECTIONS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_dwMaxUnauthenticatedConnections = DEFAULT_MAX_CONNECTIONS;
|
|
}
|
|
|
|
|
|
m_dwNumOfUnauthenticatedConnections = 0;
|
|
m_dwMaxIPLimit = 4;
|
|
|
|
__try
|
|
{
|
|
InitializeCriticalSection(&m_csQModification);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
; // Nothing to do, just don't die.... BaskarK
|
|
}
|
|
}
|
|
|
|
CQueue::~CQueue(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CQueue class.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
if(m_pHead != NULL && m_pTail != NULL )
|
|
{
|
|
PQ_LIST_ENTRY pTmp=m_pHead;
|
|
while( m_pHead != m_pTail )
|
|
{
|
|
pTmp = m_pHead;
|
|
m_pHead = m_pHead->pQNext;
|
|
delete pTmp;
|
|
}
|
|
delete m_pHead;
|
|
}
|
|
m_pHead = NULL;
|
|
m_pTail = NULL;
|
|
|
|
DeleteCriticalSection(&m_csQModification);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Checks whether queue is full. i.e. if the number of entries are equal
|
|
to maximum number of unauthenticated connections allowed.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Values:
|
|
|
|
Returns TRUE on success.
|
|
|
|
--*/
|
|
|
|
bool
|
|
CQueue::IsQFull()
|
|
{ bool result;
|
|
bool bCSOwned = true;
|
|
do
|
|
{
|
|
__try
|
|
{
|
|
EnterCriticalSection(&m_csQModification);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Sleep(1);
|
|
bCSOwned = false;
|
|
}
|
|
}
|
|
while(!bCSOwned);
|
|
result = (m_dwNumOfUnauthenticatedConnections >= m_dwMaxUnauthenticatedConnections) ? true : false;
|
|
LeaveCriticalSection(&m_csQModification);
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
CQueue::FreeEntry(DWORD dwPid)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
Frees a particular entry in the queue.
|
|
Also modifies the MaxNumOfUnauthenticatedConn.
|
|
|
|
Arguments:
|
|
|
|
[in]pId whose entry is to be removed.
|
|
|
|
Return Values:
|
|
|
|
Returns TRUE on success.
|
|
|
|
--*/
|
|
|
|
{
|
|
bool bFound = FALSE;
|
|
bool bCSOwned = true;
|
|
do
|
|
{
|
|
__try
|
|
{
|
|
EnterCriticalSection(&m_csQModification);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Sleep(1);
|
|
bCSOwned = false;
|
|
}
|
|
}
|
|
while(!bCSOwned);
|
|
PQ_LIST_ENTRY pTmp=m_pHead;
|
|
while(!bFound && pTmp )
|
|
{
|
|
if( pTmp->dwPid == dwPid )
|
|
{
|
|
bFound = TRUE;
|
|
}
|
|
else if( pTmp != m_pTail )
|
|
{
|
|
pTmp = pTmp->pQNext;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(bFound)
|
|
{
|
|
if(pTmp == m_pHead )
|
|
{
|
|
if(m_pHead->pQNext)
|
|
{
|
|
m_pHead = m_pHead->pQNext;
|
|
m_pHead->pQPrev = NULL;
|
|
}
|
|
else
|
|
{
|
|
m_pHead = NULL;
|
|
m_pTail = NULL;
|
|
}
|
|
}
|
|
else if ( pTmp == m_pTail )
|
|
{
|
|
m_pTail = m_pTail->pQPrev;
|
|
m_pTail->pQNext = NULL;
|
|
}
|
|
else
|
|
{
|
|
(pTmp->pQPrev)->pQNext = pTmp->pQNext;
|
|
(pTmp->pQNext)->pQPrev = pTmp->pQPrev;
|
|
}
|
|
m_dwNumOfUnauthenticatedConnections--;
|
|
delete pTmp;
|
|
|
|
}
|
|
LeaveCriticalSection(&m_csQModification);
|
|
return (bFound);
|
|
}
|
|
|
|
|
|
bool
|
|
CQueue::Pop(HANDLE *phWritePipe)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Frees a head entry in the queue.
|
|
|
|
Arguments:
|
|
|
|
Stores the pid and pipe handle. [out]pId, [out]PipeHandle.
|
|
|
|
Return Values:
|
|
|
|
Returns TRUE on success.
|
|
|
|
--*/
|
|
|
|
{
|
|
bool bRet = FALSE;
|
|
bool bCSOwned = true;
|
|
do
|
|
{
|
|
__try
|
|
{
|
|
EnterCriticalSection(&m_csQModification);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Sleep(1);
|
|
bCSOwned = false;
|
|
}
|
|
}
|
|
while(!bCSOwned);
|
|
*phWritePipe = m_pHead->hWritePipe;
|
|
bRet = FreeEntry(m_pHead->dwPid);
|
|
LeaveCriticalSection(&m_csQModification);
|
|
return (bRet);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Checks whether new entry can be added to the queue. New entry will
|
|
be denied when it comes from an IP Address for which the maximum
|
|
number of entries allowed per IP Address are already present in the queue
|
|
or when the queue is full.
|
|
In normal case, when new entry is to be added and the queue is not full,
|
|
entry is added at the tail position.
|
|
In case of IPLimit Reached, and QueueFull, the bool variable bSendMessage
|
|
is set to TRUE, which will be passed back to the caller function, which in turn
|
|
will send a message to the session that it ( the session ) has been terminated.
|
|
|
|
Arguments:
|
|
|
|
[in]pId ,[in]IP Address , [in/out]PipeHandle of an entry to be added [out]SendMessage. On Input,
|
|
it takes the values to be added in the queue. On output, it sends the values of removed
|
|
entry in case of IPLimitReached or QueueFull. [out]bSendMessage is set to true if
|
|
the queue is full or if the IPlimit is reached. This
|
|
flag will be used to notify that particular session that it should terminate.
|
|
|
|
Return Values:
|
|
|
|
Returns TRUE if the entry gets added to the queue successfully.
|
|
|
|
--*/
|
|
|
|
bool
|
|
CQueue::WasTheClientAdded(DWORD dwPid, IP_ADDR *pchIPAddr, HANDLE *phWritePipe, bool *pbSendMessage)
|
|
{
|
|
bool bRet = FALSE;
|
|
HANDLE hHeadWritePipe=NULL;
|
|
bool bCSOwned = true;
|
|
do
|
|
{
|
|
__try
|
|
{
|
|
EnterCriticalSection(&m_csQModification);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Sleep(1);
|
|
bCSOwned = false;
|
|
}
|
|
}
|
|
while(!bCSOwned);
|
|
*pbSendMessage = true;
|
|
|
|
if((! IsQFull()) && (! IsIPLimitReached(pchIPAddr)))
|
|
{
|
|
if (Push(dwPid, phWritePipe, pchIPAddr)) // This could fail in low memory
|
|
{
|
|
bRet = TRUE;
|
|
*pbSendMessage = false;
|
|
}
|
|
}
|
|
LeaveCriticalSection(&m_csQModification);
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
bool
|
|
CQueue::OkToProceedWithThisClient(IP_ADDR *pchIPAddr)
|
|
{
|
|
bool bRet = TRUE;
|
|
bool bCSOwned = true;
|
|
do
|
|
{
|
|
__try
|
|
{
|
|
EnterCriticalSection(&m_csQModification);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Sleep(1);
|
|
bCSOwned = false;
|
|
}
|
|
}
|
|
while(!bCSOwned);
|
|
if (
|
|
(IsQFull()) ||
|
|
(IsIPLimitReached(pchIPAddr))
|
|
)
|
|
{
|
|
bRet = false;
|
|
}
|
|
LeaveCriticalSection(&m_csQModification);
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Checks if the maximum number of entries for a particular IP Address are already
|
|
present.
|
|
|
|
Arguments:
|
|
|
|
IP address of new entry to be added in the queue.
|
|
|
|
Return Values:
|
|
|
|
Returns TRUE if maximum number of entries for a particular IP Address are
|
|
already present.
|
|
|
|
--*/
|
|
|
|
bool
|
|
CQueue::IsIPLimitReached(IP_ADDR *pchIPAddr)
|
|
{
|
|
bool bReached = FALSE;
|
|
DWORD dwCount = 0;
|
|
// Request ownership of the critical section.
|
|
bool bCSOwned = true;
|
|
do
|
|
{
|
|
__try
|
|
{
|
|
EnterCriticalSection(&m_csQModification);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Sleep(1);
|
|
bCSOwned = false;
|
|
}
|
|
}
|
|
while(!bCSOwned);
|
|
PQ_LIST_ENTRY pTmp = m_pHead;
|
|
while( pTmp )
|
|
{
|
|
if(strcmp (pTmp->chIPAddr, pchIPAddr) == 0 )
|
|
{
|
|
dwCount ++;
|
|
if(dwCount == m_dwMaxIPLimit)
|
|
{
|
|
bReached = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
pTmp = pTmp->pQNext;
|
|
}
|
|
// Release ownership of the critical section.
|
|
LeaveCriticalSection(&m_csQModification);
|
|
return (bReached);
|
|
}
|
|
|
|
bool
|
|
CQueue::Push(DWORD dwPid, HANDLE *phWritePipe, IP_ADDR *pchIPAddr)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocates memory for an entry and adds it in the queue.
|
|
Also modifies the MaxNumOfUnauthenticatedConn.
|
|
|
|
Arguments:
|
|
|
|
[in]pId and [in]PipeHandle [in]IP Address of an entry to be added.
|
|
|
|
Return Values:
|
|
|
|
Returns TRUE on success.
|
|
|
|
--*/
|
|
|
|
{
|
|
PQ_LIST_ENTRY pNode;
|
|
bool bRet = FALSE;
|
|
// Request ownership of the critical section.
|
|
bool bCSOwned = true;
|
|
do
|
|
{
|
|
__try
|
|
{
|
|
EnterCriticalSection(&m_csQModification);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Sleep(1);
|
|
bCSOwned = false;
|
|
}
|
|
}
|
|
while(!bCSOwned);
|
|
pNode = (PQ_LIST_ENTRY) new Q_LIST_ENTRY;
|
|
|
|
if (pNode)
|
|
{
|
|
pNode->pQNext = NULL;
|
|
pNode->pQPrev= NULL;
|
|
|
|
if(NULL == m_pHead )
|
|
{
|
|
m_pHead = pNode;
|
|
m_pTail = pNode;
|
|
}
|
|
else
|
|
{
|
|
m_pTail->pQNext = pNode;
|
|
pNode->pQPrev = m_pTail;
|
|
m_pTail = pNode;
|
|
}
|
|
m_pTail->dwPid = dwPid;
|
|
m_pTail->hWritePipe = (*phWritePipe);
|
|
strncpy(m_pTail->chIPAddr, pchIPAddr, SMALL_STRING - 1);
|
|
bRet = TRUE;
|
|
m_dwNumOfUnauthenticatedConnections++;
|
|
}
|
|
// Release ownership of the critical section.
|
|
LeaveCriticalSection(&m_csQModification);
|
|
return (bRet);
|
|
}
|
|
|