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

474 lines
19 KiB
C++

/****************************************************************************/
// td.h
//
// Transport driver - portable API.
//
// Copyright (C) 1997-1999 Microsoft Corporation
/****************************************************************************/
#ifndef _H_TD
#define _H_TD
extern "C" {
#ifdef OS_WINCE
#include <winsock.h>
#include <wsasync.h>
#endif
#include <adcgdata.h>
}
#include "objs.h"
#include "cd.h"
#define TRC_FILE "td"
#define TRC_GROUP TRC_GROUP_NETWORK
/****************************************************************************/
/* Define the TD buffer handle type. */
/****************************************************************************/
typedef ULONG_PTR TD_BUFHND;
typedef TD_BUFHND DCPTR PTD_BUFHND;
//
// Internal
//
/****************************************************************************/
/* FSM inputs. */
/****************************************************************************/
#define TD_EVT_TDINIT 0
#define TD_EVT_TDTERM 1
#define TD_EVT_TDCONNECT_IP 2
#define TD_EVT_TDCONNECT_DNS 3
#define TD_EVT_TDDISCONNECT 4
#define TD_EVT_WMTIMER 5
#define TD_EVT_OK 6
#define TD_EVT_ERROR 7
#define TD_EVT_CONNECTWITHENDPOINT 8
#define TD_EVT_DROPLINK 9
#define TD_FSM_INPUTS 10
/****************************************************************************/
/* FSM state definitions. */
/****************************************************************************/
#define TD_ST_NOTINIT 0
#define TD_ST_DISCONNECTED 1
#define TD_ST_WAITFORDNS 2
#define TD_ST_WAITFORSKT 3
#define TD_ST_CONNECTED 4
#define TD_ST_WAITFORCLOSE 5
#define TD_FSM_STATES 6
/****************************************************************************/
/* Send buffer sizes for the private and public queues. These must be */
/* sorted in order of increasing size. Note that the buffer sizes are */
/* chosen to minimize the runtime working set - under normal circumstances */
/* only the two 2000 byte public buffers will be in-use, consuming 1 page */
/* of memory. */
/* */
/* The two 4096-byte public buffers are provided to support virtual channel */
/* data. If VCs are not in use, these buffers are unlikely to be used. */
/* */
/* NOTE: The constant TD_SNDBUF_PUBNUM must reflect the number of */
/* buffers in the TD_SNDBUF_PUBSIZES array. */
/* Similarily TD_SNDBUF_PRINUM must reflect the number of buffers in */
/* the TD_SNDBUF_PRISIZES array. */
/****************************************************************************/
#define TD_SNDBUF_PUBSIZES {2000, 2000, 4096, 4096}
#define TD_SNDBUF_PUBNUM 4
#define TD_SNDBUF_PRISIZES {1024, 512}
#define TD_SNDBUF_PRINUM 2
/****************************************************************************/
/* Limited broadcast address. */
/****************************************************************************/
#define TD_LIMITED_BROADCAST_ADDRESS "255.255.255.255"
/****************************************************************************/
/* Maximum number of bytes TD will receive on a single FD_READ */
/****************************************************************************/
#define TD_MAX_UNINTERRUPTED_RECV (16 * 1024)
// Number of bytes to allocate to the recv buffer.
//
// The recv buffer size should be as large as the largest typical server
// OUTBUF that will come our way (8K minus a bit). Most recv()
// implementations try to copy all the data for a TCP sequence (an entire
// OUTBUF) into the target buffer, if the space is available. This means
// that, for code that can access an unaligned data stream, we can use the
// data bytes straight out of the TD receive buffer most of the time, saving
// a large memcpy to an aligned reassembly buffer.
//
// NOTE: Because of Win2000 bug 392510, we alloc a full 8K but only use
// (8K - 2 bytes) because the MPPC decompression code in core\compress.c
// does not stay within the source data buffer boundary.
#define TD_RECV_BUFFER_SIZE 8192
/****************************************************************************/
/* Macro to trace out all the send buffers and the contents of the send */
/* queue. This is used when a send-buffer error occurs. */
/****************************************************************************/
#if defined(DC_DEBUG) && (TRC_COMPILE_LEVEL < TRC_LEVEL_DIS)
#define TD_TRACE_SENDINFO(level) \
{ \
TD_TRACE_SENDBUFS(level, _TD.pubSndBufs, TD_SNDBUF_PUBNUM, "Pub"); \
TD_TRACE_SENDBUFS(level, _TD.priSndBufs, TD_SNDBUF_PRINUM, "Pri"); \
TD_TRACE_SENDQUEUE(level); \
}
#define TD_TRACE_SENDBUFS(level, queue, numBufs, pText) \
{ \
DCUINT i; \
for (i = 0; i < numBufs; i++) \
{ \
TRCX(level, (TB, _T("%sQ[%u] <%p> pNxt:%p iU:%s ") \
"size:%u pBuf:%p bLTS:%u pDLTS:%p owner %s", \
pText, \
i, \
&queue[i], \
queue[i].pNext, \
queue[i].inUse ? "T" : "F", \
queue[i].size, \
queue[i].pBuffer, \
queue[i].bytesLeftToSend, \
queue[i].pDataLeftToSend, \
queue[i].pOwner)); \
} \
}
#define TD_TRACE_SENDQUEUE(level) \
{ \
PTD_SNDBUF_INFO pBuf; \
DCUINT i = 0; \
\
pBuf = _TD.pFQBuf; \
if (NULL == pBuf) \
{ \
TRCX(level, (TB, _T("SendQ is empty"))); \
} \
else \
{ \
while (NULL != pBuf) \
{ \
TRCX(level, (TB, _T("SendQ[%u] <%p> pNxt:%p size:%u bLTS:%u"), \
i, \
pBuf, \
pBuf->pNext, \
pBuf->size, \
pBuf->bytesLeftToSend)); \
pBuf = pBuf->pNext; \
} \
TRCX(level, (TB, _T("End of send queue"))); \
} \
}
#else // defined(DC_DEBUG) && (TRC_COMPILE_LEVEL < TRC_LEVEL_DIS)
#define TD_TRACE_SENDINFO(level)
#endif // defined(DC_DEBUG) && (TRC_COMPILE_LEVEL < TRC_LEVEL_DIS)
/****************************************************************************/
/* Structure: TD_SNDBUF_INFO */
/* */
/* Description: Contains information about a TD send buffer. */
/****************************************************************************/
typedef struct tagTD_SNDBUF_INFO DCPTR PTD_SNDBUF_INFO;
typedef struct tagTD_SNDBUF_INFO
{
PTD_SNDBUF_INFO pNext;
DCBOOL inUse;
DCUINT size;
PDCUINT8 pBuffer;
DCUINT bytesLeftToSend;
PDCUINT8 pDataLeftToSend;
#ifdef DC_DEBUG
PDCTCHAR pOwner;
#endif
} TD_SNDBUF_INFO;
/****************************************************************************/
/* Structure: TD_RECV_BUFFER */
/* */
/* Description: Contains information about the buffer into which TD */
/* receives data from Winsock. */
/****************************************************************************/
typedef struct tagTD_RCVBUF_INFO
{
DCUINT size;
DCUINT dataStart;
DCUINT dataLength;
PDCUINT8 pData;
} TD_RCVBUF_INFO;
/****************************************************************************/
/* Structure: TD_GLOBAL_DATA */
/* */
/* Description: TD global data */
/****************************************************************************/
typedef struct tagTD_GLOBAL_DATA
{
HWND hWnd;
DCUINT fsmState;
HANDLE hGHBN;
SOCKET hSocket; // connection socket
INT_PTR hTimer;
DCBOOL dataInTD;
PTD_SNDBUF_INFO pFQBuf;
TD_SNDBUF_INFO pubSndBufs[TD_SNDBUF_PUBNUM];
TD_SNDBUF_INFO priSndBufs[TD_SNDBUF_PRINUM];
DCUINT recvByteCount;
TD_RCVBUF_INFO recvBuffer;
DCBOOL inFlushSendQueue;
DCBOOL getBufferFailed;
#ifdef OS_WINCE
DCBOOL enableWSRecv;
#if (_WIN32_WCE > 300)
HANDLE hevtAddrChange;
HANDLE hAddrChangeThread;
#endif
#endif // OS_WINCE
#ifdef DC_DEBUG
INT_PTR hThroughputTimer;
DCUINT32 periodSendBytesLeft;
DCUINT32 periodRecvBytesLeft;
DCUINT32 currentThroughput;
#endif /* DC_DEBUG */
} TD_GLOBAL_DATA;
#ifdef DC_DEBUG
/****************************************************************************/
/* State and event descriptions (debug build only) */
/****************************************************************************/
static const DCTCHAR tdStateText[TD_FSM_STATES][50]
= {
_T("TD_ST_NOTINIT"),
_T("TD_ST_DISCONNECTED"),
_T("TD_ST_WAITFORDNS"),
_T("TD_ST_WAITFORSKT"),
_T("TD_ST_CONNECTED"),
_T("TD_ST_WAITFORCLOSE"),
}
;
static const DCTCHAR tdEventText[TD_FSM_INPUTS][50]
= {
_T("TD_EVT_TDINIT"),
_T("TD_EVT_TDTERM"),
_T("TD_EVT_TDCONNECT_IP"),
_T("TD_EVT_TDCONNECT_DNS"),
_T("TD_EVT_TDDISCONNECT"),
_T("TD_EVT_WMTIMER"),
_T("TD_EVT_OK"),
_T("TD_EVT_ERROR"),
_T("TD_EVT_CONNECTWITHENDPOINT")
}
;
#endif /* DC_DEBUG */
class CUI;
class CCD;
class CNL;
class CUT;
class CXT;
class CCD;
class CTD
{
public:
CTD(CObjs* objs);
~CTD();
public:
//
// API functions
//
DCVOID DCAPI TD_Init(DCVOID);
DCVOID DCAPI TD_Term(DCVOID);
DCVOID DCAPI TD_Connect(BOOL bInitateConnect, PDCTCHAR pServerAddress);
DCVOID DCAPI TD_Disconnect(DCVOID);
//
// Abortive disconnect
//
DCVOID DCAPI TD_DropLink(DCVOID);
DCBOOL DCAPI TD_GetPublicBuffer(DCUINT dataLength,
PPDCUINT8 ppBuffer,
PTD_BUFHND pBufHandle);
DCBOOL DCAPI TD_GetPrivateBuffer(DCUINT dataLength,
PPDCUINT8 ppBuffer,
PTD_BUFHND pBufHandle);
DCVOID DCAPI TD_SendBuffer(PDCUINT8 pData,
DCUINT dataLength,
TD_BUFHND bufHandle);
DCVOID DCAPI TD_FreeBuffer(TD_BUFHND bufHandle);
DCUINT DCAPI TD_Recv(PDCUINT8 pData,
DCUINT size);
#ifdef DC_DEBUG
DCVOID DCAPI TD_SetBufferOwner(TD_BUFHND bufHandle, PDCTCHAR pOwner);
#endif
/****************************************************************************/
/* Name: TD_QueryDataAvailable */
/* */
/* Purpose: The return value indicates whether there is data available */
/* in _TD. */
/* */
/* Returns: TRUE if there is data available in TD and FALSE otherwise. */
/* */
/* Operation: This function simply returns the global variable _TD.dataInTD */
/* which is set to TRUE whenever we get a FD_READ from WinSock */
/* and set to FALSE whenever a call to recv returns fewer bytes */
/* than requested. */
/****************************************************************************/
inline DCBOOL DCAPI TD_QueryDataAvailable(DCVOID)
{
DC_BEGIN_FN("TD_QueryDataAvailable");
TRC_DBG((TB, "Data is%s available in TD", _TD.dataInTD ? "" : _T(" NOT")));
DC_END_FN();
return(_TD.dataInTD);
} /* TD_QueryDataAvailable */
#ifdef OS_WINCE
/****************************************************************************/
/* Name: TD_EnableWSRecv */
/* */
/* Purpose: Perform only one recv per FD_READ */
/****************************************************************************/
inline DCVOID TD_EnableWSRecv(DCVOID)
{
DC_BEGIN_FN("TD_EnableWSRecv");
TRC_DBG((TB, _T("_TD.enableWSRecv is currently set to %s."),
_TD.enableWSRecv ? "TRUE" : "FALSE"));
TRC_ASSERT((_TD.enableWSRecv == FALSE),
(TB, _T("_TD.enableWSRecv is incorrectly set!")));
_TD.enableWSRecv = TRUE;
DC_END_FN();
} /* TD_EnableWSRecv */
#endif // OS_WINCE
#ifdef DC_DEBUG
DCVOID DCAPI TD_SetNetworkThroughput(DCUINT32 maxThroughput);
DCUINT32 DCAPI TD_GetNetworkThroughput(DCVOID);
#endif /* DC_DEBUG */
/****************************************************************************/
// TD_GetDataForLength
//
// Macro-function for XT to directly use recv()'d data from the TD data
// buffer. If we have the requested data fully constructed in the receive
// buffer, skip the data and pass back a pointer, otherwise pass back NULL.
/****************************************************************************/
#define TD_GetDataForLength(_len, _ppData, tdinst) \
if ((tdinst)->_TD.recvBuffer.dataLength >= (_len)) { \
*(_ppData) = (tdinst)->_TD.recvBuffer.pData + (tdinst)->_TD.recvBuffer.dataStart; \
(tdinst)->_TD.recvBuffer.dataLength -= (_len); \
if ((tdinst)->_TD.recvBuffer.dataLength == 0) \
/* Used all the data from the recv buffer so reset start pos. */ \
(tdinst)->_TD.recvBuffer.dataStart = 0; \
else \
/* Still some data left in recv buffer. */ \
(tdinst)->_TD.recvBuffer.dataStart += (_len); \
} \
else { \
*(_ppData) = NULL; \
}
#define TD_IgnoreRestofPacket(tdinst) \
{ \
(tdinst)->_TD.recvBuffer.dataLength = 0; \
(tdinst)->_TD.recvBuffer.dataStart = 0; \
}
unsigned DCINTERNAL TDDoWinsockRecv(BYTE FAR *, unsigned);
void DCINTERNAL TDClearSendQueue(ULONG_PTR);
EXPOSE_CD_SIMPLE_NOTIFICATION_FN(CTD, TDClearSendQueue);
void DCINTERNAL TDSendError(ULONG_PTR);
EXPOSE_CD_SIMPLE_NOTIFICATION_FN(CTD, TDSendError);
public:
//
// public data members
//
TD_GLOBAL_DATA _TD;
private:
//
// Internal member functions
//
/****************************************************************************/
/* FUNCTIONS */
/****************************************************************************/
DCVOID DCINTERNAL TDConnectFSMProc(DCUINT fsmEvent, ULONG_PTR eventData);
DCVOID DCINTERNAL TDAllocBuf(PTD_SNDBUF_INFO pSndBufInf, DCUINT size);
DCVOID DCINTERNAL TDInitBufInfo(PTD_SNDBUF_INFO pSndBufInf);
#include "wtdint.h"
public:
//Can be called by CD so has to be public
void DCINTERNAL TDFlushSendQueue(ULONG_PTR);
EXPOSE_CD_SIMPLE_NOTIFICATION_FN(CTD, TDFlushSendQueue);
private:
CNL* _pNl;
CUT* _pUt;
CXT* _pXt;
CUI* _pUi;
CCD* _pCd;
private:
CObjs* _pClientObjects;
};
#undef TRC_FILE
#undef TRC_GROUP
#endif // _H_TD