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.
298 lines
12 KiB
298 lines
12 KiB
/*
|
|
** Direct Network Protocol
|
|
**
|
|
** This file contains internal prototypes and global definitions.
|
|
*/
|
|
|
|
// Protocol Version History /////////////////////////////////////////////////////////////
|
|
//
|
|
// 1.0 - DPlay8 original
|
|
// 1.1 - Fix SACK frame bogus 2 bytes caused by bad packing (DPlay 8.1 beta period only)
|
|
// 1.2 - Revert to original sack behavior with packing fixed, ie same as DPlay 8.0 (shipped in DPlay 8.1)
|
|
// 1.3 - Increment for PocketPC release (RTM prior to DX9 Beta1)
|
|
// 1.4 - DX9 Beta1 only
|
|
// 1.5 - Add coalescence and hard disconnect support
|
|
// 1.5 - .NET Server RTM
|
|
// 1.6 - Added packet signing, new style keep alive and connection spoof prevention
|
|
// 1.6 - DX9 Beta2 through RTM
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Global Constants
|
|
#define DNET_VERSION_NUMBER 0x00010005 // The current protocol version
|
|
#define DNET_COALESCE_VERSION 0x00010005 // The first version with coalescence
|
|
#define DNET_SIGNING_VERSION 0x00010006 // The first version with signing
|
|
|
|
#define DELAYED_ACK_TIMEOUT 100 // Delay before sending dedicated ACK packet
|
|
#define SHORT_DELAYED_ACK_TIMEOUT 20 // Delay before sending dedicated NACK packet
|
|
#define DELAYED_SEND_TIMEOUT 40 // Delay before sending dedicated SEND_INFO packet
|
|
|
|
#define CONNECT_DEFAULT_TIMEOUT (200) // At .1 we saw too many retries, users can set in SetCaps
|
|
#define CONNECT_DEFAULT_RETRIES 14 // Users can set in SetCaps
|
|
#define DEFAULT_MAX_RECV_MSG_SIZE 0xFFFFFFFF //default maximum packet we accept
|
|
#define DEFAULT_SEND_RETRIES_TO_DROP_LINK 10 //default number of send retries we attempt before link is dead
|
|
#define DEFAULT_SEND_RETRY_INTERVAL_LIMIT 5000 //limit on period in msec between retries
|
|
#define DEFAULT_HARD_DISCONNECT_SENDS 3 //default number of hard disconnect frames we send out
|
|
//The value must be at least 2.
|
|
#define DEFAULT_HARD_DISCONNECT_MAX_PERIOD 500 //The default for the maximum period we allow between
|
|
//sending out hard disconnect frames
|
|
#define DEFAULT_INITIAL_FRAME_WINDOW_SIZE 2 //The default initial frame window size
|
|
#define LAN_INITIAL_FRAME_WINDOW_SIZE 32 //The initial frame window size if we asssume a LAN connection
|
|
|
|
#define STANDARD_LONG_TIMEOUT_VALUE 30000
|
|
#define DEFAULT_KEEPALIVE_INTERVAL 60000
|
|
#define ENDPOINT_BACKGROUND_INTERVAL STANDARD_LONG_TIMEOUT_VALUE // this is really what its for...
|
|
|
|
#define CONNECT_SECRET_CHANGE_INTERVAL 60000 //period between creations of new connect secrets
|
|
|
|
#define DEFAULT_THROTTLE_BACK_OFF_RATE 25 // Percent throttle (backoff) rate
|
|
#define DEFAULT_THROTTLE_THRESHOLD_RATE 7 // Percent packets dropped (out of 32)
|
|
|
|
#define DPF_TIMER_LVL 9 // The level at which to spew calls into the Protocol
|
|
|
|
#define DPF_CALLIN_LVL 2 // The level at which to spew calls into the Protocol
|
|
#define DPF_CALLOUT_LVL 3 // The level at which to spew calls out of the Protocol
|
|
|
|
#define DPF_ADAPTIVE_LVL 6 // The level at which to spew Adaptive Algorithm spew
|
|
#define DPF_FRAMECNT_LVL 7 // The level at which to spew Adaptive Algorithm spew
|
|
|
|
#define DPF_REFCNT_LVL 8 // The level at which to spew ref counts
|
|
#define DPF_REFCNT_FINAL_LVL 5 // The level at which to spew creation and destruction ref counts
|
|
|
|
// Separate ones for endpoints
|
|
#define DPF_EP_REFCNT_LVL 8 // The level at which to spew ref counts
|
|
#define DPF_EP_REFCNT_FINAL_LVL 2 // The level at which to spew creation and destruction ref counts
|
|
|
|
#undef DPF_SUBCOMP
|
|
#define DPF_SUBCOMP DN_SUBCOMP_PROTOCOL
|
|
|
|
//handy macro for dumping a ULONGLONG out to a debug line
|
|
#define DPFX_OUTPUT_ULL(ull) ((DWORD ) ull) , ((DWORD ) (ull>>32))
|
|
|
|
typedef void CALLBACK LPCB(UINT, UINT, DWORD, DWORD, DWORD);
|
|
|
|
// Global Variable definitions
|
|
|
|
extern CFixedPool ChkPtPool;
|
|
extern CFixedPool EPDPool;
|
|
extern CFixedPool MSDPool;
|
|
extern CFixedPool FMDPool;
|
|
extern CFixedPool RCDPool;
|
|
extern CFixedPool BufPool;
|
|
extern CFixedPool MedBufPool;
|
|
extern CFixedPool BigBufPool;
|
|
|
|
// Pool functions
|
|
BOOL Buf_Allocate(PVOID, PVOID pvContext);
|
|
VOID Buf_Get(PVOID, PVOID pvContext);
|
|
VOID Buf_GetMed(PVOID, PVOID pvContext);
|
|
VOID Buf_GetBig(PVOID, PVOID pvContext);
|
|
BOOL EPD_Allocate(PVOID, PVOID pvContext);
|
|
VOID EPD_Get(PVOID, PVOID pvContext);
|
|
VOID EPD_Release(PVOID);
|
|
VOID EPD_Free(PVOID);
|
|
BOOL FMD_Allocate(PVOID, PVOID pvContext);
|
|
VOID FMD_Get(PVOID, PVOID pvContext);
|
|
VOID FMD_Release(PVOID);
|
|
VOID FMD_Free(PVOID);
|
|
BOOL MSD_Allocate(PVOID, PVOID pvContext);
|
|
VOID MSD_Get(PVOID, PVOID pvContext);
|
|
VOID MSD_Release(PVOID);
|
|
VOID MSD_Free(PVOID);
|
|
BOOL RCD_Allocate(PVOID, PVOID pvContext);
|
|
VOID RCD_Get(PVOID, PVOID pvContext);
|
|
VOID RCD_Release(PVOID);
|
|
VOID RCD_Free(PVOID);
|
|
|
|
|
|
#ifdef DBG
|
|
extern CBilink g_blProtocolCritSecsHeld;
|
|
#endif // DBG
|
|
|
|
// Internal function prototypes /////////////////////////////////
|
|
|
|
// Timers
|
|
VOID CALLBACK ConnectRetryTimeout(void * const pvUser, void * const pvHandle, const UINT uiUnique);
|
|
VOID CALLBACK DelayedAckTimeout(void * const pvUser, void * const uID, const UINT uMsg);
|
|
VOID CALLBACK EndPointBackgroundProcess(void * const pvUser, void * const pvTimerData, const UINT uiTimerUnique);
|
|
VOID CALLBACK RetryTimeout(void * const pvUser, void * const uID, const UINT Unique);
|
|
VOID CALLBACK ScheduledSend(void * const pvUser, void * const pvTimerData, const UINT uiTimerUnique);
|
|
VOID CALLBACK TimeoutSend(void * const pvUser, void * const uID, const UINT uMsg);
|
|
VOID CALLBACK HardDisconnectResendTimeout(void * const pvUser, void * const pvTimerData, const UINT uiTimerUnique);
|
|
|
|
|
|
VOID AbortSendsOnConnection(PEPD);
|
|
SPRECEIVEDBUFFER * AbortRecvsOnConnection(PEPD);
|
|
VOID CancelEpdTimers(PEPD);
|
|
ULONG WINAPI BackgroundThread(PVOID);
|
|
HRESULT DoCancel(PMSD, HRESULT);
|
|
VOID CompleteConnect(PMSD, PSPD, PEPD, HRESULT);
|
|
VOID CompleteDisconnect(PMSD pMSD, PSPD pSPD, PEPD pEPD);
|
|
VOID CompleteHardDisconnect(PEPD pEPD);
|
|
VOID CompleteDatagramSend(PSPD, PMSD, HRESULT);
|
|
VOID CompleteReliableSend(PSPD, PMSD, HRESULT);
|
|
VOID CompleteSPConnect(PMSD, PSPD, HRESULT);
|
|
VOID DisconnectConnection(PEPD);
|
|
VOID DropLink(PEPD);
|
|
PMSD BuildDisconnectFrame(PEPD);
|
|
VOID EndPointDroppedFrame(PEPD, DWORD);
|
|
VOID EnqueueMessage(PMSD, PEPD);
|
|
VOID FlushCheckPoints(PEPD);
|
|
VOID InitLinkParameters(PEPD, UINT, DWORD);
|
|
PCHKPT LookupCheckPoint(PEPD, BYTE);
|
|
PEPD NewEndPoint(PSPD, HANDLE);
|
|
VOID SendKeepAlive(PEPD pEPD);
|
|
VOID ReceiveComplete(PEPD);
|
|
VOID SendAckFrame(PEPD, BOOL, BOOL fFinalAck = FALSE);
|
|
HRESULT SendCommandFrame(PEPD, BYTE, BYTE, ULONG, BOOL);
|
|
HRESULT SendConnectedSignedFrame(PEPD pEPD, CFRAME_CONNECTEDSIGNED * pCFrameRecv, DWORD tNow);
|
|
ULONG WINAPI SendThread(PVOID);
|
|
VOID ServiceCmdTraffic(PSPD);
|
|
VOID ServiceEPD(PSPD, PEPD);
|
|
VOID UpdateEndPoint(PEPD, UINT, DWORD);
|
|
VOID UpdateXmitState(PEPD, BYTE, ULONG, ULONG, DWORD);
|
|
VOID RejectInvalidPacket(PEPD);
|
|
|
|
ULONGLONG GenerateConnectSig(DWORD dwSessID, DWORD dwAddressHash, ULONGLONG ullConnectSecret);
|
|
ULONGLONG GenerateOutgoingFrameSig(PFMD pFMD, ULONGLONG ullSecret);
|
|
ULONGLONG GenerateIncomingFrameSig(BYTE * pbyFrame, DWORD dwFrameSize, ULONGLONG ullSecret);
|
|
ULONGLONG GenerateNewSecret(ULONGLONG ullCurrentSecret, ULONGLONG ullSecretModifier);
|
|
ULONGLONG GenerateLocalSecretModifier(BUFFERDESC * pBuffers, DWORD dwNumBuffers);
|
|
ULONGLONG GenerateRemoteSecretModifier(BYTE * pbyData, DWORD dwDataSize);
|
|
|
|
//returns TRUE if supplied protocol version number indicates signing is supported
|
|
inline BOOL VersionSupportsSigning(DWORD dwVersion)
|
|
{
|
|
return (((dwVersion>>16)==1) && ((dwVersion & 0xFFFF) >= (DNET_SIGNING_VERSION & 0xFFFF)));
|
|
}
|
|
|
|
//returns TRUE if supplied protocol version number indicates coalescence is supported
|
|
inline BOOL VersionSupportsCoalescence(DWORD dwVersion)
|
|
{
|
|
return (((dwVersion>>16)==1) && ((dwVersion & 0xFFFF) >= (DNET_COALESCE_VERSION & 0xFFFF)));
|
|
}
|
|
|
|
#ifndef DPNBUILD_NOPROTOCOLTESTITF
|
|
extern PFNASSERTFUNC g_pfnAssertFunc;
|
|
extern PFNMEMALLOCFUNC g_pfnMemAllocFunc;
|
|
#endif // !DPNBUILD_NOPROTOCOLTESTITF
|
|
|
|
// Internal Macro definitions
|
|
|
|
#undef ASSERT
|
|
|
|
#ifndef DBG
|
|
#define ASSERT(EXP) DNASSERT(EXP)
|
|
#else // DBG
|
|
#define ASSERT(EXP) \
|
|
if (!(EXP)) \
|
|
{ \
|
|
if (g_pfnAssertFunc) \
|
|
{ \
|
|
g_pfnAssertFunc(#EXP); \
|
|
} \
|
|
DNASSERT(EXP); \
|
|
}
|
|
#endif // !DBG
|
|
|
|
#ifdef DPNBUILD_NOPROTOCOLTESTITF
|
|
|
|
#define MEMALLOC(memid, dwpSize) DNMalloc(dwpSize)
|
|
#define POOLALLOC(memid, pool) (pool)->Get()
|
|
|
|
#else // !DPNBUILD_NOPROTOCOLTESTITF
|
|
|
|
#define MEMALLOC(memid, dwpSize) MemAlloc(memid, dwpSize)
|
|
#define POOLALLOC(memid, pool) PoolAlloc(memid, pool)
|
|
__inline VOID* MemAlloc(ULONG ulAllocID, DWORD_PTR dwpSize)
|
|
{
|
|
if (g_pfnMemAllocFunc)
|
|
{
|
|
if (!g_pfnMemAllocFunc(ulAllocID))
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
return DNMalloc(dwpSize);
|
|
}
|
|
__inline VOID* PoolAlloc(ULONG ulAllocID, CFixedPool* pPool)
|
|
{
|
|
if (g_pfnMemAllocFunc)
|
|
{
|
|
if (!g_pfnMemAllocFunc(ulAllocID))
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
return pPool->Get();
|
|
}
|
|
|
|
#endif // DPNBUILD_NOPROTOCOLTESTITF
|
|
|
|
#define Lock(P) DNEnterCriticalSection(P)
|
|
#define Unlock(P) DNLeaveCriticalSection(P)
|
|
|
|
#define ASSERT_PPD(PTR) ASSERT((PTR) != NULL); ASSERT((PTR)->Sign == PPD_SIGN)
|
|
#define ASSERT_SPD(PTR) ASSERT((PTR) != NULL); ASSERT((PTR)->Sign == SPD_SIGN)
|
|
#define ASSERT_EPD(PTR) ASSERT((PTR) != NULL); ASSERT((PTR)->Sign == EPD_SIGN)
|
|
#define ASSERT_MSD(PTR) ASSERT((PTR) != NULL); ASSERT((PTR)->Sign == MSD_SIGN)
|
|
#define ASSERT_FMD(PTR) ASSERT((PTR) != NULL); ASSERT((PTR)->Sign == FMD_SIGN)
|
|
#define ASSERT_RCD(PTR) ASSERT((PTR) != NULL); ASSERT((PTR)->Sign == RCD_SIGN)
|
|
|
|
#define INTER_INC(PTR) DNInterlockedIncrement(&(PTR)->lRefCnt)
|
|
#define INTER_DEC(PTR) DNInterlockedDecrement(&(PTR)->lRefCnt)
|
|
|
|
#ifdef DBG
|
|
|
|
VOID LockEPD(PEPD, PTSTR);
|
|
VOID ReleaseEPD(PEPD, PTSTR);
|
|
VOID DecrementEPD(PEPD, PTSTR);
|
|
VOID LockMSD(PMSD, PTSTR);
|
|
VOID ReleaseMSD(PMSD, PTSTR);
|
|
VOID DecrementMSD(PMSD, PTSTR);
|
|
VOID ReleaseFMD(PFMD, PTSTR);
|
|
VOID LockFMD(PFMD, PTSTR);
|
|
|
|
#define LOCK_EPD(a, b) LockEPD(a, _T(b))
|
|
#define RELEASE_EPD(a, b) ReleaseEPD(a, _T(b))
|
|
#define DECREMENT_EPD(a, b) DecrementEPD(a, _T(b))
|
|
#define LOCK_MSD(a, b) LockMSD(a, _T(b))
|
|
#define RELEASE_MSD(a, b) ReleaseMSD(a, _T(b))
|
|
#define DECREMENT_MSD(a, b) DecrementMSD(a, _T(b))
|
|
#define RELEASE_FMD(a, b) ReleaseFMD(a, _T(b))
|
|
#define LOCK_FMD(a, b) LockFMD(a, _T(b))
|
|
|
|
#else // !DBG
|
|
|
|
VOID LockEPD(PEPD);
|
|
VOID ReleaseEPD(PEPD);
|
|
VOID DecrementEPD(PEPD);
|
|
VOID LockMSD(PMSD);
|
|
VOID ReleaseMSD(PMSD);
|
|
VOID DecrementMSD(PMSD);
|
|
VOID ReleaseFMD(PFMD);
|
|
VOID LockFMD(PFMD);
|
|
|
|
#define LOCK_EPD(a, b) LockEPD(a)
|
|
#define RELEASE_EPD(a, b) ReleaseEPD(a)
|
|
#define DECREMENT_EPD(a, b) DecrementEPD(a)
|
|
#define LOCK_MSD(a, b) LockMSD(a)
|
|
#define RELEASE_MSD(a, b) ReleaseMSD(a)
|
|
#define DECREMENT_MSD(a, b) DecrementMSD(a)
|
|
#define RELEASE_FMD(a, b) ReleaseFMD(a)
|
|
#define LOCK_FMD(a, b) LockFMD(a)
|
|
|
|
#endif // DBG
|
|
|
|
#define LOCK_RCD(PTR) (INTER_INC(PTR))
|
|
#define RELEASE_RCD(PTR) ASSERT((PTR)->lRefCnt > 0); if( INTER_DEC(PTR) == 0) { RCDPool.Release((PTR)); }
|
|
|
|
// This links the passed in pRcvBuff onto a passed in list
|
|
#define RELEASE_SP_BUFFER(LIST, PTR) if((PTR) != NULL) { (PTR)->pNext = (LIST); (LIST) = (PTR); (PTR) = NULL;}
|
|
|
|
#define RIGHT_SHIFT_64(HIGH_MASK, LOW_MASK) { ((LOW_MASK) >>= 1); if((HIGH_MASK) & 1){ (LOW_MASK) |= 0x80000000; } ((HIGH_MASK) >>= 1); }
|
|
|
|
// CONVERT TO AND FROM 16.16 FIXED POINT REPRESENTATION
|
|
|
|
#define TO_FP(X) (((X) << 16) & 0xFFFF0000)
|
|
#define FP_INT(X) (((X) >> 16) & 0x0000FFFF)
|
|
|