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__
|