446 lines
16 KiB
C
446 lines
16 KiB
C
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ARPSTRUC.H
|
|
|
|
Abstract:
|
|
|
|
Structure definitions for the ARP protocol implementation
|
|
|
|
Author:
|
|
|
|
Aaron Ogus (aarono)
|
|
|
|
Environment:
|
|
|
|
Win32/COM
|
|
|
|
Revision History:
|
|
|
|
Date Author Description
|
|
======= ====== ============================================================
|
|
1/27/97 aarono Original
|
|
2/18/98 aarono Added more fields to SEND for SendEx support
|
|
6/6/98 aarono Turn on throttling and windowing
|
|
|
|
--*/
|
|
|
|
#ifndef _ARPSTRUC_H_
|
|
#define _ARPSTRUC_H_
|
|
|
|
#include <windows.h>
|
|
#include <mmsystem.h>
|
|
#include <dplay.h>
|
|
#include "arpd.h"
|
|
#include "bufpool.h"
|
|
#include "bilink.h"
|
|
#include "mydebug.h"
|
|
//#include "threads.h"
|
|
|
|
#define VOL volatile
|
|
//
|
|
// Information about sent packets, tracked for operational statistics.
|
|
//
|
|
|
|
#define SENDSTAT_SIGN SIGNATURE('S','T','A','T')
|
|
|
|
typedef struct PROTOCOL *PPROTOCOL;
|
|
|
|
typedef struct _SENDSTAT {
|
|
#ifdef SIGN
|
|
UINT Signature; // Signature for SIGN
|
|
#endif
|
|
union {
|
|
BILINK StatList; // linked on Send and later SESSION.
|
|
struct _SENDSTAT *pNext;
|
|
};
|
|
UINT messageid;
|
|
UINT sequence; // sequence number
|
|
UINT serial; // serial number
|
|
UINT tSent; // tick time when this packet instance sent.
|
|
UINT LocalBytesSent; // number of bytes sent on session at send time.
|
|
UINT RemoteBytesReceived;// last remote byte report at send time.
|
|
UINT tRemoteBytesReceived; // remote timestamp when received.
|
|
UINT bResetBias;
|
|
} SENDSTAT, *PSENDSTAT;
|
|
|
|
#define SEND_SIGN SIGNATURE('S','E','N','D')
|
|
|
|
typedef enum _TRANSMITSTATE {
|
|
Start=0, // Never sent a packet.
|
|
Sending=1, // Thread to send is running and xmitting.
|
|
Throttled=2, // Waiting for send bandwidth.
|
|
WaitingForAck=3, // Timer running, listening for ACKs.
|
|
WaitingForId=4, // Waiting for a Send Id.
|
|
ReadyToSend=5, // Have stuff to xmit, waiting for thread.
|
|
TimedOut=6, // Retry timed out.
|
|
Cancelled=7, // User cancelled send.
|
|
UserTimeOut=8, // Didn't try to send until too late.
|
|
Done=9 // Finished sending, singalled sender.
|
|
|
|
} TRANSMITSTATE;
|
|
|
|
struct _SESSION;
|
|
|
|
// this Send is an ACK or NACK (OR'ed into SEND.dwFlags)
|
|
#define ASEND_PROTOCOL 0x80000000
|
|
|
|
#pragma pack(push,1)
|
|
|
|
typedef struct _SEND{
|
|
|
|
#ifdef SIGN
|
|
UINT Signature; // Signature for SIGN
|
|
#endif
|
|
CRITICAL_SECTION SendLock; // Lock for Send Structure
|
|
VOL UINT RefCount; // @#$%!
|
|
|
|
VOL TRANSMITSTATE SendState; // State of this message's transmission.
|
|
|
|
// Lists and Links...
|
|
|
|
union {
|
|
struct _SEND *pNext; // linking on free pool
|
|
BILINK SendQ; // linking on session send queue
|
|
};
|
|
BILINK m_GSendQ; // Global Priority Queue
|
|
BILINK TimeoutList; // List of sends waiting for timeout (workaround MMTIMER cancel bug).
|
|
struct _SESSION *pSession; // pointer to SESSIONion(gets a ref)
|
|
|
|
PPROTOCOL pProtocol; // pointer to Protocol instance that created us.
|
|
|
|
// Send Information
|
|
|
|
DPID idFrom;
|
|
DPID idTo;
|
|
WORD wIdTo; // index in table
|
|
WORD wIdFrom; // index in table
|
|
UINT dwFlags; // Send Flags (include reliable)
|
|
PBUFFER pMessage; // Buffer chain describing message.
|
|
UINT MessageSize; // Total size of the message.
|
|
UINT FrameDataLen; // Data area of each frame.
|
|
UINT nFrames; // Number of frames for this message.
|
|
|
|
UINT Priority; // Send Priority.
|
|
|
|
// User cancel and complete info
|
|
DWORD dwMsgID; // message id given to user, for use in cancel.
|
|
LPVOID lpvUserMsgID; // user's own identifier for this send.
|
|
BOOL bSendEx; // called through SendEx.
|
|
|
|
// Vars for reliability
|
|
BOOL fSendSmall;
|
|
VOL BOOL fUpdate; // update to NS,NR NACKMask made by receive.
|
|
UINT messageid; // Message ID number.
|
|
UINT serial; // serial number.
|
|
VOL UINT OpenWindow; // Number of sends we are trying to get outstanding
|
|
VOL UINT NS; // Sequence Sent.
|
|
VOL UINT NR; // Sequence ACKED.
|
|
UINT SendSEQMSK; // Mask to use. - BUGBUG: determine speed at start
|
|
VOL UINT NACKMask; // Bit pattern of NACKed frames.
|
|
|
|
|
|
// These are the values at NR - updated by ACKs
|
|
VOL UINT SendOffset; // Current offset we are sending.
|
|
VOL PBUFFER pCurrentBuffer; // Current buffer being sent.
|
|
VOL UINT CurrentBufferOffset; // Offset in the current buffer of next packet.
|
|
|
|
// info to update link characteristics when ACKs come in.
|
|
|
|
BILINK StatList; // Info for packets already sent.
|
|
DWORD BytesThisSend; // number of bytes being sent in the current packet.
|
|
|
|
// Operational Characteristics
|
|
|
|
VOL UINT_PTR uRetryTimer;
|
|
UINT TimerUnique;
|
|
|
|
UINT RetryCount; // Number of times we retransmitted.
|
|
UINT WindowSize; // Maximum Window Size.
|
|
UINT SAKInterval; // interval (frames) at which a SAK is required.
|
|
UINT SAKCountDown; // countdown to 0 from interval.
|
|
UINT tLastACK; // Time we last got an ACK.
|
|
|
|
UINT dwSendTime; // time we were called in send.
|
|
UINT dwTimeOut; // timeout time.
|
|
|
|
//BUGBUG:
|
|
UINT PacketSize; // Size of packets to send.
|
|
UINT FrameSize; // Size of Frames for this send.
|
|
|
|
// Completion Vars
|
|
HANDLE hEvent; // Event to wait on for internal send.
|
|
UINT Status; // Send Completion Status.
|
|
|
|
PASYNCSENDINFO pAsyncInfo; // ptr to Info for completing Async send(NULL=>internal send)
|
|
ASYNCSENDINFO AsyncInfo; // actual info (copied at send call).
|
|
|
|
DWORD tScheduled; // the time we scheduled the retry;
|
|
DWORD tRetryScheduled; // expected retry timer run time.
|
|
VOL BOOL bCleaningUp; // we are on the queue but don't take a ref pls.
|
|
} SEND, *PSEND;
|
|
|
|
#pragma pack(pop)
|
|
|
|
#define RECEIVE_SIGN SIGNATURE('R','C','V','_')
|
|
|
|
|
|
// Receive buffers are in reverse receive order. When they have all
|
|
// been received, they are then put in proper order.
|
|
typedef struct _RECEIVE {
|
|
#ifdef SIGN
|
|
UINT Signature; // Signature for SIGN
|
|
#endif
|
|
union {
|
|
BILINK pReceiveQ;
|
|
struct _RECEIVE * pNext;
|
|
};
|
|
BILINK RcvBuffList; // List of receive buffers that make up the message.
|
|
|
|
CRITICAL_SECTION ReceiveLock;
|
|
|
|
struct _SESSION *pSession;
|
|
|
|
VOL BOOL fBusy; // Someone is moving this receive.
|
|
BOOL fReliable; // Whether this is a reliable receive.
|
|
VOL BOOL fEOM; // Whether we received the EOM bit.
|
|
|
|
UINT command;
|
|
|
|
UINT messageid;
|
|
VOL UINT MessageSize;
|
|
|
|
VOL UINT iNR; // Absolute index of first receiving packet (reliable only).
|
|
VOL UINT NR; // Last in sequence packet received.
|
|
VOL UINT NS; // Highest packet number received.
|
|
VOL UINT RCVMask; // bitmask of received packets (NR relative)
|
|
|
|
PUCHAR pSPHeader;
|
|
UCHAR SPHeader[0];
|
|
|
|
} RECEIVE, *PRECEIVE;
|
|
|
|
#pragma pack(push,1)
|
|
|
|
typedef struct _CMDINFO {
|
|
WORD wIdTo; // index
|
|
WORD wIdFrom; // index
|
|
DPID idTo; // actual DPID
|
|
DPID idFrom; // actual DPID
|
|
|
|
UINT bytes; // read from ACK.
|
|
DWORD tRemoteACK; // remote time remote ACKed/NACKed
|
|
|
|
UINT tReceived; // timeGetTime() when received.
|
|
UINT command;
|
|
UINT IDMSK;
|
|
USHORT SEQMSK;
|
|
USHORT messageid;
|
|
USHORT sequence;
|
|
UCHAR serial;
|
|
UCHAR flags;
|
|
PVOID pSPHeader; // used to issue a reply.
|
|
} CMDINFO, *PCMDINFO;
|
|
|
|
#pragma pack(pop)
|
|
|
|
//BUGBUG: when a SESSIONion hasn't been used in a long time and contains no pending sends/receives,
|
|
// age it out.
|
|
|
|
#define SESSION_SIGN SIGNATURE('S','E','S','S')
|
|
|
|
// since we now have a full byte for messagid and sequenne in the small headers,
|
|
// we no longer have an advantage for full headers until we apply the new
|
|
// bitmask package, then we must transit to large frame for windows > 127 messages.
|
|
|
|
#define MAX_SMALL_CSENDS 29UL // Maximum Concurrent Sends when using small frame headers
|
|
#define MAX_LARGE_CSENDS 29UL // Maxinum Concurrent Sends when using large frame headers (could make larger except for mask bits)
|
|
#define MAX_SMALL_DG_CSENDS 16UL // Maximum concurrent datagrams when using small frame
|
|
#define MAX_LARGE_DG_CSENDS 16UL // Maximum Concurrent datagrams when using large frames.
|
|
#define MAX_SMALL_WINDOW 24UL
|
|
#define MAX_LARGE_WINDOW 24UL
|
|
|
|
typedef enum _SESSION_STATE {
|
|
Open, // When created and Inited.
|
|
Closing, // Don't accept new receives/sends.
|
|
Closed // gone.
|
|
} SESSION_STATE;
|
|
|
|
#define SERVERPLAYER_INDEX 0xFFFE
|
|
|
|
#define SESSION_THROTTLED 0x00000001 // session throttle is on.
|
|
#define SESSION_UNTHROTTLED 0x00000002 // unthrottle is deffered to avoid confusing GetMessageQueue.
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Transition Matrix for Throttle Adjust
|
|
//
|
|
// Initial State Event:
|
|
// No Drops 1 Drop >1 Drop
|
|
//
|
|
// Start + Start - Meta -- Start
|
|
//
|
|
// Meta + Meta - Stable -- Meta
|
|
//
|
|
// Stable + Stable - Stable -- Meta
|
|
//
|
|
//
|
|
// Engagement of Backlog Throttle goes to MetaStable State.
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
#define METASTABLE_GROWTH_RATE 4
|
|
#define METASTABLE_ADJUST_SMALL_ERR 12
|
|
#define METASTABLE_ADJUST_LARGE_ERR 25
|
|
|
|
#define START_GROWTH_RATE 50
|
|
#define START_ADJUST_SMALL_ERR 25
|
|
#define START_ADJUST_LARGE_ERR 50
|
|
|
|
#define STABLE_GROWTH_RATE 2
|
|
#define STABLE_ADJUST_SMALL_ERR 12
|
|
#define STABLE_ADJUST_LARGE_ERR 25
|
|
|
|
typedef enum _ThrottleAdjustState
|
|
{
|
|
Begin=0, // At start, double until drop or backlog
|
|
MetaStable=1, // Meta stable, large deltas for drops
|
|
Stable=2 // Stable, small deltas for drops
|
|
} eThrottleAdjust;
|
|
|
|
typedef struct _SESSION {
|
|
PPROTOCOL pProtocol; // back ptr to object.
|
|
|
|
#ifdef SIGN
|
|
UINT Signature; // Signature for SIGN
|
|
#endif
|
|
|
|
// Identification
|
|
|
|
CRITICAL_SECTION SessionLock; // Lock for the SESSIONion.
|
|
VOL UINT RefCount; // RefCount for the SESSION.
|
|
VOL SESSION_STATE eState;
|
|
HANDLE hClosingEvent; // Delete waits on this during close.
|
|
|
|
DPID dpid; // The remote direct play id for this session.
|
|
UINT iSession; // index in the session table
|
|
UINT iSysPlayer; // index in session table of sys player.
|
|
// BUGBUG: if iSysPlayer != iSession, then rest of struct not req'd.
|
|
|
|
BILINK SendQ; // Priority order sendQ;
|
|
BOOL fFastLink; // set True when link > 50K/sec, set False when less than 10K/sec.
|
|
BOOL fSendSmall; // Whether we are sending small reliable frames.
|
|
BOOL fSendSmallDG; // Whether we are sending small datagram frames.
|
|
|
|
BOOL fReceiveSmall;
|
|
BOOL fReceiveSmallDG;
|
|
|
|
UINT MaxPacketSize; // Largest packet allowed on the media.
|
|
|
|
// Operating parameters -- Send
|
|
|
|
// Common
|
|
|
|
UINT MaxCSends; // maximum number of concurrent sends
|
|
UINT MaxCDGSends; // maximum number of concurrent datagram sends
|
|
|
|
// Reliable
|
|
|
|
UINT FirstMsg; // First message number being transmitted
|
|
UINT LastMsg; // Last message number being transmitted
|
|
UINT OutMsgMask; // relative to FirstMsg, unacked messages
|
|
|
|
UINT nWaitingForMessageid; // number of sends on queue that can't start sending because they don't have an id.
|
|
|
|
// DataGram
|
|
|
|
|
|
UINT DGFirstMsg; // First message number being transmitted
|
|
UINT DGLastMsg; // Last message number being transmitted
|
|
UINT DGOutMsgMask; // relative to FirstMsg, not-fully sent messages.
|
|
|
|
UINT nWaitingForDGMessageid; // number of sends on queue that can't start sending because they don't have an id.
|
|
|
|
// Send stats are tracked seperately since sends may
|
|
// no longer be around when completions come in.
|
|
|
|
//BILINK OldStatList;
|
|
|
|
|
|
// Operating parameters -- Receive
|
|
|
|
// DataGram Receive.
|
|
BILINK pDGReceiveQ; // queue of ongoing datagram receives
|
|
|
|
// Reliable Receive.
|
|
BILINK pRlyReceiveQ; // queue of ongoing reliable receives
|
|
BILINK pRlyWaitingQ; // Queue of out of order reliable receives waiting.
|
|
// only used when PROTOCOL_NO_ORDER not set.
|
|
UINT FirstRlyReceive;
|
|
UINT LastRlyReceive;
|
|
UINT InMsgMask; // mask of fully received receives, relative to FirstRlyReceive
|
|
|
|
|
|
// Operational characteristics - MUST BE DWORD ALIGNED!!! - this is because we read and write them
|
|
// without a lock and assume the reads and writes are atomic (not in combination)
|
|
|
|
UINT WindowSize; // Max outstanding packets on a send - reliable
|
|
UINT DGWindowSize; // Max outstanding packets on a send - datagram
|
|
|
|
UINT MaxRetry; // Usual max retries before dropping.
|
|
UINT MinDropTime; // Min time to retry before dropping.
|
|
UINT MaxDropTime; // After this time always drop.
|
|
|
|
UINT LocalBytesReceived; // Total Data Bytes received (including retries).
|
|
VOL UINT RemoteBytesReceived; // Last value from remote.
|
|
VOL DWORD tRemoteBytesReceived; // Remote time last value received.
|
|
|
|
UINT LongestLatency; // longest observed latency (msec)
|
|
UINT ShortestLatency; // shortest observed latency(msec)
|
|
UINT LastLatency; // last observed latency (msec)
|
|
|
|
UINT FpAverageLatency; // average latency (msec 24.8) (128 samples)
|
|
UINT FpLocalAverageLatency; // Local average latency (msec 24.8) (16 samples)
|
|
|
|
UINT FpAvgDeviation; // average deviation of latency. (msec 24.8) (128 samples)
|
|
UINT FpLocalAvgDeviation; // average deviation of latency. (msec 24.8) (16 samples)
|
|
|
|
UINT Bandwidth; // latest observed bandwidth (bps)
|
|
UINT HighestBandwidth; // highest observed bandwidth (bps)
|
|
|
|
// we will use changes in the remote ACK delta to isolate latency in the send direction.
|
|
UINT RemAvgACKDelta; // average clock delta between our send time (local time) and remote ACK time (remote time).
|
|
UINT RemAvgACKDeltaResidue;
|
|
UINT RemAvgACKBias; // This value is used to pull the clock delta into a safe range (not near 0 or -1)
|
|
// that won't risk hitting the wraparound when doing calculations
|
|
|
|
// Throttle statistics
|
|
DWORD dwFlags; // Session Flags - currently just "throttle on/off"(MUST STAY THIS WAY)
|
|
UINT SendRateThrottle; // current rate (bps) at which we are throttling.
|
|
DWORD bhitThrottle; // we hit a throttle
|
|
DWORD tNextSend; // when we are allowed to send again.
|
|
DWORD tNextSendResidue; // residual from calculating next send time
|
|
DWORD_PTR uUnThrottle;
|
|
DWORD UnThrottleUnique;
|
|
DWORD FpAvgUnThrottleTime; // (24.8) how late Unthrottle usually called. (throttle when send is this far ahead)
|
|
// last 16 samples, start at 5 ms.
|
|
|
|
DWORD tLastSAK; // last time we asked for an ACK
|
|
|
|
CRITICAL_SECTION SessionStatLock; // [locks this section ------------------------------------------- ]
|
|
BILINK DGStatList; // [Send Statistics for Datagrams (for reliable they are on Sends) ]
|
|
DWORD BytesSent; // [Total Bytes Sent to this target ]
|
|
DWORD BytesLost; // [Total Bytes Lost on the link. ]
|
|
DWORD bResetBias; // [Counts down to reset latency bias ]
|
|
// [---------------------------------------------------------------]
|
|
|
|
eThrottleAdjust ThrottleState; // ZEROINIT puts in Start
|
|
DWORD GrowCount; // number of times we grew in this state
|
|
DWORD ShrinkCount; // number of times we shrank in this state
|
|
DWORD tLastThrottleAdjust; // remember when we last throttled to avoid overthrottling.
|
|
} SESSION, *PSESSION;
|
|
|
|
#endif
|