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.
510 lines
22 KiB
510 lines
22 KiB
/**MOD+**********************************************************************/
|
|
/* Module: ncapi.cpp */
|
|
/* */
|
|
/* Purpose: Node Controller API/callbacks */
|
|
/* */
|
|
/* Copyright(C) Microsoft Corporation 1997-1999 */
|
|
/* */
|
|
/****************************************************************************/
|
|
|
|
#include <adcg.h>
|
|
extern "C" {
|
|
#define TRC_GROUP TRC_GROUP_NETWORK
|
|
#define TRC_FILE "ncapi"
|
|
#include <atrcapi.h>
|
|
}
|
|
|
|
#include "autil.h"
|
|
#include "nc.h"
|
|
#include "cd.h"
|
|
#include "nl.h"
|
|
#include "mcs.h"
|
|
#include "cchan.h"
|
|
|
|
/****************************************************************************/
|
|
/* MCS user data header bytes. */
|
|
/****************************************************************************/
|
|
const DCINT8 ncMCSHeader[NC_MCS_HDRLEN] =
|
|
{
|
|
0x00, 0x05, 0x00, 0x14, 0x7C, 0x00, 0x01
|
|
};
|
|
|
|
/****************************************************************************/
|
|
/* GCC CreateConferenceRequest PDU body */
|
|
/****************************************************************************/
|
|
const DCINT8 ncGCCBody[NC_GCC_REQLEN] =
|
|
{
|
|
0x00, /* extension bit; 3 * choice bits; 3 * optional fields */
|
|
0x08, /* 5*Optional (user data only);2*ConfName options;length bit 0 */
|
|
0x00, /* Length bits 1-7; pad bit */
|
|
0x10, /* Conference name (numeric) = "1"; locked; listed; */
|
|
0x00, /* conductible; 2*Terminate =automatic; pad */
|
|
0x01, /* Number of UserData fields */
|
|
'\xC0', /* optional;choice;6*size (0=>4 octets) */
|
|
0x00 /* 2* size; 6* pad */
|
|
};
|
|
|
|
|
|
CNC::CNC(CObjs* objs)
|
|
{
|
|
_pClientObjects = objs;
|
|
}
|
|
|
|
CNC::~CNC()
|
|
{
|
|
}
|
|
|
|
|
|
#ifdef OS_WIN32
|
|
/**PROC+*********************************************************************/
|
|
/* Name: NC_Main */
|
|
/* */
|
|
/* Purpose: Receiver Thread message loop */
|
|
/* */
|
|
/* Returns: None */
|
|
/* */
|
|
/* Params: None */
|
|
/* */
|
|
/**PROC-*********************************************************************/
|
|
DCVOID DCAPI CNC::NC_Main(DCVOID)
|
|
{
|
|
MSG msg;
|
|
|
|
DC_BEGIN_FN("NC_Main");
|
|
|
|
TRC_NRM((TB, _T("Receiver Thread initialization")));
|
|
|
|
#if defined(OS_WINCE) && defined(WINCE_USEBRUSHCACHE)
|
|
BrushCacheInitialize();
|
|
#endif
|
|
|
|
|
|
_pCd = _pClientObjects->_pCdObject;
|
|
_pCc = _pClientObjects->_pCcObject;
|
|
_pMcs = _pClientObjects->_pMCSObject;
|
|
_pUt = _pClientObjects->_pUtObject;
|
|
_pRcv = _pClientObjects->_pRcvObject;
|
|
_pNl = _pClientObjects->_pNlObject;
|
|
_pSl = _pClientObjects->_pSlObject;
|
|
_pUi = _pClientObjects->_pUiObject;
|
|
_pChan = _pClientObjects->_pChanObject;
|
|
|
|
NC_Init();
|
|
|
|
TRC_NRM((TB, _T("Start Receiver Thread message loop")));
|
|
while (GetMessage (&msg, NULL, 0, 0))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
TRC_NRM((TB, _T("Exit Receiver Thread message loop")));
|
|
NC_Term();
|
|
|
|
#if defined(OS_WINCE) && defined(WINCE_USEBRUSHCACHE)
|
|
BrushCacheUninitialize();
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/* This is the end of the Receiver Thread. */
|
|
/************************************************************************/
|
|
TRC_NRM((TB, _T("Receiver Thread terminates")));
|
|
|
|
DC_END_FN();
|
|
|
|
return;
|
|
|
|
} /* NC_Main */
|
|
#endif /* OS_WIN32 */
|
|
|
|
|
|
/**PROC+*********************************************************************/
|
|
/* Name: NC_Init */
|
|
/* */
|
|
/* Purpose: Initialize the Node Controller */
|
|
/* */
|
|
/* Returns: None */
|
|
/* */
|
|
/* Params: None */
|
|
/* */
|
|
/**PROC-*********************************************************************/
|
|
DCVOID DCAPI CNC::NC_Init(DCVOID)
|
|
{
|
|
DC_BEGIN_FN("NC_Init");
|
|
|
|
/************************************************************************/
|
|
/* Initialize global data. */
|
|
/************************************************************************/
|
|
DC_MEMSET(&_NC, 0, sizeof(_NC));
|
|
|
|
/************************************************************************/
|
|
/* Register with CD, to receive messages. */
|
|
/************************************************************************/
|
|
_pCd->CD_RegisterComponent(CD_RCV_COMPONENT);
|
|
|
|
/************************************************************************/
|
|
/* Initialize lower layers. */
|
|
/************************************************************************/
|
|
_pMcs->MCS_Init();
|
|
|
|
/************************************************************************/
|
|
/* Initialize virtual channel stuff */
|
|
/************************************************************************/
|
|
_pChan->ChannelOnInitializing();
|
|
|
|
TRC_NRM((TB, _T("NC successfully initialized")));
|
|
|
|
/************************************************************************/
|
|
/* Tell the Core that we are initialized */
|
|
/************************************************************************/
|
|
_pNl->_NL.callbacks.onInitialized(_pSl);
|
|
|
|
_pChan->ChannelOnInitialized();
|
|
|
|
DC_END_FN();
|
|
return;
|
|
|
|
} /* NC_Init */
|
|
|
|
|
|
/**PROC+*********************************************************************/
|
|
/* Name: NC_Term */
|
|
/* */
|
|
/* Purpose: Terminate the Node Controller */
|
|
/* */
|
|
/* Returns: None */
|
|
/* */
|
|
/* Params: None */
|
|
/* */
|
|
/**PROC-*********************************************************************/
|
|
DCVOID DCAPI CNC::NC_Term(DCVOID)
|
|
{
|
|
DC_BEGIN_FN("NC_Term");
|
|
|
|
/************************************************************************/
|
|
/* Tell core that we are terminating */
|
|
/************************************************************************/
|
|
_pNl->_NL.callbacks.onTerminating(_pSl);
|
|
|
|
_pChan->ChannelOnTerminating();
|
|
|
|
/************************************************************************/
|
|
/* Terminate lower NL layers. */
|
|
/************************************************************************/
|
|
_pMcs->MCS_Term();
|
|
|
|
/************************************************************************/
|
|
/* Unregister with CD */
|
|
/************************************************************************/
|
|
_pCd->CD_UnregisterComponent(CD_RCV_COMPONENT);
|
|
|
|
DC_END_FN();
|
|
return;
|
|
|
|
} /* NC_Term */
|
|
|
|
|
|
|
|
/**PROC+*********************************************************************/
|
|
/* Name: NC_Connect */
|
|
/* */
|
|
/* Purpose: Connect to the requested Server by calling MCS */
|
|
/* */
|
|
/* Returns: None */
|
|
/* */
|
|
/* Params: IN pData - user data (SL + Core) */
|
|
/* IN dataLen - length */
|
|
/* */
|
|
/* Operation: Send an MCSConnectProvider request with a GCC Create */
|
|
/* Conference request encoded in the user data. The encoding is */
|
|
/* as follows: */
|
|
/* */
|
|
/* number of bytes value */
|
|
/* =============== ===== */
|
|
/* NC_MCS_HDRLEN MCS header */
|
|
/* 1 or 2 Total GCC PDU length */
|
|
/* NC_GCC_REQLEN GCC CreateConference PDU body */
|
|
/* 4 H221 key */
|
|
/* 1 or 2 length of GCC user data */
|
|
/* ? GCC user data */
|
|
/* */
|
|
/**PROC-*********************************************************************/
|
|
DCVOID DCAPI CNC::NC_Connect(PDCVOID pData, DCUINT dataLen)
|
|
{
|
|
PNC_CONNECT_DATA pConn;
|
|
PDCUINT8 pAddress;
|
|
PDCUINT8 pProtocol;
|
|
PDCUINT8 pUserData;
|
|
DCUINT userDataLen;
|
|
DCUINT mcsUserDataLen;
|
|
DCUINT gccPDULen;
|
|
PDCUINT8 pGCCPDU;
|
|
DCUINT8 mcsUserData[NC_GCCREQ_MAX_PDULEN];
|
|
RNS_UD_CS_NET netUserData;
|
|
PCHANNEL_DEF pVirtualChannels;
|
|
BOOL bInitateConnect;
|
|
|
|
DC_BEGIN_FN("NC_Connect");
|
|
|
|
DC_IGNORE_PARAMETER(dataLen);
|
|
|
|
/************************************************************************/
|
|
/* We are about to dereference pData as NC_CONNECT_DATA. Thus, we must */
|
|
/* have at least that much in our PDU. */
|
|
/************************************************************************/
|
|
if (dataLen < ((ULONG)FIELDOFFSET(NC_CONNECT_DATA, userDataLen) +
|
|
(ULONG)FIELDSIZE(NC_CONNECT_DATA, userDataLen)))
|
|
{
|
|
DCUINT errorCode;
|
|
TRC_ABORT((TB, _T("Not enough data for NC_CONNECT_DATA struct: %u"), dataLen));
|
|
|
|
/************************************************************************/
|
|
/* We haven't even called into the MCS layer yet, so the disconnect */
|
|
/* is a bit tricky. Uninitialize our layer and bubble up. */
|
|
/************************************************************************/
|
|
errorCode = NL_MAKE_DISCONNECT_ERR(NL_ERR_NCNOUSERDATA);
|
|
NC_OnMCSDisconnected(errorCode);
|
|
DC_QUIT;
|
|
}
|
|
|
|
pConn = (PNC_CONNECT_DATA)pData;
|
|
|
|
bInitateConnect = pConn->bInitateConnect;
|
|
|
|
if( bInitateConnect )
|
|
{
|
|
pAddress = pConn->data;
|
|
TRC_ASSERT((pConn->addressLen > 0),
|
|
(TB, _T("Invalid address length")));
|
|
}
|
|
else
|
|
{
|
|
pAddress = NULL;
|
|
TRC_ASSERT((pConn->addressLen == 0),
|
|
(TB, _T("Invalid address length %u"), pConn->addressLen));
|
|
}
|
|
|
|
pProtocol = pConn->data + pConn->addressLen;
|
|
pUserData = pConn->data + pConn->addressLen + pConn->protocolLen;
|
|
|
|
|
|
/************************************************************************/
|
|
/* Verify that pUserdata sits within the data passed in, since */
|
|
/* we just get the pointer from an offset specified in the packet. */
|
|
/************************************************************************/
|
|
if (!IsContainedPointer(pData,dataLen,pUserData))
|
|
{
|
|
DCUINT errorCode;
|
|
TRC_ABORT((TB, _T("Invalid offset in data (pConn->addressLen): %u"), pConn->addressLen));
|
|
|
|
/************************************************************************/
|
|
/* We haven't even called into the MCS layer yet, so the disconnect */
|
|
/* is a bit tricky. Uninitialize our layer and bubble up. */
|
|
/************************************************************************/
|
|
errorCode = NL_MAKE_DISCONNECT_ERR(NL_ERR_NCNOUSERDATA);
|
|
NC_OnMCSDisconnected(errorCode);
|
|
DC_QUIT;
|
|
}
|
|
|
|
if( bInitateConnect )
|
|
{
|
|
TRC_DBG((TB, _T("Server address %s"), pProtocol));
|
|
}
|
|
else
|
|
{
|
|
TRC_DBG((TB, _T("Server address : not initiate connection%s")));
|
|
}
|
|
|
|
TRC_DBG((TB, _T("Protocol %s"), pProtocol));
|
|
TRC_DBG((TB, _T("User data length %u"), pConn->userDataLen));
|
|
TRC_DATA_NRM("User data from Core+SL", pUserData, pConn->userDataLen);
|
|
|
|
/************************************************************************/
|
|
/* Get Virtual Channel user data */
|
|
/************************************************************************/
|
|
userDataLen = pConn->userDataLen;
|
|
|
|
_pChan->ChannelOnConnecting(&pVirtualChannels, &(netUserData.channelCount));
|
|
|
|
TRC_NRM((TB, _T("%d virtual channels"), netUserData.channelCount));
|
|
if (netUserData.channelCount != 0)
|
|
{
|
|
netUserData.header.type = RNS_UD_CS_NET_ID;
|
|
netUserData.header.length = (DCUINT16)(sizeof(RNS_UD_CS_NET) +
|
|
(netUserData.channelCount * sizeof(CHANNEL_DEF)));
|
|
pConn->userDataLen += netUserData.header.length;
|
|
TRC_NRM((TB, _T("User data length (NET/total): %d/%d"),
|
|
netUserData.header.length, pConn->userDataLen));
|
|
}
|
|
|
|
TRC_ASSERT((pConn->userDataLen <= NC_MAX_UDLEN),
|
|
(TB, _T("Too much userdata (%u)"), pConn->userDataLen));
|
|
|
|
/************************************************************************/
|
|
/* Work out the length of the GCC PDU: Fixed body + H221 Key + */
|
|
/* userDataLength (1 or 2) + user Data */
|
|
/************************************************************************/
|
|
gccPDULen = NC_GCC_REQLEN + H221_KEY_LEN + 1 + pConn->userDataLen;
|
|
if (pConn->userDataLen >= 128)
|
|
{
|
|
TRC_DBG((TB, _T("Two byte GCC PDU length field")));
|
|
gccPDULen++;
|
|
}
|
|
TRC_DBG((TB, _T("GCC PDU Length %u"), gccPDULen));
|
|
|
|
/************************************************************************/
|
|
/* Write fixed MCS header */
|
|
/************************************************************************/
|
|
pGCCPDU = &(mcsUserData[0]);
|
|
DC_MEMCPY(pGCCPDU, ncMCSHeader, NC_MCS_HDRLEN);
|
|
pGCCPDU += NC_MCS_HDRLEN;
|
|
|
|
/************************************************************************/
|
|
/* SECURITY: Note that the first few fields that we write into pGCCPDU */
|
|
/* don't have to be validated for buffer overruns. This is because */
|
|
/* they are fixed-size, and pGCCPDU points to a fixed-size buffer. */
|
|
/* The first variable-length field that is written into this buffer is */
|
|
/* pUserData (len==userDataLen), which is below. */
|
|
/************************************************************************/
|
|
|
|
if (gccPDULen < 128)
|
|
{
|
|
/********************************************************************/
|
|
/* single length byte */
|
|
/********************************************************************/
|
|
*pGCCPDU++ = (DCUINT8)gccPDULen;
|
|
}
|
|
else
|
|
{
|
|
/********************************************************************/
|
|
/* two length bytes */
|
|
/********************************************************************/
|
|
*pGCCPDU++ = (DCUINT8)((gccPDULen >> 8) | 0x0080);
|
|
*pGCCPDU++ = (DCUINT8)(gccPDULen & 0x00FF);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Fixed GCC PDU body */
|
|
/************************************************************************/
|
|
DC_MEMCPY(pGCCPDU, ncGCCBody, NC_GCC_REQLEN);
|
|
pGCCPDU += NC_GCC_REQLEN;
|
|
|
|
/************************************************************************/
|
|
/* H221 key */
|
|
/************************************************************************/
|
|
DC_MEMCPY(pGCCPDU, CLIENT_H221_KEY, H221_KEY_LEN);
|
|
pGCCPDU += H221_KEY_LEN;
|
|
|
|
/************************************************************************/
|
|
/* Total Length = MCS header + GCC PDU + 1 or 2 length bytes. */
|
|
/************************************************************************/
|
|
mcsUserDataLen = NC_MCS_HDRLEN + gccPDULen + 1;
|
|
|
|
/************************************************************************/
|
|
/* The GCC user data length field - 2 bytes if length > 127. */
|
|
/************************************************************************/
|
|
if (pConn->userDataLen < 128)
|
|
{
|
|
*pGCCPDU++ = (DCUINT8)(pConn->userDataLen & 0x00ff);
|
|
}
|
|
else
|
|
{
|
|
TRC_NRM((TB, _T("Long UserData %d"), pConn->userDataLen));
|
|
*pGCCPDU++ = (DCUINT8)((pConn->userDataLen >> 8) | 0x0080);
|
|
*pGCCPDU++ = (DCUINT8)(pConn->userDataLen & 0x00ff);
|
|
|
|
/********************************************************************/
|
|
/* Add extra length byte */
|
|
/********************************************************************/
|
|
mcsUserDataLen++;
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* Verify that the buffer has enough room, AND the source has */
|
|
/* enough data. */
|
|
/********************************************************************/
|
|
if (!IsContainedMemory(&(mcsUserData[0]), NC_GCCREQ_MAX_PDULEN, pGCCPDU, userDataLen) ||
|
|
!IsContainedMemory(pData, dataLen, pUserData, userDataLen))
|
|
{
|
|
DCUINT errorCode;
|
|
TRC_ABORT((TB, _T("Data source/dest size mismatch: targetsize=%u, sourcebuf=%u, copysize=%u"),
|
|
NC_GCCREQ_MAX_PDULEN, dataLen, userDataLen));
|
|
|
|
/************************************************************************/
|
|
/* Again, haven't called into MCS layer yet, so disconnect by calling */
|
|
/* NC_OnMCSDisconnected directly. */
|
|
/************************************************************************/
|
|
errorCode = NL_MAKE_DISCONNECT_ERR(NL_ERR_NCNOUSERDATA);
|
|
NC_OnMCSDisconnected(errorCode);
|
|
DC_QUIT;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Write the SL + core UserData. */
|
|
/************************************************************************/
|
|
DC_MEMCPY(pGCCPDU, pUserData, userDataLen);
|
|
|
|
/************************************************************************/
|
|
/* Write the NET user data */
|
|
/************************************************************************/
|
|
if (netUserData.channelCount != 0)
|
|
{
|
|
TRC_NRM((TB, _T("Append NET user data")));
|
|
pGCCPDU += userDataLen;
|
|
DC_MEMCPY(pGCCPDU, &netUserData, sizeof(netUserData));
|
|
pGCCPDU += sizeof(netUserData);
|
|
DC_MEMCPY(pGCCPDU,
|
|
pVirtualChannels,
|
|
netUserData.header.length - sizeof(netUserData));
|
|
}
|
|
|
|
TRC_DATA_NRM("MCS User Data passed in", mcsUserData, mcsUserDataLen);
|
|
|
|
/************************************************************************/
|
|
/* Call MCS_Connect passing in the GCC CreateConference PDU as */
|
|
/* userdata. */
|
|
/************************************************************************/
|
|
_pMcs->MCS_Connect(bInitateConnect,
|
|
(PDCTCHAR)pAddress,
|
|
mcsUserData,
|
|
mcsUserDataLen);
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return;
|
|
|
|
} /* NC_Connect */
|
|
|
|
|
|
/**PROC+*********************************************************************/
|
|
/* Name: NC_Disconnect */
|
|
/* */
|
|
/* Purpose: Disconnect from the Server by calling MCS */
|
|
/* */
|
|
/* Returns: None */
|
|
/* */
|
|
/* Params: IN unused - unused parameter */
|
|
/* */
|
|
/**PROC-*********************************************************************/
|
|
DCVOID DCAPI CNC::NC_Disconnect(ULONG_PTR unused)
|
|
{
|
|
DC_BEGIN_FN("NC_Disconnect");
|
|
|
|
DC_IGNORE_PARAMETER(unused);
|
|
|
|
/************************************************************************/
|
|
/* Disconnect from the server by calling MCS_Disconnect. */
|
|
/************************************************************************/
|
|
TRC_NRM((TB, _T("Call MCS_Disconnect")));
|
|
_pMcs->MCS_Disconnect();
|
|
|
|
DC_END_FN();
|
|
return;
|
|
|
|
} /* NC_Disconnect */
|
|
|
|
|
|
|
|
|
|
|
|
|