Windows2003-3790/termsrv/newclient/core/ncapi.cpp
2020-09-30 16:53:55 +02:00

511 lines
22 KiB
C++

/**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 */