1686 lines
33 KiB
C++
1686 lines
33 KiB
C++
/*++ b
|
||
|
||
Copyright (C) Microsoft Corporation, 1993 - 1999
|
||
|
||
Module Name:
|
||
|
||
dgclnt.hxx
|
||
|
||
Abstract:
|
||
|
||
This file contains the definitions used by the datagram client.
|
||
|
||
Revision History:
|
||
|
||
NT 3.5 was the first version shipped, supporting IPX and UDP. (connieh)
|
||
NT 3.51 added secure calls over NTLM and DEC Kerberos. (jroberts)
|
||
NT 4.0 added sliding window, larger packet sizes, cancels. (jroberts)
|
||
NT 5.0 added asynchronous calls and SSL/PCT security. (jroberts)
|
||
|
||
--*/
|
||
|
||
#ifndef __DGCLNT_HXX__
|
||
#define __DGCLNT_HXX__
|
||
|
||
class DG_CCALL;
|
||
typedef DG_CCALL * PDG_CCALL;
|
||
|
||
class DG_CCONNECTION;
|
||
typedef DG_CCONNECTION * PDG_CCONNECTION;
|
||
|
||
class DG_CASSOCIATION;
|
||
typedef DG_CASSOCIATION * PDG_CASSOCIATION;
|
||
|
||
class DG_BINDING_HANDLE;
|
||
typedef DG_BINDING_HANDLE * PDG_BINDING_HANDLE;
|
||
|
||
|
||
class INTERFACE_AND_OBJECT_LIST
|
||
{
|
||
public:
|
||
|
||
inline
|
||
INTERFACE_AND_OBJECT_LIST(
|
||
)
|
||
{
|
||
Head = 0;
|
||
Cache1Available = TRUE;
|
||
Cache2Available = TRUE;
|
||
}
|
||
|
||
~INTERFACE_AND_OBJECT_LIST(
|
||
);
|
||
|
||
BOOL
|
||
Insert(
|
||
void * Interface,
|
||
RPC_UUID * Object
|
||
);
|
||
|
||
BOOL
|
||
Find(
|
||
void * Interface,
|
||
RPC_UUID * Object
|
||
);
|
||
|
||
BOOL
|
||
Delete(
|
||
void * Interface,
|
||
RPC_UUID * Object
|
||
);
|
||
|
||
private:
|
||
|
||
#define MAX_ELEMENTS 10
|
||
|
||
struct INTERFACE_AND_OBJECT
|
||
{
|
||
INTERFACE_AND_OBJECT * Next;
|
||
void * Interface;
|
||
RPC_UUID Object;
|
||
|
||
inline void
|
||
Update(
|
||
void * a_Interface,
|
||
RPC_UUID * a_Object
|
||
)
|
||
{
|
||
Interface = a_Interface;
|
||
Object = *a_Object;
|
||
}
|
||
};
|
||
|
||
INTERFACE_AND_OBJECT * Head;
|
||
|
||
unsigned Cache1Available : 1;
|
||
unsigned Cache2Available : 1;
|
||
|
||
INTERFACE_AND_OBJECT Cache1;
|
||
INTERFACE_AND_OBJECT Cache2;
|
||
};
|
||
|
||
|
||
class DG_CCONNECTION : public DG_COMMON_CONNECTION
|
||
{
|
||
public:
|
||
|
||
long TimeStamp;
|
||
DG_CCONNECTION * Next;
|
||
|
||
boolean CallbackCompleted;
|
||
boolean fServerSupportsAsync;
|
||
boolean fSecurePacketReceived;
|
||
boolean ServerResponded;
|
||
|
||
boolean fBusy;
|
||
boolean InConnectionTable;
|
||
signed char AckPending;
|
||
boolean AckOrphaned;
|
||
|
||
boolean PossiblyRunDown;
|
||
boolean fAutoReconnect;
|
||
boolean fError;
|
||
|
||
DWORD ThreadId;
|
||
PDG_BINDING_HANDLE BindingHandle;
|
||
int AssociationKey;
|
||
PDG_CASSOCIATION Association;
|
||
|
||
PDG_CCALL CurrentCall;
|
||
|
||
//--------------------------------------------------------------------
|
||
|
||
DG_CCALL * AllocateCall();
|
||
|
||
inline void
|
||
AddCallToCache(
|
||
PDG_CCALL Call
|
||
);
|
||
|
||
RPC_STATUS
|
||
BeginCall(
|
||
IN PDG_CCALL Call
|
||
);
|
||
|
||
void
|
||
EndCall(
|
||
IN PDG_CCALL Call
|
||
);
|
||
|
||
long DecrementRefCount();
|
||
long DecrementRefCountAndKeepMutex();
|
||
|
||
void
|
||
IncrementRefCount(
|
||
void
|
||
);
|
||
|
||
inline int
|
||
IsSupportedAuthInfo(
|
||
IN const CLIENT_AUTH_INFO * ClientAuthInfo
|
||
);
|
||
|
||
RPC_STATUS
|
||
DealWithAuthCallback(
|
||
IN void * InToken,
|
||
IN long InTokenLengh,
|
||
OUT void * OutToken,
|
||
OUT long MaxOutTokenLength,
|
||
OUT long * OutTokenLength
|
||
);
|
||
|
||
RPC_STATUS
|
||
DealWithAuthMore(
|
||
IN long Index,
|
||
OUT void * OutToken,
|
||
OUT long MaxOutTokenLength,
|
||
OUT long * OutTokenLength
|
||
);
|
||
|
||
DG_CCONNECTION(
|
||
IN PDG_CASSOCIATION a_Association,
|
||
IN const CLIENT_AUTH_INFO * AuthInfo,
|
||
IN OUT RPC_STATUS * pStatus
|
||
);
|
||
|
||
~DG_CCONNECTION();
|
||
|
||
void PostDelayedAck();
|
||
void SendDelayedAck();
|
||
void CancelDelayedAck(
|
||
BOOL Flush = FALSE
|
||
);
|
||
|
||
inline void UpdateAssociation();
|
||
|
||
RPC_STATUS
|
||
UpdateServerAddress(
|
||
IN DG_PACKET * Packet,
|
||
IN DG_TRANSPORT_ADDRESS Address
|
||
);
|
||
|
||
void EnableOverlappedCalls();
|
||
|
||
unsigned long
|
||
GetSequenceNumber()
|
||
{
|
||
return LowestActiveSequence;
|
||
}
|
||
|
||
unsigned long
|
||
GetLowestActiveSequence()
|
||
{
|
||
return LowestActiveSequence;
|
||
}
|
||
|
||
RPC_STATUS WillNextCallBeQueued();
|
||
|
||
RPC_STATUS MaybeTransmitNextCall();
|
||
|
||
DG_CCALL *
|
||
FindIdleCalls(
|
||
long CurrentTime
|
||
);
|
||
|
||
void
|
||
DispatchPacket(
|
||
PDG_PACKET Packet,
|
||
void * Address
|
||
);
|
||
|
||
inline unsigned long CurrentSequenceNumber();
|
||
|
||
virtual RPC_STATUS
|
||
SealAndSendPacket(
|
||
IN DG_ENDPOINT * SourceEndpoint,
|
||
IN DG_TRANSPORT_ADDRESS RemoteAddress,
|
||
IN UNALIGNED NCA_PACKET_HEADER * Header,
|
||
IN unsigned long BufferOffset
|
||
);
|
||
|
||
RPC_STATUS
|
||
VerifyPacket(
|
||
IN DG_PACKET * Packet
|
||
);
|
||
|
||
static inline DG_CCONNECTION *
|
||
FromHashNode(
|
||
IN UUID_HASH_TABLE_NODE * Node
|
||
)
|
||
{
|
||
return CONTAINING_RECORD( Node, DG_CCONNECTION, ActivityNode );
|
||
}
|
||
|
||
inline void *
|
||
operator new(
|
||
IN size_t ObjectLength,
|
||
IN const RPC_DATAGRAM_TRANSPORT * Transport
|
||
);
|
||
|
||
void WaitForNoReferences()
|
||
{
|
||
while (ReferenceCount)
|
||
{
|
||
Sleep(10);
|
||
}
|
||
|
||
fBusy = FALSE;
|
||
}
|
||
|
||
RPC_STATUS
|
||
TransferCallsToNewConnection(
|
||
PDG_CCALL FirstCall,
|
||
PDG_CCONNECTION NewConnection
|
||
);
|
||
|
||
const CLIENT_AUTH_INFO *
|
||
InqAuthInfo()
|
||
{
|
||
return &AuthInfo;
|
||
}
|
||
|
||
BOOL MutexTryRequest()
|
||
{
|
||
BOOL result = Mutex.TryRequest();
|
||
|
||
if (result)
|
||
{
|
||
LogEvent( SU_MUTEX, EV_INC, this, 0, 0, TRUE, 1);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
void MutexRequest()
|
||
{
|
||
Mutex.Request();
|
||
|
||
LogEvent( SU_MUTEX, EV_INC, this, 0, 0, TRUE, 1);
|
||
|
||
#ifdef CHECK_MUTEX_INVERSION
|
||
ThreadSelf()->ConnectionMutexHeld = this;
|
||
#endif
|
||
}
|
||
|
||
void MutexClear()
|
||
{
|
||
LogEvent( SU_MUTEX, EV_DEC, this, 0, 0, TRUE, 1);
|
||
Mutex.Clear();
|
||
|
||
#ifdef CHECK_MUTEX_INVERSION
|
||
ThreadSelf()->ConnectionMutexHeld = 0;
|
||
#endif
|
||
}
|
||
|
||
private:
|
||
|
||
CLIENT_AUTH_INFO AuthInfo;
|
||
DELAYED_ACTION_NODE DelayedAckTimer;
|
||
|
||
unsigned SecurityContextId;
|
||
|
||
long LastScavengeTime;
|
||
|
||
unsigned CachedCallCount;
|
||
PDG_CCALL CachedCalls;
|
||
|
||
PDG_CCALL ActiveCallHead;
|
||
PDG_CCALL ActiveCallTail;
|
||
|
||
//--------------------------------------------------------------------
|
||
|
||
RPC_STATUS InitializeSecurityContext();
|
||
|
||
unsigned char * SecurityBuffer;
|
||
long SecurityBufferLength;
|
||
|
||
public:
|
||
|
||
long LastCallbackTime;
|
||
};
|
||
|
||
NEW_SDICT(DG_CCONNECTION);
|
||
|
||
|
||
inline void *
|
||
DG_CCONNECTION::operator new(
|
||
IN size_t ObjectLength,
|
||
IN const RPC_DATAGRAM_TRANSPORT * Transport
|
||
)
|
||
{
|
||
return new char[ObjectLength + Transport->AddressSize];
|
||
}
|
||
|
||
inline void
|
||
DG_CCONNECTION::IncrementRefCount()
|
||
{
|
||
Mutex.VerifyOwned();
|
||
|
||
++ReferenceCount;
|
||
LogEvent(SU_CCONN, EV_INC, this, 0, ReferenceCount, TRUE);
|
||
}
|
||
|
||
|
||
class DG_CCALL : public CCALL, public DG_PACKET_ENGINE
|
||
{
|
||
friend RPC_STATUS DG_CCONNECTION::WillNextCallBeQueued();
|
||
|
||
public:
|
||
|
||
//
|
||
// The call's Next pointer is NOT_ACTIVE until the call is added
|
||
// to a connection's active call list.
|
||
//
|
||
#define DG_CCALL_NOT_ACTIVE ((DG_CCALL *) (~0))
|
||
|
||
long TimeStamp;
|
||
|
||
DG_CCALL * Next;
|
||
DG_CCALL * Previous;
|
||
|
||
boolean LastSendTimedOut;
|
||
boolean CancelPending;
|
||
boolean CancelComplete;
|
||
boolean AutoReconnectOk;
|
||
|
||
//-----------------------------------------------
|
||
|
||
DG_CCALL(
|
||
IN PDG_CCONNECTION Connection,
|
||
OUT RPC_STATUS * pStatus
|
||
);
|
||
|
||
virtual
|
||
~DG_CCALL();
|
||
|
||
RPC_STATUS
|
||
DispatchPacket(
|
||
PDG_PACKET Packet
|
||
);
|
||
|
||
inline void IncrementRefCount();
|
||
long DecrementRefCount();
|
||
long DecrementRefCountAndKeepMutex();
|
||
|
||
//------------------------------------------------
|
||
//
|
||
// implementations of CCALL virtual functions
|
||
//
|
||
|
||
virtual RPC_STATUS
|
||
NegotiateTransferSyntax (
|
||
IN OUT PRPC_MESSAGE Message
|
||
)
|
||
{
|
||
// datagrams don't support multiple syntax
|
||
// negotiation. They always return the transfer
|
||
// syntax the stub prefers
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
virtual RPC_STATUS
|
||
GetBuffer (
|
||
IN OUT PRPC_MESSAGE Message,
|
||
IN UUID *ObjectUuid = 0
|
||
);
|
||
|
||
virtual RPC_STATUS
|
||
SendReceive (
|
||
IN OUT PRPC_MESSAGE Message
|
||
);
|
||
|
||
virtual RPC_STATUS
|
||
Send(
|
||
PRPC_MESSAGE Message
|
||
);
|
||
|
||
virtual RPC_STATUS
|
||
Receive(
|
||
PRPC_MESSAGE Message,
|
||
unsigned MinimumSize
|
||
);
|
||
|
||
virtual RPC_STATUS
|
||
AsyncSend(
|
||
PRPC_MESSAGE Message
|
||
);
|
||
|
||
virtual RPC_STATUS
|
||
AsyncReceive(
|
||
PRPC_MESSAGE Message,
|
||
unsigned MinimumSize
|
||
);
|
||
|
||
virtual void
|
||
FreeBuffer (
|
||
IN PRPC_MESSAGE Message
|
||
);
|
||
|
||
virtual void
|
||
FreePipeBuffer (
|
||
IN PRPC_MESSAGE Message
|
||
) ;
|
||
|
||
virtual RPC_STATUS
|
||
ReallocPipeBuffer (
|
||
IN PRPC_MESSAGE Message,
|
||
IN unsigned int NewSize
|
||
) ;
|
||
|
||
virtual BOOL
|
||
IssueNotification (
|
||
IN RPC_ASYNC_EVENT Event
|
||
) ;
|
||
|
||
virtual void
|
||
FreeAPCInfo (
|
||
IN RPC_APC_INFO *pAPCInfo
|
||
) ;
|
||
|
||
RPC_STATUS
|
||
CancelAsyncCall (
|
||
IN BOOL fAbort
|
||
);
|
||
|
||
void SendAck();
|
||
|
||
virtual RPC_STATUS
|
||
Cancel(
|
||
void * ThreadHandle
|
||
);
|
||
|
||
virtual unsigned TestCancel();
|
||
|
||
void ExecuteDelayedSend();
|
||
|
||
RPC_STATUS SendSomeFragments();
|
||
|
||
inline RPC_STATUS
|
||
GetInitialBuffer(
|
||
IN OUT RPC_MESSAGE * Message,
|
||
IN UUID *MyObjectUuid
|
||
);
|
||
|
||
inline void
|
||
SwitchConnection(
|
||
PDG_CCONNECTION NewConnection
|
||
);
|
||
|
||
BOOL IsBroadcast()
|
||
{
|
||
if (BasePacketFlags & RPC_NCA_FLAGS_BROADCAST)
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
RPC_STATUS
|
||
ProcessFaultOrRejectData(
|
||
PDG_PACKET Packet
|
||
);
|
||
|
||
BOOL
|
||
InProgress()
|
||
{
|
||
if (AsyncStatus == RPC_S_ASYNC_CALL_PENDING)
|
||
{
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
private:
|
||
|
||
enum DG_CLIENT_STATE
|
||
{
|
||
CallInit = 0x900,
|
||
CallQuiescent,
|
||
CallSend,
|
||
CallSendReceive,
|
||
CallReceive,
|
||
CallCancellingSend,
|
||
CallComplete
|
||
};
|
||
|
||
DG_CLIENT_STATE State;
|
||
DG_CLIENT_STATE PreviousState;
|
||
|
||
PRPC_CLIENT_INTERFACE InterfacePointer;
|
||
PDG_CCONNECTION Connection;
|
||
|
||
DELAYED_ACTION_NODE TransmitTimer;
|
||
|
||
// unused
|
||
unsigned WorkingCount;
|
||
unsigned UnansweredRequestCount;
|
||
long ReceiveTimeout;
|
||
unsigned long PipeReceiveSize;
|
||
|
||
long TimeoutLimit;
|
||
long LastReceiveTime;
|
||
long CancelTime;
|
||
|
||
boolean StaticArgsSent;
|
||
boolean AllArgsSent;
|
||
boolean _unused;
|
||
boolean ForceAck;
|
||
|
||
long DelayedSendPending;
|
||
|
||
// Extended Error Info stuff
|
||
// used in async calls only to hold
|
||
// information b/n call failure and
|
||
// RpcAsyncCompleteCall
|
||
ExtendedErrorInfo *EEInfo;
|
||
|
||
//--------------------------------------------------------------------
|
||
|
||
RPC_STATUS
|
||
BeforeSendReceive(
|
||
PRPC_MESSAGE Message
|
||
);
|
||
|
||
RPC_STATUS
|
||
AfterSendReceive(
|
||
PRPC_MESSAGE Message,
|
||
RPC_STATUS Status
|
||
);
|
||
|
||
RPC_STATUS
|
||
MaybeSendReceive(
|
||
IN OUT PRPC_MESSAGE Message
|
||
);
|
||
|
||
void
|
||
BuildNcaPacketHeader(
|
||
OUT PNCA_PACKET_HEADER pNcaPacketHeader,
|
||
IN OUT PRPC_MESSAGE Message
|
||
);
|
||
|
||
RPC_STATUS AttemptAutoReconnect();
|
||
|
||
BOOL CheckForCancelTimeout();
|
||
|
||
void PostDelayedSend();
|
||
void CancelDelayedSend();
|
||
void SendDelayedAck();
|
||
|
||
RPC_STATUS
|
||
SendFragment(
|
||
PRPC_MESSAGE pMessage,
|
||
PNCA_PACKET_HEADER pBaseHeader
|
||
);
|
||
|
||
RPC_STATUS SendQuit();
|
||
|
||
RPC_STATUS SendPing();
|
||
|
||
RPC_STATUS ReceiveSinglePacket();
|
||
|
||
//-----------------------------------------------
|
||
|
||
RPC_STATUS
|
||
DealWithNocall(
|
||
PDG_PACKET pPacket
|
||
);
|
||
|
||
RPC_STATUS
|
||
DealWithFault(
|
||
PDG_PACKET pPacket
|
||
);
|
||
|
||
RPC_STATUS
|
||
DealWithReject(
|
||
PDG_PACKET pPacket
|
||
);
|
||
|
||
RPC_STATUS
|
||
DealWithWorking(
|
||
PDG_PACKET pPacket
|
||
);
|
||
|
||
RPC_STATUS
|
||
DealWithResponse(
|
||
PDG_PACKET pPacket
|
||
);
|
||
|
||
RPC_STATUS
|
||
DealWithFack(
|
||
PDG_PACKET pPacket
|
||
);
|
||
|
||
RPC_STATUS
|
||
DealWithQuack(
|
||
PDG_PACKET pPacket
|
||
);
|
||
|
||
RPC_STATUS
|
||
DealWithTimeout();
|
||
|
||
RPC_STATUS
|
||
DealWithRequest(
|
||
IN PDG_PACKET Packet,
|
||
IN DG_TRANSPORT_ADDRESS RemoteAddress
|
||
);
|
||
|
||
void IncreaseReceiveTimeout();
|
||
|
||
RPC_STATUS
|
||
MapErrorCode(
|
||
RPC_STATUS Status
|
||
);
|
||
|
||
RPC_STATUS
|
||
GetEndpoint(
|
||
DWORD EndpointFlags
|
||
);
|
||
|
||
void
|
||
SetState(
|
||
IN DG_CLIENT_STATE NewState
|
||
)
|
||
{
|
||
if (NewState != State)
|
||
{
|
||
LogEvent(SU_CCALL, EV_STATE, this, 0, NewState);
|
||
}
|
||
|
||
PreviousState = State;
|
||
State = NewState;
|
||
}
|
||
};
|
||
|
||
|
||
class DG_CASSOCIATION : public GENERIC_OBJECT
|
||
{
|
||
friend class DG_ASSOCIATION_TABLE;
|
||
|
||
public:
|
||
|
||
RPC_DATAGRAM_TRANSPORT * TransportInterface;
|
||
|
||
unsigned long ServerBootTime;
|
||
unsigned long ServerDataRep;
|
||
|
||
unsigned CurrentPduSize;
|
||
unsigned RemoteWindowSize;
|
||
|
||
boolean fServerSupportsAsync;
|
||
boolean fLoneBindingHandle;
|
||
|
||
enum
|
||
{
|
||
BROADCAST = 0x100,
|
||
UNRESOLVEDEP = 0x200
|
||
};
|
||
|
||
//----------------------------------------------------------
|
||
|
||
DG_CASSOCIATION(
|
||
IN RPC_DATAGRAM_TRANSPORT * a_Transport,
|
||
IN LONG a_AssociationFlag,
|
||
IN DCE_BINDING * a_DceBinding,
|
||
IN BOOL a_Unique,
|
||
IN OUT RPC_STATUS * pStatus
|
||
);
|
||
|
||
~DG_CASSOCIATION();
|
||
|
||
RPC_STATUS
|
||
SendPacket(
|
||
IN DG_ENDPOINT Endpoint,
|
||
IN PNCA_PACKET_HEADER Header,
|
||
IN unsigned SecurityTrailerLength = 0
|
||
);
|
||
|
||
virtual RPC_STATUS
|
||
ToStringBinding (
|
||
OUT RPC_CHAR * * StringBinding,
|
||
IN RPC_UUID * ObjectUuid
|
||
);
|
||
|
||
void IncrementRefCount();
|
||
void DecrementRefCount();
|
||
|
||
int
|
||
CompareWithBinding(
|
||
IN PDG_BINDING_HANDLE pBinding
|
||
);
|
||
|
||
BOOL
|
||
ComparePartialBinding(
|
||
IN PDG_BINDING_HANDLE pBinding,
|
||
void * Interface
|
||
);
|
||
|
||
BOOL
|
||
AddInterface(
|
||
void * InterfaceInformation,
|
||
RPC_UUID * ObjectUuid
|
||
);
|
||
|
||
BOOL
|
||
RemoveInterface(
|
||
void * InterfaceInformation,
|
||
RPC_UUID * ObjectUuid
|
||
);
|
||
|
||
RPC_STATUS
|
||
AllocateCall(
|
||
IN PDG_BINDING_HANDLE BindingHandle,
|
||
IN const CLIENT_AUTH_INFO * AuthInfo,
|
||
OUT PDG_CCALL * ppCall,
|
||
IN BOOL fAsync
|
||
);
|
||
|
||
void
|
||
ReleaseCall(
|
||
IN PDG_CCALL Call
|
||
);
|
||
|
||
PDG_CCONNECTION
|
||
AllocateConnection(
|
||
IN PDG_BINDING_HANDLE BindingHandle,
|
||
IN const CLIENT_AUTH_INFO * AuthInfo,
|
||
IN DWORD ThreadId,
|
||
IN BOOL fAsync,
|
||
OUT RPC_STATUS * pStatus
|
||
);
|
||
|
||
void
|
||
ReleaseConnection(
|
||
IN PDG_CCONNECTION Call
|
||
);
|
||
|
||
void
|
||
DeleteIdleConnections(
|
||
long CurrentTime
|
||
);
|
||
|
||
RPC_STATUS
|
||
UpdateAssociationWithAddress(
|
||
PDG_PACKET Packet,
|
||
void * Address
|
||
);
|
||
|
||
BOOL SendKeepAlive();
|
||
|
||
DCE_BINDING * DuplicateDceBinding ();
|
||
|
||
void SetErrorFlag () { fErrorFlag = TRUE; }
|
||
void ClearErrorFlag() { fErrorFlag = FALSE; }
|
||
BOOL ErrorFlag () { return fErrorFlag; }
|
||
|
||
DG_TRANSPORT_ADDRESS
|
||
InqServerAddress ()
|
||
{
|
||
return ServerAddress;
|
||
}
|
||
|
||
void
|
||
CopyServerAddress(
|
||
IN DG_TRANSPORT_ADDRESS Destination
|
||
);
|
||
|
||
inline void *
|
||
operator new(
|
||
IN size_t ObjectLength,
|
||
IN const RPC_DATAGRAM_TRANSPORT * Transport
|
||
);
|
||
|
||
BOOL IsAckPending();
|
||
|
||
void FlushAcks();
|
||
|
||
void IncrementBindingRefCount(
|
||
unsigned ContextHandleRef
|
||
);
|
||
|
||
void DecrementBindingRefCount(
|
||
unsigned ContextHandleRef
|
||
);
|
||
|
||
void VerifyNotLocked()
|
||
{
|
||
Mutex.VerifyNotOwned();
|
||
}
|
||
|
||
BOOL LockOwnedByMe()
|
||
{
|
||
return Mutex.OwnedByMe();
|
||
}
|
||
|
||
private:
|
||
|
||
void MutexRequest()
|
||
{
|
||
#ifdef CHECK_MUTEX_INVERSION
|
||
if (!Mutex.OwnedByMe() )
|
||
{
|
||
DG_CCONNECTION * conn = (DG_CCONNECTION *) ThreadSelf()->ConnectionMutexHeld;
|
||
|
||
ASSERT( 0 == conn || conn->ThreadId == GetCurrentThreadId() );
|
||
}
|
||
#endif
|
||
|
||
Mutex.Request();
|
||
}
|
||
|
||
void MutexClear()
|
||
{
|
||
Mutex.Clear();
|
||
}
|
||
|
||
INTERLOCKED_INTEGER ReferenceCount;
|
||
MUTEX Mutex;
|
||
|
||
LONG AssociationFlag;
|
||
|
||
boolean fErrorFlag;
|
||
|
||
DCE_BINDING * pDceBinding;
|
||
|
||
long LastScavengeTime;
|
||
|
||
DG_TRANSPORT_ADDRESS ServerAddress;
|
||
|
||
DG_CCONNECTION_DICT ActiveConnections;
|
||
DG_CCONNECTION_DICT InactiveConnections;
|
||
|
||
INTERFACE_AND_OBJECT_LIST InterfaceAndObjectDict;
|
||
|
||
RPC_CHAR * ResolvedEndpoint;
|
||
|
||
long BindingHandleReferences;
|
||
long InternalTableIndex;
|
||
|
||
DG_BINDING_HANDLE * KeepAliveHandle;
|
||
|
||
public:
|
||
|
||
long LastReceiveTime;
|
||
};
|
||
|
||
|
||
inline DCE_BINDING *
|
||
DG_CASSOCIATION::DuplicateDceBinding (
|
||
)
|
||
{
|
||
CLAIM_MUTEX lock( Mutex );
|
||
|
||
ASSERT( !InvalidHandle(DG_CASSOCIATION_TYPE) );
|
||
return(pDceBinding->DuplicateDceBinding());
|
||
}
|
||
|
||
inline
|
||
void
|
||
DG_CASSOCIATION::IncrementRefCount(
|
||
void
|
||
)
|
||
{
|
||
ASSERT( !InvalidHandle(DG_CASSOCIATION_TYPE) );
|
||
|
||
long Count = ReferenceCount.Increment();
|
||
|
||
LogEvent(SU_CASSOC, EV_INC, this, 0, Count);
|
||
}
|
||
|
||
inline void *
|
||
DG_CASSOCIATION::operator new(
|
||
IN size_t ObjectLength,
|
||
IN const RPC_DATAGRAM_TRANSPORT * Transport
|
||
)
|
||
{
|
||
return new char[ObjectLength + 2 * Transport->AddressSize];
|
||
}
|
||
|
||
|
||
class DG_ASSOCIATION_TABLE
|
||
{
|
||
public:
|
||
|
||
BOOL fCasUuidReady;
|
||
UUID CasUuid;
|
||
|
||
//--------------------------------------------------------------------
|
||
|
||
typedef LONG HINT;
|
||
|
||
DG_ASSOCIATION_TABLE(
|
||
RPC_STATUS * pStatus
|
||
);
|
||
|
||
~DG_ASSOCIATION_TABLE()
|
||
{
|
||
if (Associations != InitialAssociations)
|
||
delete Associations;
|
||
}
|
||
|
||
HINT
|
||
MakeHint(
|
||
DCE_BINDING * pDceBinding
|
||
);
|
||
|
||
RPC_STATUS
|
||
Add(
|
||
DG_CASSOCIATION * Association
|
||
);
|
||
|
||
DG_CASSOCIATION *
|
||
Find(
|
||
DG_BINDING_HANDLE * Binding,
|
||
RPC_CLIENT_INTERFACE * Interface,
|
||
BOOL fContextHandle,
|
||
BOOL fPartial,
|
||
BOOL fReconnect
|
||
);
|
||
|
||
void
|
||
Delete(
|
||
DG_CASSOCIATION * Association
|
||
);
|
||
|
||
BOOL
|
||
DeleteIdleEntries(
|
||
long CurrentTime
|
||
);
|
||
|
||
BOOL
|
||
SendContextHandleKeepalives();
|
||
|
||
void
|
||
IncrementContextHandleCount(
|
||
DG_CASSOCIATION * Association
|
||
);
|
||
|
||
void
|
||
DecrementContextHandleCount(
|
||
DG_CASSOCIATION * Association
|
||
);
|
||
|
||
long
|
||
GetContextHandleCount(
|
||
DG_CASSOCIATION * Association
|
||
);
|
||
|
||
void
|
||
UpdateTimeStamp(
|
||
DG_CASSOCIATION * Association
|
||
);
|
||
|
||
void LockExclusive()
|
||
{
|
||
Mutex.LockExclusive();
|
||
}
|
||
|
||
void UnlockExclusive()
|
||
{
|
||
Mutex.UnlockExclusive();
|
||
}
|
||
|
||
private:
|
||
|
||
struct NODE
|
||
{
|
||
DG_CASSOCIATION * Association;
|
||
HINT Hint;
|
||
BOOL fBusy;
|
||
long ContextHandleCount;
|
||
long TimeStamp;
|
||
};
|
||
|
||
enum
|
||
{
|
||
INITIAL_ARRAY_LENGTH = 4,
|
||
MINIMUM_IDLE_ENTRIES = 10
|
||
};
|
||
|
||
CSharedLock Mutex;
|
||
NODE * Associations;
|
||
LONG AssociationsLength;
|
||
|
||
NODE InitialAssociations[ INITIAL_ARRAY_LENGTH ];
|
||
|
||
long PreviousFreedCount;
|
||
};
|
||
|
||
extern DG_ASSOCIATION_TABLE * ActiveAssociations;
|
||
|
||
|
||
inline void
|
||
DG_CASSOCIATION::IncrementBindingRefCount(
|
||
unsigned ContextHandleRef
|
||
)
|
||
{
|
||
ASSERT( ContextHandleRef <= 1 );
|
||
// ASSERT( ContextHandleReferences < 100 );
|
||
// ASSERT( BindingHandleReferences < 100 );
|
||
|
||
++BindingHandleReferences;
|
||
|
||
if (ContextHandleRef)
|
||
{
|
||
ActiveAssociations->IncrementContextHandleCount(this);
|
||
}
|
||
|
||
IncrementRefCount();
|
||
}
|
||
|
||
|
||
inline void
|
||
DG_CASSOCIATION::DecrementBindingRefCount(
|
||
unsigned ContextHandleRef
|
||
)
|
||
{
|
||
ASSERT( ContextHandleRef <= 1 );
|
||
ASSERT( BindingHandleReferences > 0 );
|
||
|
||
if (ContextHandleRef)
|
||
{
|
||
ActiveAssociations->DecrementContextHandleCount(this);
|
||
}
|
||
|
||
// ASSERT( ContextHandleReferences >= 0 );
|
||
|
||
if (0 == --BindingHandleReferences)
|
||
{
|
||
FlushAcks();
|
||
}
|
||
|
||
DecrementRefCount();
|
||
}
|
||
|
||
|
||
class DG_BINDING_HANDLE : public BINDING_HANDLE
|
||
|
||
/*++
|
||
|
||
Class Description:
|
||
|
||
This class represents a handle pointing at a particular server/endpoint.
|
||
|
||
Fields:
|
||
|
||
pDceBinding - Until a DG_CASSOCIATION is found (or created) for this
|
||
binding handle, pDceBinding will point at the appropriate DCE_BINDING.
|
||
|
||
Mutex - Protects this binding handle.
|
||
|
||
ReferenceCount - Number of DG_CCALLs currently associated with this
|
||
binding handle.
|
||
|
||
DecrementReferenceCount - Decrements the reference count to this binding
|
||
handle. If the reference count hits 0, the binding handle is deleted.
|
||
|
||
DisassociateFromServer - If this is a BH that we couldnt
|
||
successfully use, tear down the association
|
||
|
||
--*/
|
||
|
||
{
|
||
public:
|
||
|
||
DCE_BINDING * pDceBinding;
|
||
|
||
DWORD EndpointFlags;
|
||
|
||
DG_BINDING_HANDLE(
|
||
IN OUT RPC_STATUS * RpcStatus
|
||
);
|
||
|
||
//
|
||
// This is not a general-purpose constructor.
|
||
// The context handle keep-alive code uses it.
|
||
//
|
||
DG_BINDING_HANDLE(
|
||
IN PDG_CASSOCIATION Association,
|
||
IN DCE_BINDING * DceBinding,
|
||
IN OUT RPC_STATUS * RpcStatus
|
||
);
|
||
|
||
~DG_BINDING_HANDLE();
|
||
|
||
virtual RPC_STATUS
|
||
NegotiateTransferSyntax (
|
||
IN OUT PRPC_MESSAGE Message
|
||
)
|
||
{
|
||
// datagrams don't support multiple syntax
|
||
// negotiation. They always return the transfer
|
||
// syntax the stub prefers
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
|
||
RPC_STATUS
|
||
GetBuffer (
|
||
IN OUT PRPC_MESSAGE Message,
|
||
IN UUID *ObjectUuid
|
||
);
|
||
|
||
RPC_STATUS
|
||
BindingCopy (
|
||
OUT BINDING_HANDLE * * DestinationBinding,
|
||
IN unsigned int MaintainContext
|
||
);
|
||
|
||
RPC_STATUS BindingFree ();
|
||
|
||
PDG_CCONNECTION
|
||
GetReplacementConnection(
|
||
PDG_CCONNECTION OldConnection,
|
||
PRPC_CLIENT_INTERFACE Interface
|
||
);
|
||
|
||
RPC_STATUS
|
||
PrepareBindingHandle (
|
||
IN TRANS_INFO * TransportInterface,
|
||
IN DCE_BINDING * DceBinding
|
||
);
|
||
|
||
RPC_STATUS
|
||
ToStringBinding (
|
||
OUT RPC_CHAR * * StringBinding
|
||
);
|
||
|
||
RPC_STATUS
|
||
ResolveBinding (
|
||
IN RPC_CLIENT_INTERFACE * RpcClientInterface
|
||
);
|
||
|
||
RPC_STATUS
|
||
BindingReset ();
|
||
|
||
virtual RPC_STATUS
|
||
InquireTransportType(
|
||
OUT unsigned int * Type
|
||
)
|
||
{
|
||
*Type = TRANSPORT_TYPE_DG;
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
inline void IncrementRefCount()
|
||
{
|
||
long Count = ReferenceCount.Increment();
|
||
|
||
LogEvent(SU_HANDLE, EV_INC, this, 0, Count);
|
||
}
|
||
|
||
void DecrementRefCount();
|
||
|
||
void
|
||
FreeCall(
|
||
DG_CCALL * Call
|
||
);
|
||
|
||
void DisassociateFromServer();
|
||
|
||
unsigned long
|
||
MapAuthenticationLevel (
|
||
IN unsigned long AuthenticationLevel
|
||
);
|
||
|
||
BOOL
|
||
SetTransportAuthentication(
|
||
IN unsigned long ulAuthenticationLevel,
|
||
IN unsigned long ulAuthenticationService,
|
||
OUT RPC_STATUS *pStatus
|
||
);
|
||
|
||
inline BOOL
|
||
IsDynamic()
|
||
{
|
||
return fDynamicEndpoint;
|
||
}
|
||
|
||
RPC_STATUS
|
||
SetTransportOption(
|
||
IN unsigned long option,
|
||
IN ULONG_PTR optionValue
|
||
);
|
||
|
||
RPC_STATUS
|
||
InqTransportOption(
|
||
IN unsigned long option,
|
||
OUT ULONG_PTR * pOptionValue
|
||
);
|
||
|
||
void MutexRequest()
|
||
{
|
||
#ifdef CHECK_MUTEX_INVERSION
|
||
if (!BindingMutex.OwnedByMe() )
|
||
{
|
||
DG_CCONNECTION * conn = (DG_CCONNECTION *) ThreadSelf()->ConnectionMutexHeld;
|
||
|
||
ASSERT( 0 == conn || conn->ThreadId == GetCurrentThreadId() );
|
||
|
||
if (Association)
|
||
{
|
||
if (Association->LockOwnedByMe() == FALSE)
|
||
{
|
||
Association->VerifyNotLocked();
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
BindingMutex.Request();
|
||
}
|
||
|
||
void MutexClear()
|
||
{
|
||
BindingMutex.Clear();
|
||
}
|
||
|
||
private:
|
||
|
||
TRANS_INFO * TransportObject;
|
||
RPC_DATAGRAM_TRANSPORT *TransportInterface;
|
||
DG_CASSOCIATION * Association;
|
||
INTERLOCKED_INTEGER ReferenceCount;
|
||
|
||
boolean fDynamicEndpoint;
|
||
unsigned fContextHandle;
|
||
|
||
|
||
RPC_STATUS
|
||
FindOrCreateAssociation(
|
||
IN const PRPC_CLIENT_INTERFACE Interface,
|
||
IN BOOL fReconnect,
|
||
IN BOOL fBroadcast
|
||
);
|
||
};
|
||
|
||
|
||
inline DG_BINDING_HANDLE::DG_BINDING_HANDLE(
|
||
IN OUT RPC_STATUS * pStatus
|
||
)
|
||
: BINDING_HANDLE (pStatus),
|
||
Association (0),
|
||
ReferenceCount(1),
|
||
pDceBinding (0),
|
||
fContextHandle(0),
|
||
EndpointFlags (0)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The constructor for DG_BINDING_HANDLE. This object represents a
|
||
binding to a server. Most of the important members
|
||
are set in DG_BINDING_HANDLE::PrepareBindingHandle.
|
||
|
||
--*/
|
||
{
|
||
ObjectType = DG_BINDING_HANDLE_TYPE;
|
||
LogEvent(SU_HANDLE, EV_CREATE, this);
|
||
}
|
||
|
||
inline DG_BINDING_HANDLE::DG_BINDING_HANDLE(
|
||
IN PDG_CASSOCIATION a_Association,
|
||
IN DCE_BINDING * a_DceBinding,
|
||
IN OUT RPC_STATUS * a_pStatus
|
||
)
|
||
: BINDING_HANDLE(a_pStatus),
|
||
Association (a_Association),
|
||
ReferenceCount(1),
|
||
pDceBinding (a_DceBinding),
|
||
fContextHandle(0),
|
||
EndpointFlags (0)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The constructor for DG_BINDING_HANDLE. This is a quick and dirty constructor;
|
||
in particular it does not clone the DCE_BINDING.
|
||
|
||
--*/
|
||
{
|
||
ObjectType = DG_BINDING_HANDLE_TYPE;
|
||
LogEvent(SU_HANDLE, EV_CREATE, this, 0, *a_pStatus);
|
||
|
||
if (0 != *a_pStatus)
|
||
{
|
||
Association = 0;
|
||
}
|
||
}
|
||
|
||
|
||
inline DG_BINDING_HANDLE::~DG_BINDING_HANDLE()
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Destructor for the DG_BINDING_HANDLE. Let the association know we aren't
|
||
using it anymore; this may cause it to be deleted.
|
||
|
||
Arguments:
|
||
|
||
<none>
|
||
|
||
Return Value:
|
||
|
||
<none>
|
||
|
||
--*/
|
||
{
|
||
LogEvent(SU_HANDLE, EV_DELETE, this);
|
||
|
||
if (Association != 0)
|
||
{
|
||
Association->DecrementBindingRefCount(fContextHandle);
|
||
}
|
||
|
||
delete pDceBinding;
|
||
}
|
||
|
||
|
||
inline void
|
||
DG_BINDING_HANDLE::DecrementRefCount()
|
||
{
|
||
long Count = ReferenceCount.Decrement();
|
||
|
||
LogEvent(SU_HANDLE, EV_DEC, this, 0, Count, TRUE);
|
||
|
||
if (Count == 0)
|
||
{
|
||
delete this;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
class DG_CLIENT_CALLBACK : public MESSAGE_OBJECT
|
||
{
|
||
public:
|
||
|
||
DG_PACKET * Request;
|
||
DG_CCONNECTION * Connection;
|
||
DG_ENDPOINT * LocalEndpoint;
|
||
DG_TRANSPORT_ADDRESS RemoteAddress;
|
||
|
||
//--------------------------------------------------------------------
|
||
|
||
inline DG_CLIENT_CALLBACK()
|
||
{
|
||
ObjectType = DG_CALLBACK_TYPE;
|
||
Request = 0;
|
||
}
|
||
|
||
inline ~DG_CLIENT_CALLBACK()
|
||
{
|
||
if (Request)
|
||
{
|
||
Request->Free(FALSE);
|
||
}
|
||
}
|
||
|
||
virtual RPC_STATUS
|
||
NegotiateTransferSyntax (
|
||
IN OUT PRPC_MESSAGE Message
|
||
)
|
||
{
|
||
// datagrams don't support multiple syntax
|
||
// negotiation. They always return the transfer
|
||
// syntax the stub prefers
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
virtual RPC_STATUS
|
||
GetBuffer(
|
||
IN OUT PRPC_MESSAGE Message,
|
||
IN UUID *ObjectUuid
|
||
);
|
||
|
||
virtual void
|
||
FreeBuffer(
|
||
IN OUT PRPC_MESSAGE Message
|
||
);
|
||
|
||
// not really implemented
|
||
|
||
virtual RPC_STATUS
|
||
SendReceive (
|
||
IN OUT PRPC_MESSAGE Message
|
||
);
|
||
|
||
virtual RPC_STATUS
|
||
Send(
|
||
PRPC_MESSAGE Message
|
||
);
|
||
|
||
virtual RPC_STATUS
|
||
AsyncSend(
|
||
PRPC_MESSAGE Message
|
||
);
|
||
|
||
virtual RPC_STATUS
|
||
Receive(
|
||
PRPC_MESSAGE Message,
|
||
unsigned MinimumSize
|
||
);
|
||
|
||
virtual RPC_STATUS
|
||
SetAsyncHandle (
|
||
IN RPC_ASYNC_STATE * hAsync
|
||
);
|
||
|
||
virtual BOOL
|
||
IsSyncCall ()
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
inline void
|
||
SendPacket(
|
||
NCA_PACKET_HEADER * Header
|
||
)
|
||
{
|
||
unsigned Frag = (Header->PacketType << 16) | Header->GetFragmentNumber();
|
||
|
||
LogEvent( SU_CCONN, EV_PKT_OUT, Connection, 0, Frag);
|
||
|
||
LocalEndpoint->TransportInterface->Send(
|
||
&LocalEndpoint->TransportEndpoint,
|
||
RemoteAddress,
|
||
0,
|
||
0,
|
||
Header,
|
||
sizeof(NCA_PACKET_HEADER) + Header->GetPacketBodyLen(),
|
||
0,
|
||
0
|
||
);
|
||
}
|
||
};
|
||
|
||
typedef DG_CLIENT_CALLBACK * PDG_CLIENT_CALLBACK;
|
||
|
||
|
||
class CLIENT_ACTIVITY_TABLE : private UUID_HASH_TABLE
|
||
{
|
||
public:
|
||
|
||
inline
|
||
CLIENT_ACTIVITY_TABLE(
|
||
RPC_STATUS * pStatus
|
||
)
|
||
: UUID_HASH_TABLE(pStatus)
|
||
{
|
||
}
|
||
|
||
inline
|
||
~CLIENT_ACTIVITY_TABLE(
|
||
)
|
||
{
|
||
}
|
||
|
||
PDG_CCONNECTION
|
||
Lookup(
|
||
RPC_UUID * Uuid
|
||
);
|
||
|
||
inline RPC_STATUS
|
||
Add(
|
||
PDG_CCONNECTION Connection
|
||
);
|
||
|
||
inline RPC_STATUS
|
||
Remove(
|
||
PDG_CCONNECTION Connection
|
||
);
|
||
};
|
||
|
||
|
||
RPC_STATUS
|
||
CLIENT_ACTIVITY_TABLE::Add(
|
||
PDG_CCONNECTION Connection
|
||
)
|
||
{
|
||
ASSERT( !Connection->InConnectionTable );
|
||
|
||
Connection->InConnectionTable = TRUE;
|
||
|
||
unsigned Hash = MakeHash(&Connection->ActivityNode.Uuid);
|
||
|
||
RequestHashMutex(Hash);
|
||
|
||
UUID_HASH_TABLE::Add(&Connection->ActivityNode);
|
||
|
||
ReleaseHashMutex(Hash);
|
||
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
|
||
RPC_STATUS
|
||
CLIENT_ACTIVITY_TABLE::Remove(
|
||
PDG_CCONNECTION Connection
|
||
)
|
||
{
|
||
if( !Connection->InConnectionTable )
|
||
{
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
Connection->InConnectionTable = FALSE;
|
||
|
||
unsigned Hash = MakeHash(&Connection->ActivityNode.Uuid);
|
||
|
||
RequestHashMutex(Hash);
|
||
|
||
UUID_HASH_TABLE::Remove(&Connection->ActivityNode);
|
||
|
||
ReleaseHashMutex(Hash);
|
||
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
|
||
class ENDPOINT_MANAGER
|
||
{
|
||
public:
|
||
|
||
ENDPOINT_MANAGER(
|
||
IN OUT RPC_STATUS * pStatus
|
||
);
|
||
|
||
DG_ENDPOINT *
|
||
RequestEndpoint(
|
||
IN RPC_DATAGRAM_TRANSPORT * TransportInterface,
|
||
IN BOOL Async,
|
||
IN DWORD Flags
|
||
);
|
||
|
||
void
|
||
ReleaseEndpoint(
|
||
IN DG_ENDPOINT * Endpoint
|
||
);
|
||
|
||
BOOL
|
||
DeleteIdleEndpoints(
|
||
long CurrentTime
|
||
);
|
||
|
||
private:
|
||
|
||
#define DG_TRANSPORT_COUNT 2
|
||
|
||
MUTEX Mutex;
|
||
|
||
DWORD LastScavengeTime;
|
||
|
||
DG_ENDPOINT_STATS Stats;
|
||
|
||
DG_ENDPOINT * AsyncEndpoints[DG_TRANSPORT_COUNT];
|
||
|
||
DG_ENDPOINT * Endpoints;
|
||
};
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
|
||
inline void
|
||
DG_CCONNECTION::AddCallToCache(
|
||
PDG_CCALL Call
|
||
)
|
||
{
|
||
Mutex.VerifyOwned();
|
||
|
||
Call->Next = CachedCalls;
|
||
CachedCalls = Call;
|
||
|
||
LogEvent(SU_CCALL, EV_STOP, Call, this, Call->GetSequenceNumber() );
|
||
|
||
#ifdef DEBUGRPC
|
||
PDG_CCALL Node = ActiveCallHead;
|
||
while (Node)
|
||
{
|
||
ASSERT( Node != Call );
|
||
Node = Node->Next;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
void
|
||
DG_CCONNECTION::UpdateAssociation(
|
||
)
|
||
{
|
||
Association->CurrentPduSize = CurrentPduSize;
|
||
Association->RemoteWindowSize = RemoteWindowSize;
|
||
}
|
||
|
||
unsigned long
|
||
DG_CCONNECTION::CurrentSequenceNumber()
|
||
{
|
||
return CurrentCall->GetSequenceNumber();
|
||
}
|
||
|
||
inline void DG_CCALL::IncrementRefCount()
|
||
{
|
||
++ReferenceCount;
|
||
LogEvent(SU_CCALL, EV_INC, this, 0, ReferenceCount);
|
||
}
|
||
|
||
inline void
|
||
DG_CCALL::SwitchConnection(
|
||
PDG_CCONNECTION NewConnection
|
||
)
|
||
{
|
||
Connection = NewConnection;
|
||
ReadConnectionInfo(NewConnection, 0);
|
||
|
||
ActivityHint = 0xffff;
|
||
|
||
pSavedPacket->Header.ServerBootTime = NewConnection->Association->ServerBootTime;
|
||
pSavedPacket->Header.ActivityHint = ActivityHint;
|
||
}
|
||
|
||
RPC_STATUS
|
||
StandardPacketChecks(
|
||
PDG_PACKET Packet
|
||
);
|
||
|
||
#endif // if __DGCLNT_HXX__
|