windows-nt/Source/XPSP1/NT/net/wins/server/com/assoc.c

1683 lines
30 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
assoc.c
Abstract:
THis module contains the functions that deal with associations and
dialogues
Functions:
CommAssocSetUpAssoc
CommAssocFrmStartAssocReq
CommAssocUfmStartAssocReq
CommAssocFrmStopAssocReq
CommAssocUfmStopAssocReq
CommAssocFrmStartAssocRsp
CommAssocUfmStartAssocRsp
CommAssocAllocAssoc
CommAssocAllocDlg
AllocEnt
DeallocEnt
CommAssocDeallocAssoc
CommAssocDeallocDlg
CommAssocInit
CommAssocInsertUdpDlgInTbl
CommAssocDeleteUdpDlgInTbl
CommAssocCreateAssocInTbl
CommAssocDeleteAssocInTbl
CommAssocLookupAssoc
CommAssocInsertAssocInTbl
Portability:
This module is portable
Author:
Pradeep Bahl (PradeepB) 7-Dec-1992
Revision History:
Modification date Person Description of modification
----------------- ------- ----------------------------
--*/
/*
* Includes
*/
#include "wins.h"
#include "nms.h"
#include "comm.h"
#include "assoc.h"
#include "winsque.h"
#include "winsmsc.h"
#include "winsevt.h"
/*
* Local Macro Declarations
*/
/*
* Local Typedef Declarations
*/
#if PRSCONN
STATIC DWORD sAssocSeqNo = 0;
#else
STATIC DWORD sAssocSeqNo = 1;
#endif
STATIC QUE_HD_T sAssocQueHd;
STATIC CRITICAL_SECTION sAssocListCrtSec;
#if PRSCONN
STATIC DWORD sDlgSeqNo = 0;
#else
STATIC DWORD sDlgSeqNo = 1;
#endif
STATIC QUE_HD_T sDlgQueHd;
STATIC DWORD sNoOfDlgCrtSec; //no of crt. secs in dlgs
STATIC DWORD sNoOfAssocCrtSec; //no of crt. secs in assocs.
STATIC CRITICAL_SECTION sDlgListCrtSec;
STATIC LIST_ENTRY sUdpDlgHead;
COMMASSOC_TAG_POOL_T sTagAssoc; //32bit ULONG -> LPVOID mapping
/*
* Global Variable Definitions
*/
/*
Handles to the heaps to be used for assoc. and dlg. allocation
*/
HANDLE CommAssocAssocHeapHdl;
HANDLE CommAssocDlgHeapHdl;
HANDLE CommAssocTcpMsgHeapHdl;
/*
Size of the memory for one assoc.
*/
DWORD CommAssocAssocSize = 0;
/*
Size of
DWORD CommAssocMaxAssoc = 0;
/*
* Local Variable Definitions
*/
STATIC CRITICAL_SECTION sUdpDlgTblCrtSec;
//
// This is the start of the Responder Assoc Table. This table holds the list of
// active Responder associations. Currently, the table is implemented
// as a linked list using the Rtl Linked list functions.
//
QUE_HD_T sRspAssocQueHd;
/*
* Local Function Prototype Declarations
*/
/* prototypes for functions local to this module go here */
STATIC
LPVOID
AllocEnt(
HANDLE HeapHdl,
PQUE_HD_T pQueHd,
LPCRITICAL_SECTION pCrtSec,
LPDWORD pSeqNoCntr,
DWORD Size,
LPDWORD pCntCrtSec
);
STATIC
VOID
DeallocEnt(
HANDLE HeapHdl,
PQUE_HD_T pQueHd,
LPCRITICAL_SECTION pCrtSec,
LPDWORD pSeqNoCntr,
LPVOID pHdl,
LPDWORD pCntCrtSec
);
//
// Function definitions start here
//
VOID
CommAssocSetUpAssoc(
IN PCOMM_HDL_T pDlgHdl,
IN PCOMM_ADD_T pAdd,
IN COMM_TYP_E CommTyp_e,
OUT PCOMMASSOC_ASSOC_CTX_T *ppAssocCtx
)
/*++
Routine Description:
This function sets up an association
Arguments:
pDlghdl - Handle to dlg under which an association has to be set up
pAdd - Address of node with which the association has to be set up
CommTyp_e - TYpe of association
ppAssocCtx - Association Context block allocated by the function
Externals Used:
None
Called by:
ECommStartDlg
Comments:
None
Return Value:
Success status codes -- WINS_SUCCESS
Error status codes --
--*/
{
SOCKET SockNo = INVALID_SOCKET;
PCOMMASSOC_ASSOC_CTX_T pAssocCtx = NULL; //v. imp to init this to NULL
INT BytesRead = -1;
MSG_T pTcpMsg;
STATUS RetStat;
WINS_MEM_T WinsMem[2];
PWINS_MEM_T pWinsMem = WinsMem;
#if SUPPORT612WINS > 0
BYTE AssocMsg[COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE];
DWORD MsgLen = COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE;
#else
BYTE AssocMsg[COMMASSOC_ASSOC_MSG_SIZE];
DWORD MsgLen = COMMASSOC_ASSOC_MSG_SIZE;
#endif
PCOMMASSOC_DLG_CTX_T pDlgCtx = pDlgHdl->pEnt;
pWinsMem->pMem = NULL;
try {
/*
* Create a TCP connection to the WINS at the other node
*/
CommConnect(
pAdd,
CommWinsTcpPortNo, // WINS_TCP_PORT,
&SockNo
);
/*
* Allocate the assoc context block
*/
pAssocCtx = CommAssocAllocAssoc();
pAssocCtx->SockNo = SockNo;
pAssocCtx->uRemAssocCtx = 0;
pAssocCtx->State_e = COMMASSOC_ASSOC_E_NON_EXISTENT;
pAssocCtx->Role_e = COMMASSOC_ASSOC_E_INITIATOR;
pAssocCtx->Typ_e = CommTyp_e;
pAssocCtx->DlgHdl = *pDlgHdl;
pAssocCtx->RemoteAdd.sin_addr.s_addr = pAdd->Add.IPAdd;
pAssocCtx->nTag = CommAssocTagAlloc(&sTagAssoc,pAssocCtx);
/*
Format the start association message.
The address passed to the formatting function is offset
from the address of the buffer by a LONG so that CommSendAssoc
can store the length of the message in it.
*/
CommAssocFrmStartAssocReq(
pAssocCtx,
AssocMsg + sizeof(LONG),
MsgLen - sizeof(LONG)
);
pDlgCtx->AssocHdl.pEnt = pAssocCtx;
pDlgCtx->AssocHdl.SeqNo = pAssocCtx->Top.SeqNo;
/*
* send the message on the TCP connection
*/
CommSendAssoc(
pAssocCtx->SockNo,
AssocMsg + sizeof(LONG),
MsgLen - sizeof(LONG)
);
/*
Read in the response message
*/
RetStat = CommReadStream(
pAssocCtx->SockNo,
TRUE, // do timed wait
&pTcpMsg,
&BytesRead
);
/*
If the return status is not WINS_SUCCESS or bytes read are 0, then
either it is a disconnect or the read timed out. Raise an exception.
(We should have gotten either a start or a stop assoc. message.
*/
if ((BytesRead != 0) && (RetStat == WINS_SUCCESS))
{
DWORD Opc;
DWORD MsgTyp;
ULONG uNoNeed;
pWinsMem->pMem = pTcpMsg - sizeof(LONG) - COMM_BUFF_HEADER_SIZE;
(++pWinsMem)->pMem = NULL;
/*
* unformat the response
*/
COMM_GET_HEADER_M(pTcpMsg, Opc, uNoNeed, MsgTyp);
/*
* if MsgTyp indicates that it is a start assoc. response
* message, change state of association to Active; return
* success
*/
if (MsgTyp == COMM_START_RSP_ASSOC_MSG)
{
CommAssocUfmStartAssocRsp(
pTcpMsg,
&pAssocCtx->MajVersNo,
&pAssocCtx->MinVersNo,
&pAssocCtx->uRemAssocCtx
);
pAssocCtx->State_e = COMMASSOC_ASSOC_E_ACTIVE;
#if SUPPORT612WINS > 0
//
// If bytes read are less than what a post-beta1
// WINS sends us, it means that it must be a beta1 WINS.
//
if (BytesRead >= (COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE - sizeof(LONG)))
{
#if 0
pAssocCtx->MajVersNo = WINS_BETA2_MAJOR_VERS_NO;
pAssocCtx->MinVersNo = 1; //not used currently
#endif
}
else
{
pAssocCtx->MajVersNo = WINS_BETA1_MAJOR_VERS_NO;
pAssocCtx->MinVersNo = 1; //not used currently
}
#endif
}
//
// Let us free the message that we received
//
ECommFreeBuff(pTcpMsg);
/*
* if opcode indicates that it is a stop assoc. message, do
* cleanup; return failure
*/
if (MsgTyp == COMM_STOP_REQ_ASSOC_MSG)
{
//
// Decrement conn. count
//
CommDecConnCount();
WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
}
}
else // Either Bytes Read are 0 or select timed out or some other error
// occurred
{
WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
DWORD ExcCode = GetExceptionCode();
DBGPRINTEXC("CommAssocSetUpAssoc");
//
// If the exception occurred after the socket was opened, close it
//
if (SockNo != INVALID_SOCKET)
{
CommDisc(SockNo, TRUE); // close the socket
}
//
// if an assoc. ctx block was allocated, free it now
//
if (pAssocCtx != NULL)
{
CommAssocTagFree(&sTagAssoc, pAssocCtx->nTag);
CommAssocDeallocAssoc(pAssocCtx);
}
//
// reraise the exception
//
WINS_HDL_EXC_N_RERAISE_M(WinsMem);
} //end of except {..}
*ppAssocCtx = pAssocCtx;
return;
} //CommAssocSetUpAssoc()
VOID
CommAssocFrmStartAssocReq(
IN PCOMMASSOC_ASSOC_CTX_T pAssocCtx,
IN MSG_T pMsg,
IN MSG_LEN_T MsgLen
)
/*++
Routine Description:
This function is called to format a start association message
Arguments:
pAssocCtx - Association Context block
pMsg - Buffer containing the formatted start assoc. req. msg.
MsgLen - Size of the above buffer
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
CommAssocSetUpAssoc
Side Effects:
Comments:
None
--*/
{
ULONG *pLong = NULL;
/*
The start assoc. message contains the following fields
the assoc handle (ptr field)
Version Number (major and minor) both are 16 bits
Authentication Info (currently nothing)
Association Type (an integer)
*/
pLong = (LPLONG)pMsg;
COMM_SET_HEADER_M(
pLong,
WINS_IS_NOT_NBT, //opcode
0, /*We don't have the remote guy's assoc. ptr yet*/
COMM_START_REQ_ASSOC_MSG //msg type
);
*pLong++ = htonl(pAssocCtx->nTag);
*pLong++ = htonl((WINS_MAJOR_VERS << 16 ) | WINS_MINOR_VERS);
*pLong = htonl(pAssocCtx->Typ_e); //assoc type
return;
}
VOID
CommAssocUfmStartAssocReq(
IN MSG_T pMsg,
OUT PCOMM_TYP_E pAssocTyp_e,
OUT LPDWORD pMajorVer,
OUT LPDWORD pMinorVer,
OUT ULONG *puRemAssocCtx
)
/*++
Routine Description:
This function parses the start association message that arrives on
a TCP connection and returns with the relevant information
Arguments:
pMsg -- Message to be unformatted
pAssocTyp_e -- Type of assoc (i.e from who -- replicator, COMSYS, etc)
pMajorVer -- Major version no.
pMinorVer -- Minor version no.
puRemAssocCtx -- ptr to assoc. ctx block of remote WINS
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
ProcTcpMsg
Side Effects:
Comments:
None
--*/
{
/*
Increment pLong past the comm header
*/
LPLONG pLong = (LPLONG)(pMsg + COMM_HEADER_SIZE);
LONG lTmp;
*puRemAssocCtx = ntohl(*pLong++);
//ptr to assoc. ctx at remote WINS
/*
* Get the long that contains the major and minor version numbers
*/
lTmp = ntohl(*pLong++);
*pMajorVer = lTmp >> 16; //Major vers. no.
*pMinorVer = lTmp & 0x0ff; //Minor vers. no.
*pAssocTyp_e = ntohl(*pLong); /*Msg type (from who -- COMSYS,
Replicator
*/
return;
}
VOID
CommAssocFrmStopAssocReq(
IN PCOMMASSOC_ASSOC_CTX_T pAssocCtx,
IN MSG_T pMsg,
IN MSG_LEN_T MsgLen,
IN COMMASSOC_STP_RSN_E StopRsn_e
)
/*++
Routine Description:
This function formats a stop association message
Arguments:
pAssocCtx -- Assoc. Ctx block.
pMsg -- Buffer containing the formatted stop assoc. req. msg.
MsgLen -- Length of above buffer
StopRsn_e -- Reason why the association is being stopped
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
CommAssocSetUpAssoc
Side Effects:
Comments:
None
--*/
{
unsigned long *pLong = NULL;
/*
The stop assoc. message contains the following fields
the reason for the stop/abort.
*/
pLong = (LPLONG)pMsg;
COMM_SET_HEADER_M(
pLong,
WINS_IS_NOT_NBT,
pAssocCtx->uRemAssocCtx,
COMM_STOP_REQ_ASSOC_MSG
);
*pLong = htonl(StopRsn_e);
return;
}
VOID
CommUfmStopAssocReq(
IN MSG_T pMsg,
OUT PCOMMASSOC_STP_RSN_E pStopRsn_e
)
/*++
Routine Description:
This function formats a stop association message
Arguments:
pMsg - Message containing the stop assoc. req.
pStopRsn_e - reason why the association was stopped
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
ProcTcpMsg
Side Effects:
Comments:
None
--*/
{
/*
Increment pLong past the comm header
*/
LPLONG pLong = (LPLONG)(pMsg + COMM_HEADER_SIZE);
*pStopRsn_e = ntohl(*pLong);
return;
}
VOID
CommAssocFrmStartAssocRsp(
IN PCOMMASSOC_ASSOC_CTX_T pAssocCtx,
IN MSG_T pMsg,
IN MSG_LEN_T MsgLen
)
/*++
Routine Description:
This function is called to format a start association response message
Arguments:
pAssocCtx -- Assoc. ctx block
pMsg -- Buffer containing the formatted start assoc. rsp. msg.
MsgLen -- Length of above buffer
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
ProcTcpMsg
Side Effects:
Comments:
None
--*/
{
LPLONG pLong = NULL;
/*
The start assoc. message contains the following fields
the assoc handle (ptr field)
Authentication Info (currently nothing)
*/
pLong = (unsigned long *)pMsg;
COMM_SET_HEADER_M(
pLong,
WINS_IS_NOT_NBT,
pAssocCtx->uRemAssocCtx,
COMM_START_RSP_ASSOC_MSG
);
*pLong++ = htonl(pAssocCtx->nTag);
*pLong = htonl((WINS_MAJOR_VERS << 16 ) | WINS_MINOR_VERS);
return;
}
VOID
CommAssocUfmStartAssocRsp(
IN MSG_T pMsg,
OUT LPDWORD pMajorVer,
OUT LPDWORD pMinorVer,
OUT ULONG *puRemAssocCtx
)
/*++
Routine Description:
This function formats a stop association message
Arguments:
pMsg - Buffer containing the Start Assoc. rsp. message
puRemAssocCtx - ptr to remote assoc. ctx block.
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
CommAssocSetUpAssoc
Side Effects:
Comments:
None
--*/
{
/*
Increment pLong past the comm header
*/
LPLONG pLong = (LPLONG)(pMsg + COMM_HEADER_SIZE);
LONG lTmp;
*puRemAssocCtx = ntohl(*pLong++);
/*
* Get the long that contains the major and minor version numbers
*/
lTmp = ntohl(*pLong);
*pMajorVer = lTmp >> 16; //Major vers. no.
*pMinorVer = lTmp & 0xff; //Minor vers. no.
return;
}
LPVOID
CommAssocAllocAssoc(
VOID
)
/*++
Routine Description:
This function allocates an association
Arguments:
None
Externals Used:
None
Return Value:
Success status codes --
Error status codes --
Error Handling:
Called by:
ECommAssocAllocAssoc
Side Effects:
Comments:
None
--*/
{
return(
AllocEnt(
CommAssocAssocHeapHdl,
&sAssocQueHd,
&sAssocListCrtSec,
&sAssocSeqNo,
COMMASSOC_ASSOC_DS_SZ,
&sNoOfAssocCrtSec
)
);
}
LPVOID
CommAssocAllocDlg(
VOID
)
/*++
Routine Description:
This function allocates a dialogue context block
Arguments:
None
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
ECommStartDlg, ProcTcpMsg
Side Effects:
Comments:
None
--*/
{
return(
AllocEnt(
CommAssocDlgHeapHdl,
&sDlgQueHd,
&sDlgListCrtSec,
&sDlgSeqNo,
COMMASSOC_DLG_DS_SZ,
&sNoOfDlgCrtSec
)
);
}
LPVOID
AllocEnt(
IN HANDLE HeapHdl,
IN PQUE_HD_T pQueHd,
IN LPCRITICAL_SECTION pCrtSec,
IN LPDWORD pSeqNoCntr,
IN DWORD Size,
IN LPDWORD pCntOfCrtSec
)
/*++
Routine Description:
This function is used to allocate a ctx. block (association or dlg).
Arguments:
HeapHdl - Heap from where the alloc. muxt be done
pQueHd - Head of free list queue
pCrtSec - Critical section protecting the above queue
pSeqNoCtr - Counter value used to stamp the buffer if it is allocated
as versus when it is taken from the free list
Size - Size of buffer to allocate
Externals Used:
None
Return Value:
Ptr to the block allocated
Error Handling:
Called by:
CommAssocAllocAssoc, CommAssocAllocDlg
Side Effects:
Comments:
--*/
{
PCOMM_TOP_T pTop;
// DWORD Error;
PLIST_ENTRY pHead = &pQueHd->Head;
EnterCriticalSection(pCrtSec);
try {
if (IsListEmpty(pHead))
{
pTop = WinsMscHeapAlloc(
HeapHdl,
Size
);
#ifdef WINSDBG
IF_DBG(HEAP_CNTRS)
{
EnterCriticalSection(&NmsHeapCrtSec);
NmsHeapAllocForList++;
LeaveCriticalSection(&NmsHeapCrtSec);
}
#endif
//
// Init the critical section in the block we just allocated.
//
InitializeCriticalSection(&pTop->CrtSec);
pTop->fCrtSecInited = TRUE;
(*pCntOfCrtSec)++;
pTop->SeqNo = (*pSeqNoCntr)++;
}
else
{
pTop = (PCOMM_TOP_T)RemoveTailList(pHead);
//
// Just took a free entry. Decrement count
//
if (!pTop->fCrtSecInited)
{
InitializeCriticalSection(&pTop->CrtSec);
pTop->fCrtSecInited = TRUE;
(*pCntOfCrtSec)++;
}
}
}
finally {
LeaveCriticalSection(pCrtSec);
}
return(pTop);
}
VOID
DeallocEnt(
IN HANDLE HeapHdl,
IN PQUE_HD_T pQueHd,
IN LPCRITICAL_SECTION pCrtSec,
IN LPDWORD pSeqNoCntr,
IN LPVOID pEnt,
IN LPDWORD pCntOfCrtSec
)
/*++
Routine Description:
The function deallocates a context block
Arguments:
pQueHd - Head of free list queue
pCrtSec - Critical section protecting the above queue
pSeqNoCtr - Counter value used to stamp the buffer before putting
it in the queue.
heap
pEnt - entity to be deallocated
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
CommAssocDeallocDlg, CommAssocDeallocAssoc
Side Effects:
Comments:
None
--*/
{
PCOMM_TOP_T pTop;
PLIST_ENTRY pHead = &pQueHd->Head;
UNREFERENCED_PARAMETER(HeapHdl);
pTop = pEnt;
EnterCriticalSection(pCrtSec);
try {
(*pSeqNoCntr)++;
pTop->SeqNo = *pSeqNoCntr;
InsertTailList(pHead, &pTop->Head);
//
// Delete critical section if necessary to save on non-paged pool
//
if (*pCntOfCrtSec > COMM_FREE_COMM_HDL_THRESHOLD)
{
//
//
// We want to keep the non-paged pool within a limit.
// Deallocate this block. This ensures that we will never
// have more than COMM_FREE_COMM_HDL_THRESHOLD no of dlgs and
// assocs in the free list.
//
DeleteCriticalSection(&pTop->CrtSec);
(*pCntOfCrtSec)--;
pTop->fCrtSecInited = FALSE;
}
} //end of try
finally {
LeaveCriticalSection(pCrtSec);
}
return;
}
VOID
CommAssocDeallocAssoc(
IN LPVOID pAssocCtx
)
/*++
Routine Description:
The function deallocates an association context block
Arguments:
pAssocCtx - Buffer (assoc. ctx block) to deallocate
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
CommAssocDeleteAssocInTbl, CommAssocSetUpAssoc, CommEndAssoc
Side Effects:
Comments:
None
--*/
{
DeallocEnt(
CommAssocAssocHeapHdl,
&sAssocQueHd,
&sAssocListCrtSec,
&sAssocSeqNo,
pAssocCtx,
&sNoOfAssocCrtSec
);
return;
}
VOID
CommAssocDeallocDlg(
IN LPVOID pDlgCtx
)
/*++
Routine Description:
The function deallocates a dialogue context block
Arguments:
pDlgCtx - Buffer (dlg. ctx block) to deallocate
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
RtlDeleteElementGenericTable
Side Effects:
Comments:
None
--*/
{
DeallocEnt(
CommAssocDlgHeapHdl,
&sDlgQueHd,
&sDlgListCrtSec,
&sDlgSeqNo,
pDlgCtx,
&sNoOfDlgCrtSec
);
return;
}
VOID
CommAssocInit(
VOID
)
/*++
Routine Description:
The function is called at init time to initialize the critical sections
and queues for RESPONDER associations and dialogues pertaining to
incoming request datagrams.
Arguments:
None
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
CommInit
Side Effects:
Comments:
None
--*/
{
//
// Initialize the critical sections that guard the lists of
// associations and non-udp dialogues
//
InitializeCriticalSection(&sAssocListCrtSec);
InitializeCriticalSection(&sDlgListCrtSec);
//
// Initialize the critical section for the UDP table
//
InitializeCriticalSection(&sUdpDlgTblCrtSec);
//
// Initialize the list heads for the lists of associations
// and non-udp dialogues
//
InitializeListHead(&sAssocQueHd.Head);
InitializeListHead(&sDlgQueHd.Head);
//
// Initialize the list head for the list of active responder
// associations
//
InitializeListHead(&sRspAssocQueHd.Head);
InitializeListHead(&sUdpDlgHead);
// Initialize the tag variable
InitializeCriticalSection(&sTagAssoc.crtSection);
sTagAssoc.nIdxLimit = 0;
sTagAssoc.nMaxIdx = 0;
sTagAssoc.ppStorage = NULL;
sTagAssoc.pTagPool = NULL;
return;
}
PCOMMASSOC_DLG_CTX_T
CommAssocInsertUdpDlgInTbl(
IN PCOMMASSOC_DLG_CTX_T pCtx,
OUT LPBOOL pfNewElem
)
/*++
Routine Description:
This function is called to insert a UDP dlg into the CommUdpNbtDlgTable.
Arguments:
pDlgCtx - Dlg Ctx Block
pfNewElem - flag indicating whether it is a new element
Externals Used:
None
Return Value:
Ptr to the dlg ctx block
Error Handling:
Called by:
Side Effects:
Comments:
None
--*/
{
PCOMMASSOC_DLG_CTX_T pDlgCtx;
EnterCriticalSection(&sUdpDlgTblCrtSec);
try {
pDlgCtx = WINSMSC_INSERT_IN_TBL_M(
&CommUdpNbtDlgTable,
pCtx,
sizeof(COMMASSOC_DLG_CTX_T),
(PBOOLEAN)pfNewElem
);
}
finally {
LeaveCriticalSection(&sUdpDlgTblCrtSec);
}
return(pDlgCtx);
}
VOID
CommAssocDeleteUdpDlgInTbl(
IN PCOMMASSOC_DLG_CTX_T pDlgCtx
)
/*++
Routine Description:
This function is called to insert a UDP dlg into the CommUdpNbtDlgTable.
Arguments:
pDlgCtx - Dlg Ctx Block
Externals Used:
None
Return Value:
Ptr to the dlg ctx block
Error Handling:
Called by:
Side Effects:
Comments:
None
--*/
{
BOOLEAN fRetVal;
EnterCriticalSection(&sUdpDlgTblCrtSec);
try {
DBGPRINT0(FLOW, "CommAssocDeleteUdpDlgInTbl:Deleting dlg from table\n");
fRetVal = WINSMSC_DELETE_FRM_TBL_M(
&CommUdpNbtDlgTable,
pDlgCtx
);
if (fRetVal == (BOOLEAN)FALSE)
{
DBGPRINT0(ERR, "CommAssocDeleteUdpDlgInTbl:Could not delete dlg in table\n");
}
}
finally {
LeaveCriticalSection(&sUdpDlgTblCrtSec);
}
return;
}
LPVOID
CommAssocCreateAssocInTbl(
SOCKET SockNo
)
/*++
Routine Description:
This function is called to create an association ctx block for
a tcp connection
Arguments:
SockNo - Socket # of socket mapped to the TCP connection
Externals Used:
sRspAssocQueHd
Return Value:
ptr to the associaton context block created for the TCP connection
Error Handling:
Called by:
MonTcp (TCP listener thread)
Side Effects:
Comments:
None
--*/
{
PCOMMASSOC_ASSOC_CTX_T pAssocCtx;
//
// Allocate/(grab from free list) an association
//
pAssocCtx = CommAssocAllocAssoc();
pAssocCtx->SockNo = SockNo;
pAssocCtx->nTag = CommAssocTagAlloc(&sTagAssoc,pAssocCtx);
CommAssocInsertAssocInTbl(pAssocCtx);
return(pAssocCtx);
}
VOID
CommAssocDeleteAssocInTbl(
PCOMMASSOC_ASSOC_CTX_T pAssocCtx
)
/*++
Routine Description:
This function is called to delete an association context block from
the table of active responder associations. The association ctx.
block is deleted from the table and also deallocated (i.e. put
in the free list)
Arguments:
pAssocCtx - Association context block to delete from a table
Externals Used:
sRspAssocQueHd
Return Value:
None
Error Handling:
Called by:
DelAssoc
Side Effects:
Comments:
None
--*/
{
//
// Unlink the association
//
COMMASSOC_UNLINK_RSP_ASSOC_M(pAssocCtx);
//
// Dealloc the assoc. so that it can be reused for some other
// TCP connection
//
CommAssocTagFree(&sTagAssoc, pAssocCtx->nTag);
CommAssocDeallocAssoc(pAssocCtx);
return;
}
LPVOID
CommAssocLookupAssoc(
SOCKET SockNo
)
/*++
Routine Description:
This function is called to lookup an association context block
corresponding to a socket.
Arguments:
SockNo - Socket # of socket whose association context block is
desired
Externals Used:
sRspAssocQueHd
Return Value:
ptr to assoc ctx block or NULL if there is no assoc. mapped to the
socket
Error Handling:
Called by:
DelAssoc
Side Effects:
Comments:
None
--*/
{
PCOMMASSOC_ASSOC_CTX_T pTmp =
(PCOMMASSOC_ASSOC_CTX_T)sRspAssocQueHd.Head.Flink;
//
// If list is empty, return NULL
//
if (IsListEmpty(&sRspAssocQueHd.Head))
{
return(NULL);
}
//
// Search for the assoc. mapped to socket
//
for(
;
pTmp != (PCOMMASSOC_ASSOC_CTX_T)&sRspAssocQueHd ;
pTmp = NEXT_ASSOC_M(pTmp)
)
{
if (pTmp->SockNo == SockNo)
{
return(pTmp);
}
}
//
// There is no assoc. mapped to socket SockNo. Return NULL
//
return(NULL);
}
VOID
CommAssocInsertAssocInTbl(
PCOMMASSOC_ASSOC_CTX_T pAssocCtx
)
/*++
Routine Description:
This function is called to insert an association at the head
of the list of associations currently being monitored
Arguments:
pAssocCtx - Assoc. Ctx. Block
Externals Used:
None
Return Value:
None
Error Handling:
Called by:
CommAssocCreateAssocInTbl, ECommMonDlg
Side Effects:
Comments:
Change to a macro
--*/
{
//
// Insert at the head of the list of active responder associations
//
// Insertion is done at the head of the list in order to optimize
// the lookup of the association when the first message comes on
// it from a remote WINS. Since the first message follows on the
// heels of the connection set up, the search for the association
// which starts from the head is optimized.
//
InsertHeadList(&sRspAssocQueHd.Head, &pAssocCtx->Top.Head);
return;
}
ULONG
CommAssocTagAlloc(
PCOMMASSOC_TAG_POOL_T pTag,
LPVOID pPtrValue
)
/*++
Routine Description:
This function is used to create a mapping between a generic pointer (32bit/64bit)
and a 32bit tag.
Arguments:
pPtrValue - generic pointer value
Externals Used:
TBD
Return Value:
None
--*/
{
// a try..finally block is needed just in case the memory reallocation would raise.
// an exception. In this case, before leaving the try block and the function, the finally
// block gets executed and leaves cleanly the tag critical section. If this happens
// the exception will still be passed up the chain (since there is no except block present).
try
{
ULONG newTag;
DBGPRINT0(FLOW, "Entering CommAssocTagAlloc.\n");
EnterCriticalSection(&(pTag->crtSection));
// if nMaxIdx is 0 this means there is no entry available in the Tag pool
if (pTag->nMaxIdx == 0)
{
UINT i;
// tag pool needs to be enlarged. We might want to check if the buffers have not reached
// 2^32 entries (highly unlikely)
ULONG nNewLimit = pTag->nIdxLimit + COMMASSOC_TAG_CHUNK;
// realloc failures raise exceptions.
if (pTag->nIdxLimit == 0)
{
pTag->ppStorage = (LPVOID*)WinsMscHeapAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(LPVOID));
pTag->pTagPool = (ULONG*)WinsMscHeapAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(ULONG));
}
else
{
WinsMscHeapReAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(LPVOID), (LPVOID)&(pTag->ppStorage));
WinsMscHeapReAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(ULONG), &(pTag->pTagPool));
}
// mark the newly allocated entries as being free for use
pTag->nMaxIdx = COMMASSOC_TAG_CHUNK;
for (i = 0; i < pTag->nMaxIdx; i++)
{
// tags should be in the range 1... hence the pre-increment op here.
pTag->pTagPool[i] = ++pTag->nIdxLimit;
}
}
// at this point pTag->nMaxIdx entries are free for use and pTag->nMaxIdx is guaranteed
// to be greater than 0. The entries free for use have the indices in pTag->pTagPool[0..pTag->nMaxIdx-1]
// get the newly allocated tag
newTag = pTag->pTagPool[--pTag->nMaxIdx];
// map the pointer to this tag into the pointer storage
pTag->ppStorage[newTag-1] = pPtrValue;
#ifdef WINSDBG
// robust programming
pTag->pTagPool[pTag->nMaxIdx] = 0;
#endif
DBGPRINT2(REPL, "TagAlloc: tag for %p is %08x.\n", pPtrValue, newTag);
// return the newly allocated tag
return newTag;
}
finally
{
LeaveCriticalSection(&(pTag->crtSection));
DBGPRINT0(FLOW, "Leaving CommAssocTagAlloc.\n");
}
}
VOID
CommAssocTagFree(
PCOMMASSOC_TAG_POOL_T pTag,
ULONG nTag
)
/*++
Routine Description:
This function is used to free a mapping between a generic pointer (32bit/64bit)
and a 32bit tag.
Arguments:
nTag - tag value to be freed.
Externals Used:
TBD
Return Value:
None
--*/
{
DBGPRINT0(FLOW, "Entering CommAssocTagFree.\n");
EnterCriticalSection(&(pTag->crtSection));
#ifdef WINSDBG
// robust programming - just set the corresponding pointer from the storage to NULL
pTag->ppStorage[nTag-1] = NULL;
#endif
// just mark the nTag index as being free for use
pTag->pTagPool[pTag->nMaxIdx++] = nTag;
DBGPRINT1(REPL, "TagFree for tag %08x.\n", nTag);
// 'Free' has to match with 'Alloc' so nMaxIdx can't exceed under no circumstances nIdxLimit
ASSERT (pTag->nMaxIdx <= pTag->nIdxLimit);
LeaveCriticalSection(&(pTag->crtSection));
DBGPRINT0(FLOW, "Leaving CommAssocTagFree.\n");
}
LPVOID
CommAssocTagMap(
PCOMMASSOC_TAG_POOL_T pTag,
ULONG nTag
)
/*++
Routine Description:
This function is used to retrieve a generic pointer (32bit/64bit) that
is uniquely identified through a 32bit tag.
Arguments:
nTag - tag value that identifies the generic pointer.
Externals Used:
TBD
Return Value:
None
--*/
{
DBGPRINT0(FLOW, "Entering CommAssocTagMap.\n");
DBGPRINT2(REPL, "TagMap for tag %08x is %p.\n",
nTag,
nTag == 0 ? NULL : pTag->ppStorage[nTag-1]);
// the indices that were given have to fall in the range 0..pTag->nIdxLimit
ASSERT (nTag <= pTag->nIdxLimit);
DBGPRINT0(FLOW, "Leaving CommAssocTagMap.\n");
// return the (64bit) value from pStorage, associated with the nTag provided
return nTag == 0 ? NULL : pTag->ppStorage[nTag-1];
}