windows-nt/Source/XPSP1/NT/com/rpc/runtime/mtrt/dgpkt.hxx
2020-09-26 16:20:57 +08:00

1488 lines
28 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (C) Microsoft Corporation, 1993 - 1999
Module Name:
dgpkt.hxx
Abstract:
This file contains the definitions for a dg packet.
Author:
Dave Steckler (davidst) 3-Mar-1992
Revision History:
EdwardR 09-Jul-1997 Added support for large packets (Falcon).
--*/
#ifndef __DGPKT_HXX__
#define __DGPKT_HXX__
#include <rpctrans.hxx>
#include <limits.h>
#include <hashtabl.hxx>
typedef MESSAGE_OBJECT * PMESSAGE_OBJECT;
#define MULTITHREADED
#include <threads.hxx>
#include <delaytab.hxx>
#define DG_RPC_PROTOCOL_VERSION 4
//
// Our code allows only one additional ULONG in a FACK packet body.
//
#define MAX_WINDOW_SIZE (CHAR_BIT * sizeof(unsigned))
//
// delay times
//
#define TWO_SECS_IN_MSEC (2 * 1000)
#define THREE_SECS_IN_MSEC (3 * 1000)
#define TEN_SECS_IN_MSEC (10 * 1000)
#define FIFTEEN_SECS_IN_MSEC (15 * 1000)
#define ONE_MINUTE_IN_MSEC (60 * 1000)
#define FIVE_MINUTES_IN_MSEC (5 * 60 * 1000)
//
// test hook identifiers
//
//
// sending the delayed ack
//
#define TH_DG_SEND_ACK (TH_DG_BASE+1)
#define TH_DG_CONN (TH_DG_BASE+2)
inline unsigned long
CurrentTimeInMsec(
void
)
{
#ifdef MULTITHREADED
return GetTickCount();
#else
return 0;
#endif
}
// PacketType values:
#define DG_REQUEST 0
#define DG_PING 1
#define DG_RESPONSE 2
#define DG_FAULT 3
#define DG_WORKING 4
#define DG_NOCALL 5
#define DG_REJECT 6
#define DG_ACK 7
#define DG_QUIT 8
#define DG_FACK 9
#define DG_QUACK 10
// PacketFlags values:
#define DG_PF_INIT 0x0000
#define DG_PF_FORWARDED 0x0001
#define DG_PF_LAST_FRAG 0x0002
#define DG_PF_FRAG 0x0004
#define DG_PF_NO_FACK 0x0008
#define DG_PF_MAYBE 0x0010
#define DG_PF_IDEMPOTENT 0x0020
#define DG_PF_BROADCAST 0x0040
//
// for PacketFlags2:
//
#define DG_PF2_FORWARDED_2 0x0001
#define DG_PF2_CANCEL_PENDING 0x0002
#define DG_PF2_LARGE_PACKET 0x0080
// In the AES this bit is reserved.
//
#define DG_PF2_UNRELATED 0x0004
//
// For DG_PACKET.Flags
//
#define DG_PF_PARTIAL 0x1
// for DREP[0]:
#define DG_DREP_CHAR_ASCII 0
#define DG_DREP_CHAR_EBCDIC 1
#define DG_DREP_INT_BIG 0
#define DG_DREP_INT_LITTLE 16
// for DREP[1]
#define DG_DREP_FP_IEEE 0
#define DG_DREP_FP_VAX 1
#define DG_DREP_FP_CRAY 2
#define DG_DREP_FP_IBM 3
#define DG_MSG_DREP_INITIALIZE 0x11111100
#define NDR_DREP_ENDIAN_MASK 0xF0
#define RPC_NCA_PACKET_FLAGS (RPC_NCA_FLAGS_IDEMPOTENT | RPC_NCA_FLAGS_BROADCAST | RPC_NCA_FLAGS_MAYBE)
//
// The RPC packet header and security verifier must each be 8-aligned.
//
#define PACKET_HEADER_ALIGNMENT (8)
#define SECURITY_HEADER_ALIGNMENT (8)
enum PENDING_OPERATION
{
PWT_NONE = 0x111,
PWT_RECEIVE,
PWT_SEND,
PWT_SEND_RECEIVE
};
extern const unsigned RpcToPacketFlagsArray[];
extern const unsigned PacketToRpcFlagsArray[];
extern unsigned DefaultSocketBufferLength;
extern unsigned DefaultMaxDatagramSize;
//
// Controls on the number of packets in the packet cache.
// Note that these values are for each packet size, not the
// cache as a whole.
//
#ifndef NO_PACKET_CACHE
#define MIN_FREE_PACKETS 3
#if defined(__RPC_DOS__)
#define MAX_FREE_PACKETS 8
#elif defined(__RPC_WIN16__)
#define MAX_FREE_PACKETS 20
#else
#define MAX_FREE_PACKETS 1000
#endif
#else
#define MIN_FREE_PACKETS 0
#define MAX_FREE_PACKETS 0
#endif
#if defined(DOS) && !defined(WIN)
typedef long LONG;
typedef long PAPI * PLONG;
#endif // Windows
#if defined(MAC)
typedef long LONG;
typedef long PAPI * PLONG;
#endif // Windows
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
typedef unsigned char boolean;
#ifndef DISABLE_DG_LOGGING
inline void
DgLogEvent(
IN unsigned char Subject,
IN unsigned char Verb,
IN void * SubjectPointer,
IN void * ObjectPointer = 0,
IN ULONG_PTR Data = 0,
IN BOOL fCaptureStackTrace = 0,
IN int AdditionalFramesToSkip = 0
)
{
LogEvent( Subject,
Verb,
SubjectPointer,
ObjectPointer,
Data,
fCaptureStackTrace,
AdditionalFramesToSkip
);
}
#else
inline void
DgxLogEvent(
IN unsigned char Subject,
IN unsigned char Verb,
IN void * SubjectPointer,
IN void * ObjectPointer = 0,
IN ULONG_PTR Data = 0,
IN BOOL fCaptureStackTrace = 0,
IN int AdditionalFramesToSkip = 0
)
{
}
#endif
//-------------------------------------------------------------------
extern unsigned long __RPC_FAR
MapToNcaStatusCode (
IN RPC_STATUS RpcStatus
);
extern RPC_STATUS __RPC_FAR
MapFromNcaStatusCode (
IN unsigned long NcaStatus
);
inline unsigned
PacketToRpcFlags(
unsigned PacketFlags
)
{
return PacketToRpcFlagsArray[(PacketFlags >> 4) & 7];
}
#ifndef WIN32
inline LONG
InterlockedExchange(
LONG * pDest,
LONG New
)
{
LONG Old = *pDest;
*pDest = New;
return Old;
}
inline LONG
InterlockedIncrement(
LONG * pDest
)
{
LONG Old = *pDest;
*pDest = 1+Old;
return Old;
}
inline LONG
InterlockedDecrement(
LONG * pDest
)
{
LONG Old = *pDest;
*pDest = -1+Old;
return Old;
}
#endif
//-------------------------------------------------------------------
struct DG_SECURITY_TRAILER
{
unsigned char protection_level;
unsigned char key_vers_num;
};
typedef DG_SECURITY_TRAILER __RPC_FAR * PDG_SECURITY_TRAILER;
struct FACK_BODY_VER_0
{
// FACK body version; we understand only zero.
//
unsigned char Version;
// pad byte
//
unsigned char Pad1;
// Window size, in packets.
// AES/DC contradicts itself on page 12-18, sometimes saying kilobytes.
//
unsigned short WindowSize;
// Largest datagram the sender can handle, in bytes.
//
unsigned long MaxDatagramSize;
// Largest datagram that won't be fragmented over the wire, in bytes.
//
unsigned long MaxPacketSize;
// Serial number of packet that caused this FACK.
//
unsigned short SerialNumber;
// Number of unsigned longs in the Acks[] array.
//
unsigned short AckWordCount;
#pragma warning(disable:4200)
// Array of bit masks.
//
unsigned long Acks[0];
#pragma warning(default:4200)
};
void
ByteSwapFackBody0(
FACK_BODY_VER_0 __RPC_FAR * pBody
);
typedef unsigned char DREP[4];
//
// The following structure is the NCA Datagram RPC packet header.
//
struct _NCA_PACKET_HEADER
{
unsigned char RpcVersion;
unsigned char PacketType;
unsigned char PacketFlags;
unsigned char PacketFlags2;
DREP DataRep;
RPC_UUID ObjectId;
RPC_UUID InterfaceId;
RPC_UUID ActivityId;
unsigned long ServerBootTime;
RPC_VERSION InterfaceVersion;
unsigned long SequenceNumber;
unsigned short OperationNumber;
unsigned short InterfaceHint;
unsigned short ActivityHint;
unsigned short PacketBodyLen;
unsigned short FragmentNumber;
unsigned char AuthProto;
unsigned char SerialLo;
#pragma warning(disable:4200)
unsigned char Data[0];
#pragma warning(default:4200)
//--------------------------------------------------------
// Large packet support
inline BOOL
IsLargePacket()
{
return (PacketFlags2 & DG_PF2_LARGE_PACKET);
}
inline void
SetPacketBodyLen(
unsigned long ulPacketBodyLen
)
{
if (ulPacketBodyLen <= 65535)
{
PacketBodyLen = (unsigned short)ulPacketBodyLen;
// NOTE: FragmentNumber isn't touched in this case.
PacketFlags2 &= ~DG_PF2_LARGE_PACKET;
}
else
{
PacketBodyLen = (unsigned short)(ulPacketBodyLen & 0x0000ffff);
FragmentNumber = (unsigned short)( (ulPacketBodyLen>>16) & 0x0000ffff );
PacketFlags2 |= DG_PF2_LARGE_PACKET;
}
}
inline unsigned long
GetPacketBodyLen()
{
if (PacketFlags2 & DG_PF2_LARGE_PACKET)
{
unsigned long ulLen = ((unsigned long) PacketBodyLen)|( ((unsigned long)FragmentNumber)<<16 );
return ulLen;
}
else
{
return PacketBodyLen;
}
}
inline void
SetFragmentNumber(
unsigned short usFragmentNumber
)
{
if ( !(PacketFlags2 & DG_PF2_LARGE_PACKET) )
{
FragmentNumber = usFragmentNumber;
}
}
inline unsigned short
GetFragmentNumber()
{
if (PacketFlags2 & DG_PF2_LARGE_PACKET)
{
return 0;
}
else
{
return FragmentNumber;
}
}
};
typedef struct _NCA_PACKET_HEADER NCA_PACKET_HEADER, PAPI * PNCA_PACKET_HEADER;
struct QUIT_BODY_0
{
unsigned long Version;
unsigned long EventId;
};
struct QUACK_BODY_0
{
unsigned long Version;
unsigned long EventId;
unsigned char Accepted;
};
//
// The nornal DCE fault or reject packet contains only a single ulong status code.
// A fault or reject packet containing Microsoft extended error info looks more like
// this. The offset of the EE info buffer needs to 0 mod 16, so that 64-bit platforms
// can unmarshal the info without relocating the buffer in memory.
//
#define DG_EE_MAGIC_VALUE ('M' + (('S' + (('E' + ('E' << 8)) << 8)) << 8))
struct EXTENDED_FAULT_BODY
{
unsigned long NcaStatus;
unsigned long Magic;
unsigned long reserved1;
unsigned long reserved2;
char EeInfo[1];
};
class DG_PACKET;
typedef DG_PACKET PAPI * PDG_PACKET;
class __RPC_FAR DG_PACKET
/*++
Class Description:
This class represents a packet that will be sent or received on the
network.
Fields:
pTransAddress - A pointer to either a DG_CLIENT_TRANS_ADDRESS or
a DG_SERVER_TRANS_ADDRESS that this packet will be sent or
received through.
pNcaPacketHeader - Where the packet information goes. Marshalled data
follows immediately after this header.
DataLength - Length of the marshalled data.
TimeReceive - Time in seconds that this packet was
received. This is filled in by the transport.
pNext, pPrevious - Used to keep these packets in a list.
--*/
{
public:
unsigned MaxDataLength;
unsigned DataLength;
DG_PACKET * pNext;
DG_PACKET * pPrevious;
unsigned Flags;
// Tick count when the packet was added to the free list.
//
unsigned TimeReceived;
#ifdef MONITOR_SERVER_PACKET_COUNT
unsigned unused;
long * pCount;
#endif
// WARNING: Header must be 8-byte-aligned.
//
NCA_PACKET_HEADER Header;
//--------------------------------------------------------------------
DG_PACKET(
unsigned PacketLength
);
~DG_PACKET();
void PAPI *
operator new(
size_t ObjectSize,
unsigned BufferLength
);
void
operator delete(
void PAPI * UserBuffer,
size_t ObjectSize
);
static PDG_PACKET
AllocatePacket(
unsigned BufferLength
);
static void
FreePacket(
PDG_PACKET pPacket,
BOOL fCreateNewList = TRUE
);
static BOOL
DeleteIdlePackets(
long CurrentTime
);
static void
FlushPacketLists(
);
static RPC_STATUS
Initialize(
);
inline void
Free(
BOOL CreateNewList = TRUE
)
{
FreePacket(this, CreateNewList);
}
inline static PDG_PACKET
FromStubData(
void * Buffer
)
{
return CONTAINING_RECORD (Buffer, DG_PACKET, Header.Data);
}
inline static PDG_PACKET
FromPacketHeader(
void * Buffer
)
{
return CONTAINING_RECORD(Buffer, DG_PACKET, Header);
}
//--------------------------------------------------------
// Large packet support
inline BOOL
IsLargePacket()
{
return Header.IsLargePacket();
}
inline void
SetPacketBodyLen(
unsigned long ulPacketBodyLen
)
{
Header.SetPacketBodyLen( ulPacketBodyLen );
}
inline unsigned long
GetPacketBodyLen()
{
return Header.GetPacketBodyLen();
}
inline void
SetFragmentNumber(
unsigned short usFragmentNumber
)
{
Header.SetFragmentNumber( usFragmentNumber );
}
inline unsigned short
GetFragmentNumber()
{
return Header.GetFragmentNumber();
}
private:
enum
{
NUMBER_OF_PACKET_LISTS = 6,
IDLE_PACKET_LIFETIME = (30 * 1000)
};
struct PACKET_LIST
{
unsigned PacketLength;
unsigned Count;
PDG_PACKET Head;
};
static long PacketListTimeStamp;
static MUTEX * PacketListMutex;
static PACKET_LIST PacketLists[NUMBER_OF_PACKET_LISTS];
};
inline
DG_PACKET::DG_PACKET(
unsigned PacketLength
)
{
MaxDataLength = PacketLength;
LogEvent(SU_PACKET, EV_CREATE, this, 0, MaxDataLength);
#ifdef MONITOR_SERVER_PACKET_COUNT
pCount = 0;
#endif
}
inline
DG_PACKET::~DG_PACKET()
{
#ifdef MONITOR_SERVER_PACKET_COUNT
ASSERT( pCount == 0 );
#endif
LogEvent(SU_PACKET, EV_DELETE, this, 0, MaxDataLength);
}
inline void PAPI *
DG_PACKET::operator new(
size_t ObjectSize,
unsigned BufferLength
)
/*++
Routine Description:
Allocates a DG_PACKET with the specified buffer size.
Arguments:
ObjectSize - generated by compiler; same as sizeof(DG_PACKET)
BufferLength - PDU size, including NCA header
Return Value:
an 8-byte-aligned pointer to an obect of the requested size
--*/
{
unsigned Size = ObjectSize + BufferLength - sizeof(NCA_PACKET_HEADER);
return RpcAllocateBuffer(Size);
}
inline void
DG_PACKET::operator delete(
void PAPI * UserBuffer,
size_t ObjectSize
)
{
RpcFreeBuffer(UserBuffer);
}
inline
PDG_PACKET
DG_PACKET::AllocatePacket(
unsigned BufferLength
)
/*++
Routine Description:
Allocates a DG_PACKET with the specified buffer size.
Arguments:
ObjectSize - generated by compiler; same as sizeof(DG_PACKET)
BufferLength - actual packet size
Return Value:
an 8-byte-aligned pointer to an obect of the requested size
--*/
{
PDG_PACKET Packet;
Packet = new (BufferLength) DG_PACKET(BufferLength);
#if defined(DEBUGRPC)
if (Packet)
{
Packet->TimeReceived = 0x31415926;
}
#endif
if (Packet)
{
Packet->Flags = 0;
}
LogEvent(SU_PACKET, EV_START, Packet);
return Packet;
}
inline
void
DG_PACKET::FreePacket(
PDG_PACKET Packet,
BOOL fCreateNewList
)
{
LogEvent(SU_PACKET, EV_STOP, Packet);
#ifdef DEBUGRPC
ASSERT(Packet->TimeReceived == 0x31415926);
Packet->TimeReceived = 0;
#endif
#ifdef MONITOR_SERVER_PACKET_COUNT
if (Packet->pCount)
{
InterlockedDecrement( Packet->pCount );
LogEvent( SU_SCALL, ')', PVOID(((ULONG_PTR) Packet->pCount)-0x260), Packet, *Packet->pCount );
Packet->pCount = 0;
}
#endif
delete Packet;
}
void
ByteSwapPacketHeader(
PDG_PACKET pPacket
);
inline BOOL
NeedsByteSwap(
PNCA_PACKET_HEADER pHeader
)
{
#ifdef __RPC_MAC__
if (pHeader->DataRep[0] & DG_DREP_INT_LITTLE)
{
return TRUE;
}
else
{
return FALSE;
}
#else
if (pHeader->DataRep[0] & DG_DREP_INT_LITTLE)
{
return FALSE;
}
else
{
return TRUE;
}
#endif
}
inline void
ByteSwapPacketHeaderIfNecessary(
PDG_PACKET pPacket
)
{
if (NeedsByteSwap(&pPacket->Header))
{
ByteSwapPacketHeader(pPacket);
}
}
inline unsigned short
ReadSerialNumber(
PNCA_PACKET_HEADER pHeader
)
{
unsigned short SerialNum = 0;
SerialNum = pHeader->SerialLo;
SerialNum |= (pHeader->DataRep[3] << 8);
return SerialNum;
}
inline void
SetMyDataRep(
PNCA_PACKET_HEADER pHeader
)
{
#ifdef __RPC_MAC__
pHeader->DataRep[0] = DG_DREP_CHAR_ASCII | DG_DREP_INT_BIG;
pHeader->DataRep[1] = DG_DREP_FP_IEEE;
pHeader->DataRep[2] = 0;
#else
pHeader->DataRep[0] = DG_DREP_CHAR_ASCII | DG_DREP_INT_LITTLE;
pHeader->DataRep[1] = DG_DREP_FP_IEEE;
pHeader->DataRep[2] = 0;
#endif
}
inline void
DeleteSpuriousAuthProto(
PDG_PACKET pPacket
)
/*++
Routine Description:
Some versions of OSF DCE generate packets that specify an auth proto,
but do not actually have an auth trailer. They should be interpreted
as unsecure packets.
Arguments:
the packet to clean up
Return Value:
none
--*/
{
if (pPacket->Header.AuthProto != 0 &&
pPacket->GetPacketBodyLen() == pPacket->DataLength)
{
pPacket->Header.AuthProto = 0;
}
}
#pragma warning(disable:4200) // nonstandard extension: zero-length array
struct DG_ENDPOINT
{
RPC_DATAGRAM_TRANSPORT * TransportInterface;
BOOL Async;
DWORD Flags;
long TimeStamp;
struct DG_ENDPOINT * Next;
LONG NumberOfCalls;
DG_ENDPOINT_STATS Stats;
PVOID TransportEndpoint[];
static DG_ENDPOINT *
FromEndpoint(
IN DG_TRANSPORT_ENDPOINT Endpoint
)
{
return CONTAINING_RECORD( Endpoint, DG_ENDPOINT, TransportEndpoint );
}
};
#pragma warning(3:4200) // nonstandard extension: zero-length array
class NO_VTABLE DG_COMMON_CONNECTION : public GENERIC_OBJECT
{
public:
RPC_DATAGRAM_TRANSPORT *TransportInterface;
UUID_HASH_TABLE_NODE ActivityNode;
SECURITY_CONTEXT * ActiveSecurityContext;
MUTEX Mutex;
unsigned CurrentPduSize;
unsigned RemoteWindowSize;
boolean RemoteDataUpdated;
long TimeStamp;
//--------------------------------------------------------------------
virtual RPC_STATUS
SealAndSendPacket(
IN DG_ENDPOINT * SourceEndpoint,
IN DG_TRANSPORT_ADDRESS RemoteAddress,
IN UNALIGNED NCA_PACKET_HEADER * pHeader,
IN unsigned long DataOffset
) = 0;
DG_COMMON_CONNECTION(
RPC_DATAGRAM_TRANSPORT *TransportInterface,
RPC_STATUS * pStatus
);
~DG_COMMON_CONNECTION(
);
protected:
long ReferenceCount;
unsigned LowestActiveSequence;
unsigned LowestUnusedSequence;
};
struct QUEUED_BUFFER
{
QUEUED_BUFFER * Next;
void * Buffer;
unsigned BufferLength;
unsigned long BufferFlags;
};
class NO_VTABLE DG_PACKET_ENGINE
{
public:
unsigned short ActivityHint;
unsigned short InterfaceHint;
//--------------------------------------------------------------------
DG_PACKET_ENGINE(
unsigned char PacketType,
DG_PACKET * Packet,
RPC_STATUS * pStatus
);
~DG_PACKET_ENGINE(
);
virtual RPC_STATUS
SendSomeFragments();
unsigned long GetSequenceNumber()
{
return SequenceNumber;
}
void
SetSequenceNumber(
unsigned long Seq
)
{
SequenceNumber = Seq;
pSavedPacket->Header.SequenceNumber = Seq;
}
void CheckForLeakedPackets();
void
AddActivePacket(
DG_PACKET * Packet
);
void
RemoveActivePacket(
DG_PACKET * Packet
);
unsigned long SequenceNumber;
PDG_PACKET pSavedPacket;
DG_ENDPOINT * SourceEndpoint;
DG_TRANSPORT_ADDRESS RemoteAddress;
unsigned ReferenceCount;
unsigned long CancelEventId;
unsigned char PacketType;
unsigned char BasePacketFlags;
unsigned char BasePacketFlags2;
//--------------------------------------------------------------------
PDG_PACKET
AllocatePacket(
)
{
PDG_PACKET Packet = 0;
Packet = DG_PACKET::AllocatePacket(CurrentPduSize);
#ifdef DEBUGRPC
if (Packet)
{
Packet->Flags = PtrToUlong(this);
ASSERT( 0 == (Packet->Flags & DG_PF_PARTIAL) );
}
#endif
return Packet;
}
void
FreePacket(
PDG_PACKET Packet
)
{
#ifdef DEBUGRPC
Packet->Flags &= ~DG_PF_PARTIAL;
ASSERT( Packet->Flags == 0 ||
Packet->Flags == PtrToUlong(this) );
#endif
Packet->Free(FALSE);
}
//
//--------------data common to send and receive buffers-------------------
//
//
// used to be MaxPdu
//
unsigned short Reserved0;
//
// Biggest packet that transport won't fragment.
//
unsigned short MaxPacketSize;
//
// Largest PDU that this object will send.
//
unsigned short CurrentPduSize;
//
// Number of bytes of stub data in a datagram.
//
unsigned short MaxFragmentSize;
//
// Number of bytes of security trailer in a datagram.
//
unsigned short SecurityTrailerSize;
//
// number of consecutive unacknowledged packets, including retransmissions
//
unsigned TimeoutCount;
unsigned short SendSerialNumber;
unsigned short ReceiveSerialNumber;
LONG Cancelled;
// Many of these could be made [private].
//
// -------------------data concerning send buffer-------------------------
//
void PAPI * Buffer;
unsigned BufferLength;
unsigned long BufferFlags;
//
// maximum number of packets in send window
//
unsigned short SendWindowSize;
//
// number of packets to transmit in one shot
//
unsigned short SendBurstLength;
//
// lowest unacknowledged fragment
//
unsigned short SendWindowBase;
//
// first fragment that has never been sent
//
unsigned short FirstUnsentFragment;
//
// Buffer offset of FirstUnsentFragment.
//
unsigned FirstUnsentOffset;
//
// bit mask showing which fragments to send
// (same format as in FACK packet with body)
//
unsigned SendWindowBits;
//
// For each unacknowledged fragment, we need to know the serial number
// of the last retransmission. When a FACK arrives, we will retransmit
// only those packets with a serial number less than that of the FACK.
//
struct
{
unsigned long SerialNumber;
unsigned long Length;
unsigned long Offset;
}
FragmentRingBuffer[MAX_WINDOW_SIZE];
unsigned RingBufferBase;
//
// last fragment of buffer
//
unsigned short FinalSendFrag;
// serial number of last packet FACKed by other end
//
unsigned short FackSerialNumber;
//
// ----------------data concerning receive buffer-------------------------
//
//
// all received packets
//
PDG_PACKET pReceivedPackets;
//
// last packet before a gap
//
PDG_PACKET pLastConsecutivePacket;
//
// used to be ReceiveWindowSize
//
unsigned short Reserved1;
//
// First fragment we should keep. Elder fragments belong to a previous
// pipe buffer.
//
unsigned short ReceiveFragmentBase;
//
// Length of the underlying transport's socket buffer.
//
unsigned TransportBufferLength;
//
// Number of bytes in consecutive fragments.
//
unsigned ConsecutiveDataBytes;
//
// The last-allocated pipe receive buffer, and its length.
//
void __RPC_FAR *LastReceiveBuffer;
unsigned LastReceiveBufferLength;
boolean fReceivedAllFragments;
boolean fRetransmitted;
unsigned RepeatedFack;
DG_COMMON_CONNECTION * BaseConnection;
//--------------------------------------------------------------------
RPC_STATUS
PushBuffer(
PRPC_MESSAGE Message
);
RPC_STATUS
PopBuffer(
BOOL fSendPackets
);
RPC_STATUS
FixupPartialSend(
RPC_MESSAGE * Message
);
void
CommonFreeBuffer(
RPC_MESSAGE * Message
);
RPC_STATUS
CommonGetBuffer(
RPC_MESSAGE * MEssage
);
RPC_STATUS
CommonReallocBuffer(
IN RPC_MESSAGE * Message,
IN unsigned int NewSize
);
void
ReadConnectionInfo(
DG_COMMON_CONNECTION * a_Connection,
DG_TRANSPORT_ADDRESS a_RemoteAddress
);
void NewCall();
RPC_STATUS
SetupSendWindow(
PRPC_MESSAGE Message
);
void CleanupSendWindow();
void CleanupReceiveWindow();
RPC_STATUS
SendFragment(
unsigned FragNum,
unsigned char PacketType,
BOOL fFack
);
RPC_STATUS
SendFackOrNocall(
PDG_PACKET pPacket,
unsigned char PacketType
);
RPC_STATUS
UpdateSendWindow(
PDG_PACKET pPacket,
BOOL * pfUpdated
);
BOOL
UpdateReceiveWindow(
PDG_PACKET pPacket
);
RPC_STATUS
AssembleBufferFromPackets(
IN OUT RPC_MESSAGE * Message,
IN CALL * Call
);
void SetFragmentLengths();
void RecalcReceiveWindow();
unsigned short LastConsecutiveFragment()
{
if (0 == pLastConsecutivePacket)
{
return 0xffff;
}
else
{
return pLastConsecutivePacket->GetFragmentNumber();
}
}
void MarkAllPacketsReceived()
{
ASSERT( FirstUnsentFragment > FinalSendFrag );
unsigned short Diff = FinalSendFrag+1 - SendWindowBase;
ASSERT(Diff <= MAX_WINDOW_SIZE);
ASSERT( SendWindowBase+Diff <= FirstUnsentFragment );
SendWindowBase += Diff;
RingBufferBase += Diff;
RingBufferBase %= MAX_WINDOW_SIZE;
PopBuffer(TRUE);
}
BOOL
IsBufferAcknowledged(
)
{
if (SendWindowBase > FinalSendFrag)
{
return TRUE;
}
return FALSE;
}
BOOL
IsBufferSent(
)
{
if (FirstUnsentFragment > FinalSendFrag)
{
return TRUE;
}
return FALSE;
}
inline void
AddSerialNumber(
UNALIGNED NCA_PACKET_HEADER *pHeader
);
private:
QUEUED_BUFFER * QueuedBufferHead;
QUEUED_BUFFER * QueuedBufferTail;
PDG_PACKET CachedPacket;
void
SetCurrentBuffer(
void * a_Buffer,
unsigned a_BufferLength,
unsigned long BufferFlags
);
};
typedef DG_PACKET_ENGINE * PDG_PACKET_ENGINE;
inline void
SetSerialNumber(
UNALIGNED NCA_PACKET_HEADER *pHeader,
unsigned short SerialNumber
)
{
pHeader->SerialLo = SerialNumber & 0x00ffU;
pHeader->DataRep[3] = (unsigned char) (SerialNumber >> 8);
}
inline void
DG_PACKET_ENGINE::AddSerialNumber(
UNALIGNED NCA_PACKET_HEADER *pHeader
)
{
SetSerialNumber(pHeader, SendSerialNumber);
}
extern unsigned long ProcessStartTime;
inline void
CleanupPacket(
NCA_PACKET_HEADER * pHeader
)
{
pHeader->RpcVersion = DG_RPC_PROTOCOL_VERSION;
pHeader->ServerBootTime = ProcessStartTime;
SetMyDataRep(pHeader);
pHeader->PacketFlags &= DG_PF_IDEMPOTENT;
pHeader->PacketFlags2 = 0;
pHeader->AuthProto = 0;
}
//------------------------------------------------------------------------
RPC_STATUS
SendSecurePacket(
IN DG_ENDPOINT * SourceEndpoint,
IN DG_TRANSPORT_ADDRESS RemoteAddress,
IN UNALIGNED NCA_PACKET_HEADER *pHeader,
IN unsigned long DataOffset,
IN SECURITY_CONTEXT * SecurityContext
);
RPC_STATUS
VerifySecurePacket(
PDG_PACKET pPacket,
SECURITY_CONTEXT * pSecurityContext
);
void
InitErrorPacket(
DG_PACKET * Packet,
unsigned char PacketType,
RPC_STATUS RpcStatus
);
void
DumpBuffer(
void FAR * Buffer,
unsigned Length
);
extern void EnableGlobalScavenger();
extern DELAYED_ACTION_TABLE * DelayedProcedures;
extern unsigned RandomCounter;
inline unsigned GetRandomCounter()
{
::RandomCounter *= 37;
::RandomCounter += GetTickCount();
return ::RandomCounter;
}
#endif // __DGPKT_HXX__