|
|
/*++
Copyright (C) Microsoft Corporation, 1992 - 1999
Module Name:
dgsvr.hxx
Abstract:
This is the server protocol definitions for a datagram rpc.
Author:
Dave Steckler (davidst) 15-Dec-1992
Revision History:
--*/
#ifndef __DGSVR_HXX__
#define __DGSVR_HXX__
#define MIN_THREADS_WHILE_ACTIVE 3
// Information on the source endpoint. To be used in
// forwarding a packet to a dynamic endpoint from the epmapper.
// disable "zero-length array" warning
#pragma warning(disable:4200)
struct FROM_ENDPOINT_INFO { unsigned long FromEndpointLen; DREP FromDataRepresentation; char FromEndpoint[0]; };
#pragma warning(default:4200)
//----------------------------------------------------------------------
class DG_SCALL; typedef DG_SCALL * PDG_SCALL;
class DG_SCONNECTION; typedef DG_SCONNECTION * PDG_SCONNECTION;
class DG_ADDRESS : public RPC_ADDRESS
/*++
Class Description:
This class represents an endpoint.
--*/
{ public:
#define MIN_FREE_CALLS 2
//--------------------------------------------------------------------
inline void * operator new( IN size_t ObjectLength, IN TRANS_INFO * Transport );
DG_ADDRESS( TRANS_INFO * LoadableTransport, RPC_STATUS * pStatus );
virtual ~DG_ADDRESS ();
void WaitForCalls( );
virtual void EncourageCallCleanup( RPC_INTERFACE * Interface );
virtual RPC_STATUS ServerSetupAddress ( IN RPC_CHAR PAPI *NetworkAddress, IN RPC_CHAR PAPI * PAPI *Endpoint, IN unsigned int PendingQueueSize, IN void PAPI * SecurityDescriptor, OPTIONAL IN unsigned long EndpointFlags, IN unsigned long NICFlags );
#ifndef NO_PLUG_AND_PLAY
virtual void PnpNotify(); #endif
virtual RPC_STATUS ServerStartingToListen ( IN unsigned int MinimumCallThreads, IN unsigned int MaximumConcurrentCalls );
virtual void ServerStoppedListening ( );
virtual long InqNumberOfActiveCalls ( );
RPC_STATUS CheckThreadPool( );
inline void DispatchPacket( DG_PACKET * Packet, IN DatagramTransportPair *AddressPair );
inline PDG_PACKET AllocatePacket();
inline void FreePacket( IN PDG_PACKET pPacket );
inline PDG_SCALL AllocateCall();
inline void FreeCall( PDG_SCALL pCall );
DG_SCONNECTION * AllocateConnection();
void FreeConnection( DG_SCONNECTION * Connection );
RPC_STATUS CompleteListen ();
inline RPC_STATUS SendPacketBack( NCA_PACKET_HEADER * Header, unsigned DataAfterHeader, DG_TRANSPORT_ADDRESS RemoteAddress ) { Header->PacketFlags &= ~DG_PF_FORWARDED; Header->PacketFlags2 &= ~DG_PF2_FORWARDED_2;
ASSERT( Header->PacketType <= 10 );
unsigned Frag = (Header->PacketType << 16) | Header->GetFragmentNumber(); LogEvent(SU_ADDRESS, EV_PKT_OUT, this, 0, Frag);
return Endpoint.TransportInterface->Send( Endpoint.TransportEndpoint, RemoteAddress, 0, 0, Header, sizeof(NCA_PACKET_HEADER) + DataAfterHeader, 0, 0 ); }
inline void SendRejectPacket( DG_PACKET * Packet, DWORD ErrorCode, DG_TRANSPORT_ADDRESS RemoteAddress ) { InitErrorPacket(Packet, DG_REJECT, ErrorCode); SendPacketBack (&Packet->Header, Packet->GetPacketBodyLen(), RemoteAddress); }
RPC_STATUS LaunchReceiveThread( );
static void ScavengerProc( void * address );
inline void DecrementActiveCallCount( ) { ASSERT(ActiveCallCount < 0xffff0000UL);
InterlockedDecrement((LONG *) &ActiveCallCount);
Endpoint.NumberOfCalls = ActiveCallCount; }
inline void IncrementActiveCallCount( ) { ASSERT( ActiveCallCount < 0x100000 );
InterlockedIncrement((LONG *) &ActiveCallCount);
Endpoint.NumberOfCalls = ActiveCallCount; }
void BeginAutoListenCall ( ) ;
void EndAutoListenCall ( ) ;
static inline DG_ADDRESS * FromEndpoint( IN DG_TRANSPORT_ENDPOINT Endpoint ) { return CONTAINING_RECORD( Endpoint, DG_ADDRESS, Endpoint.TransportEndpoint ); }
NETWORK_ADDRESS_VECTOR * GetNetworkAddressVector ( void ) { return Endpoint.TransportInterface->GetNetworkAddressVector(&(Endpoint.TransportEndpoint)); }
//--------------------------------------------------------------------
private:
LONG TotalThreadsThisEndpoint; LONG ThreadsReceivingThisEndpoint; unsigned MinimumCallThreads; unsigned MaximumConcurrentCalls;
DELAYED_ACTION_NODE ScavengerTimer;
unsigned ActiveCallCount;
UUID_HASH_TABLE_NODE * CachedConnections;
INTERLOCKED_INTEGER AutoListenCallCount;
public: // this needs to be the last member because the transport endpoint
// follows it.
//
DG_ENDPOINT Endpoint;
//--------------------------------------------------------------------
unsigned ScavengePackets(); unsigned ScavengeCalls();
private:
BOOL CaptureClientAddress( IN PDG_PACKET Packet, OUT DG_TRANSPORT_ADDRESS RemoteAddress );
RPC_STATUS ForwardPacket( IN PDG_PACKET Packet, IN DG_TRANSPORT_ADDRESS RemoteAddress, IN char * ServerEndpointString );
BOOL ForwardPacketIfNecessary( IN PDG_PACKET pReceivedPacket, IN void * pFromEndpoint );
unsigned short ConvertSerialNum( IN PDG_PACKET pPacket );
static inline void RemoveIdleConnections( DG_ADDRESS * Address );
};
typedef DG_ADDRESS PAPI * PDG_ADDRESS;
inline void * DG_ADDRESS::operator new( IN size_t ObjectLength, IN TRANS_INFO * Transport ) { RPC_DATAGRAM_TRANSPORT * TransportInterface = (RPC_DATAGRAM_TRANSPORT *) (Transport->InqTransInfo()); return new char[ObjectLength + TransportInterface->ServerEndpointSize]; }
PDG_PACKET DG_ADDRESS::AllocatePacket( ) /*++
Routine Description:
Allocates a packet and associates it with a particular transport address.
Arguments:
Return Value:
a packet, or zero if out of memory
--*/
{ return DG_PACKET::AllocatePacket(Endpoint.Stats.PreferredPduSize); }
void DG_ADDRESS::FreePacket( IN PDG_PACKET pPacket ) /*++
Routine Description:
Frees a packet. If there are less than MAX_FREE_PACKETS on the pre-allocated list, then just add it to the list, otherwise delete it.
Arguments:
pPacket - Packet to delete.
Return Value:
RPC_S_OK
--*/
{ pPacket->Free(); }
class ASSOC_GROUP_TABLE;
//
// casting unsigned to/from void * is OK in this case.
//
#pragma warning(push)
#pragma warning(disable:4312)
NEW_SDICT2(SECURITY_CONTEXT, unsigned);
#pragma warning(pop)
class ASSOCIATION_GROUP : public ASSOCIATION_HANDLE //
// This class represents an association group as defined by OSF. This means
// a set of associations sharing an address space.
//
{ friend class ASSOC_GROUP_TABLE;
public:
inline ASSOCIATION_GROUP( RPC_UUID * pUuid, unsigned short InitialPduSize, RPC_STATUS * pStatus ) : Mutex(pStatus), ASSOCIATION_HANDLE(), Node(pUuid), CurrentPduSize(InitialPduSize), ReferenceCount(1), RemoteWindowSize(1) { ObjectType = DG_SASSOCIATION_TYPE; }
~ASSOCIATION_GROUP( ) { }
inline static ASSOCIATION_GROUP * ContainingRecord( UUID_HASH_TABLE_NODE * Node ) { return CONTAINING_RECORD (Node, ASSOCIATION_GROUP, Node); } void RequestMutex( ) { Mutex.Request(); }
void ClearMutex( ) { Mutex.Clear(); }
void IncrementRefCount( ) { long Count = ReferenceCount.Increment(); LogEvent(SU_ASSOC, EV_INC, this, 0, Count); }
long DecrementRefCount( ) { long Count = ReferenceCount.Decrement(); LogEvent(SU_ASSOC, EV_DEC, this, 0, Count);
return Count; } private:
INTERLOCKED_INTEGER ReferenceCount; MUTEX Mutex; //
// This lets the object be added to the master ASSOC_GROUP_TABLE.
//
UUID_HASH_TABLE_NODE Node;
unsigned short CurrentPduSize; unsigned short RemoteWindowSize;
};
//
// Scurity callback results.
//
// CBI_VALID is true if the callback has occurred.
// CBI_ALLOWED is true if the callback allowed the user to make the call.
// CBI_CONTEXT_MASK is bitmask for the context (key sequence number).
//
// The remaining bits contain the interface sequence number;
// (x >> CBI_SEQUENCE_SHIFT) extracts it.
//
#define CBI_VALID (0x00000800U)
#define CBI_ALLOWED (0x00000400U)
#define CBI_CONTEXT_MASK (0x000000ffU)
#define CBI_SEQUENCE_SHIFT 12
#define CBI_SEQUENCE_MASK (~((1 << CBI_SEQUENCE_SHIFT) - 1))
class SECURITY_CALLBACK_INFO_DICT2 : public SIMPLE_DICT2 { public:
inline SECURITY_CALLBACK_INFO_DICT2 ( // Constructor.
) { }
inline ~SECURITY_CALLBACK_INFO_DICT2 ( // Destructor.
) { }
inline int Update ( RPC_INTERFACE * Key, unsigned Item ) { Remove(Key); return SIMPLE_DICT2::Insert(Key, UlongToPtr(Item)); }
inline unsigned Remove ( RPC_INTERFACE * Key ) { return PtrToUlong(SIMPLE_DICT2::Delete(Key)); }
inline unsigned Find ( RPC_INTERFACE * Key ) { return PtrToUlong(SIMPLE_DICT2::Find(Key)); } };
class DG_SCALL_TABLE { public:
inline DG_SCALL_TABLE();
inline ~DG_SCALL_TABLE();
BOOL Add( PDG_SCALL Call, unsigned long Sequence );
void Remove( PDG_SCALL Call );
PDG_SCALL Find( unsigned long Sequence );
PDG_SCALL Predecessor( unsigned long Sequence );
PDG_SCALL Successor( PDG_SCALL Call );
inline void RemoveIdleCalls( BOOL Aggressive, RPC_INTERFACE * Interface );
private:
PDG_SCALL ActiveCallHead; PDG_SCALL ActiveCallTail;
};
inline DG_SCALL_TABLE::DG_SCALL_TABLE() { ActiveCallHead = 0; ActiveCallTail = 0; }
inline DG_SCALL_TABLE::~DG_SCALL_TABLE() { ASSERT( ActiveCallHead == 0 ); ASSERT( ActiveCallTail == 0 ); }
class DG_SCONNECTION : public DG_COMMON_CONNECTION { public:
DG_SCONNECTION *Next;
CLIENT_AUTH_INFO AuthInfo;
unsigned ActivityHint;
ASSOCIATION_GROUP * pAssocGroup;
PDG_ADDRESS pAddress; RPC_INTERFACE * LastInterface;
DG_SCALL * CurrentCall; BOOL fFirstCall;
enum CALLBACK_STATE { NoCallbackAttempted = 0x99, SetupInProgress, MsConvWayAuthInProgress, ConvWayAuthInProgress, MsConvWay2InProgress, ConvWay2InProgress, ConvWayInProgress, ConvWayAuthMoreInProgress, CallbackSucceeded, CallbackFailed };
//--------------------------------------------------------------------
// The message mutex is only used by ncadg_mq.
MUTEX3 *pMessageMutex;
//--------------------------------------------------------------------
DG_SCONNECTION( DG_ADDRESS * a_Address, RPC_STATUS * pStatus );
~DG_SCONNECTION();
virtual RPC_STATUS SealAndSendPacket( IN DG_ENDPOINT * SourceEndpoint, IN DG_TRANSPORT_ADDRESS RemoteAddress, IN UNALIGNED NCA_PACKET_HEADER * Header, IN unsigned long DataOffset );
void Activate( PNCA_PACKET_HEADER pHeader, unsigned short NewHash );
void Deactivate();
PDG_SCALL AllocateCall();
void FreeCall( PDG_SCALL Call );
void CheckForExpiredCalls();
inline BOOL HasExpired();
inline void DispatchPacket( DG_PACKET * Packet, DatagramTransportPair *AddressPair );
RPC_STATUS MakeApplicationSecurityCallback( RPC_INTERFACE * Interface, PDG_SCALL Call );
inline void AddCallToCache( DG_SCALL * Call );
inline LONG IncrementRefCount( ) { ASSERT(ReferenceCount < 1000); return InterlockedIncrement(&ReferenceCount); }
inline LONG DecrementRefCount( ) { ASSERT(ReferenceCount > 0); return InterlockedDecrement(&ReferenceCount); }
inline static DG_SCONNECTION * FromHashNode( UUID_HASH_TABLE_NODE * Node ) { return CONTAINING_RECORD (Node, DG_SCONNECTION, ActivityNode); }
inline LONG GetTimeStamp() { return TimeStamp; }
inline BOOL DidCallbackFail() { if (Callback.State == CallbackFailed) { return TRUE; }
return FALSE; }
RPC_STATUS VerifyNonRequestPacket( DG_PACKET * Packet );
RPC_STATUS VerifyRequestPacket( DG_PACKET * Packet );
RPC_STATUS FindOrCreateSecurityContext( IN DG_PACKET * pPacket, IN DG_TRANSPORT_ADDRESS RemoteAddress, OUT unsigned long * pClientSequenceNumber );
inline SECURITY_CONTEXT * FindMatchingSecurityContext( DG_PACKET * Packet );
inline DG_SCALL * RemoveIdleCalls( DG_SCALL * List, BOOL Aggressive, RPC_INTERFACE * Interface );
RPC_STATUS GetAssociationGroup( DG_TRANSPORT_ADDRESS RemoteAddress );
inline void SubmitCallbackIfNecessary( PDG_SCALL Call, PDG_PACKET Packet, DG_TRANSPORT_ADDRESS RemoteAddress );
void ConvCallCompleted();
inline void MessageMutexInitialize( RPC_STATUS *pStatus ) { pMessageMutex = new MUTEX3(pStatus);
if (!pMessageMutex) { *pStatus = RPC_S_OUT_OF_MEMORY; } else if (*pStatus != RPC_S_OK) { delete pMessageMutex; pMessageMutex = 0; } }
friend class ENDPOINT_MANAGER;
private:
DG_SCALL * CachedCalls;
DG_SCALL_TABLE ActiveCalls;
SECURITY_CONTEXT_DICT2 SecurityContextDict;
unsigned MaxKeySeq;
SECURITY_CALLBACK_INFO_DICT2 InterfaceCallbackResults;
struct { CALLBACK_STATE State;
RPC_BINDING_HANDLE Binding; RPC_ASYNC_STATE AsyncState;
DG_SCALL * Call; SECURITY_CREDENTIALS * Credentials; SECURITY_CONTEXT * SecurityContext; BOOL ThirdLegNeeded; DWORD DataRep; DWORD KeySequence;
RPC_UUID CasUuid; unsigned long ClientSequence; unsigned char * TokenBuffer; long TokenLength; unsigned char * ResponseBuffer; long ResponseLength; long MaxData; unsigned long DataIndex; unsigned long Status; } Callback;
boolean BlockIdleCallRemoval;
//--------------------------------------------------------------------
void CallDispatchLoop();
RPC_STATUS FinishConvCallback( RPC_STATUS Status );
BOOL HandleMaybeCall( PDG_PACKET Packet, DatagramTransportPair *AddressPair );
PDG_SCALL HandleNewCall( PDG_PACKET Packet, DatagramTransportPair *AddressPair );
RPC_STATUS CreateCallbackBindingAndReleaseMutex( DG_TRANSPORT_ADDRESS RemoteAddress );
static void RPC_ENTRY ConvNotificationRoutine ( RPC_ASYNC_STATE * pAsync, void * Reserved, RPC_ASYNC_EVENT Event ); };
inline SECURITY_CONTEXT * DG_SCONNECTION::FindMatchingSecurityContext( DG_PACKET * Packet ) { DG_SECURITY_TRAILER * Verifier = (DG_SECURITY_TRAILER *) (Packet->Header.Data + Packet->GetPacketBodyLen());
return SecurityContextDict.Find(Verifier->key_vers_num); }
class DG_SCALL : public SCALL, public DG_PACKET_ENGINE /*++
Class Description:
This class represents a call in progress on the server.
Fields:
Revision History:
--*/ { #ifdef MONITOR_SERVER_PACKET_COUNT
long OutstandingPacketCount; #endif
public:
long TimeStamp; DG_SCALL * Next; DG_SCALL * Previous;
//------------------------------------------------
inline void * operator new( IN size_t ObjectLength, IN RPC_DATAGRAM_TRANSPORT * TransportInterface );
DG_SCALL( DG_ADDRESS * Address, RPC_STATUS * pStatus );
virtual ~DG_SCALL();
//------------------------------------------------
virtual RPC_STATUS NegotiateTransferSyntax ( IN OUT PRPC_MESSAGE Message );
virtual RPC_STATUS GetBuffer ( IN OUT PRPC_MESSAGE Message, IN UUID *ObjectUuid );
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 RPC_STATUS SendReceive ( IN OUT PRPC_MESSAGE Message );
virtual RPC_STATUS ToStringBinding ( OUT RPC_CHAR PAPI * PAPI * StringBinding );
virtual RPC_STATUS ImpersonateClient ( );
virtual RPC_STATUS RevertToSelf ( );
virtual RPC_STATUS GetAssociationContextCollection ( OUT ContextCollection **CtxCollection );
virtual void InquireObjectUuid ( OUT RPC_UUID PAPI * ObjectUuid );
virtual RPC_STATUS InquireAuthClient ( OUT RPC_AUTHZ_HANDLE PAPI * Privileges, OUT RPC_CHAR PAPI * PAPI * ServerPrincipalName, OPTIONAL OUT unsigned long PAPI * AuthenticationLevel, OUT unsigned long PAPI * AuthenticationService, OUT unsigned long PAPI * AuthorizationService, IN unsigned long Flags );
virtual RPC_STATUS ConvertToServerBinding ( OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding );
virtual RPC_STATUS InqTransportType( OUT unsigned int __RPC_FAR * Type ) ;
virtual RPC_STATUS Cancel( void * ThreadHandle );
virtual unsigned TestCancel();
virtual RPC_STATUS Receive( PRPC_MESSAGE Message, unsigned Size );
virtual RPC_STATUS Send( PRPC_MESSAGE Message );
virtual RPC_STATUS AsyncSend ( IN OUT PRPC_MESSAGE Message );
virtual RPC_STATUS AsyncReceive ( IN OUT PRPC_MESSAGE Message, IN unsigned int Size );
virtual RPC_STATUS IsClientLocal( IN OUT unsigned * pClientIsLocal ) { return RPC_S_CANNOT_SUPPORT; }
virtual void IsClientDisconnected ( OUT BOOL *ClientIsDisconnected ) { ASSERT(!"You shouldn't be here"); }
RPC_STATUS InqLocalConnAddress ( IN OUT void *Buffer, IN OUT unsigned long *BufferSize, OUT unsigned long *AddressFormat );
virtual RPC_STATUS AbortAsyncCall ( IN PRPC_ASYNC_STATE pAsync, IN unsigned long ExceptionCode );
virtual RPC_STATUS SetAsyncHandle ( IN RPC_ASYNC_STATE * pAsync );
virtual BOOL IsSyncCall () { return !pAsync; }
//------------------------------------------------
inline void DispatchPacket( DG_PACKET * Packet, IN DG_TRANSPORT_ADDRESS RemoteAddress );
void DealWithRequest ( PDG_PACKET pPacket ); void DealWithResponse ( PDG_PACKET pPacket ); void DealWithPing ( PDG_PACKET pPacket ); void DealWithFack ( PDG_PACKET pPacket ); void DealWithAck ( PDG_PACKET pPacket ); void DealWithQuit ( PDG_PACKET pPacket );
//------------------------------------------------
inline void NewCall( DG_PACKET * pPacket, DatagramTransportPair *AddressPAir );
inline void BindToConnection( PDG_SCONNECTION a_Connection );
BOOL DG_SCALL::FinishSendOrReceive( BOOL Abort );
inline BOOL ReadyToDispatch();
void ProcessRpcCall();
inline BOOL HasExpired( BOOL Aggressive, RPC_INTERFACE * Interface );
BOOL Cleanup();
inline BOOL IsSynchronous();
void FreeAPCInfo ( IN RPC_APC_INFO *pAPCInfo );
inline void IncrementRefCount(); inline void DecrementRefCount();
inline void ConvCallbackFailed( DWORD Status ) { pSavedPacket->Header.SequenceNumber = SequenceNumber;
InitErrorPacket(pSavedPacket, DG_REJECT, Status); SealAndSendPacket(&pSavedPacket->Header); Cleanup(); }
virtual RPC_STATUS InqConnection ( OUT void **ConnId, OUT BOOL *pfFirstCall ) { ASSERT(Connection); *ConnId = Connection;
if (InterlockedIncrement((LONG *) &(Connection->fFirstCall)) == 1) { *pfFirstCall = 1; } else { *pfFirstCall = 0; }
return RPC_S_OK; }
private:
enum CALL_STATE { CallInit = 0x201, CallBeforeDispatch, CallDispatched, xxxxObsolete, CallAfterDispatch, CallSendingResponse, CallComplete, CallBogus = 0xfffff004 };
CALL_STATE State; CALL_STATE PreviousState;
boolean CallInProgress; boolean CallWasForwarded; boolean KnowClientAddress; boolean TerminateWhenConvenient;
DG_SCONNECTION * Connection; RPC_INTERFACE * Interface;
//
// Data to monitor pipe data transfer.
//
unsigned long PipeThreadId;
PENDING_OPERATION PipeWaitType; unsigned long PipeWaitLength;
//
// The only unusual aspect of this is that it's an auto-reset event.
// It is created during the first call on a pipe interface.
//
EVENT * PipeWaitEvent;
//
// Stuff for RpcBindingInqAuthClient.
//
RPC_AUTHZ_HANDLE Privileges; unsigned long AuthorizationService;
DWORD LocalAddress; // IP address, network byte order encoded
//---------------------------------------------------------------------
inline void SetState( CALL_STATE NewState ) { if (NewState != State) { LogEvent(SU_SCALL, EV_STATE, this, 0, NewState); }
PreviousState = State; State = NewState; }
virtual BOOL IssueNotification ( IN RPC_ASYNC_EVENT Event );
void AddPacketToReceiveList( PDG_PACKET pPacket );
RPC_STATUS UnauthenticatedCallback( unsigned * pClientSequenceNumber );
RPC_STATUS SendFragment( PRPC_MESSAGE pMessage, unsigned FragNum, unsigned char PacketType );
RPC_STATUS SealAndSendPacket( NCA_PACKET_HEADER * Header );
RPC_STATUS SendPacketBack( NCA_PACKET_HEADER * pNcaPacketHeader, unsigned TrailerSize );
RPC_STATUS CreateReverseBinding ( RPC_BINDING_HANDLE * pServerBinding, BOOL IncludeEndpoint );
void SaveOriginalClientInfo( DG_PACKET * pPacket );
inline RPC_STATUS AssembleBufferFromPackets( IN OUT PRPC_MESSAGE Message );
RPC_STATUS WaitForPipeEvent();
//------------------------------------------------
// ConvertSidToUserW() is used to get transport supplied
// auth. info. The only DG transport that uses this is
// Falcon. The SID for the client user that sent the
// "current" request is cashed along with the user name.
// So, if the next call on this activity has the same
// SID we can return the user without hitting the domain
// server.
RPC_STATUS ConvertSidToUserW( IN SID *pSid, OUT RPC_CHAR **ppwsPrincipal );
SID *pCachedSid; RPC_CHAR *pwsCachedUserName; DWORD dwCachedUserNameSize;
boolean FinalSendBufferPresent;
RPC_MESSAGE RpcMessage; RPC_RUNTIME_INFO RpcRuntimeInfo ; };
inline void * DG_SCALL::operator new( IN size_t ObjectLength, IN RPC_DATAGRAM_TRANSPORT * TransportInterface ) { return new char[ObjectLength + TransportInterface->AddressSize]; }
inline void DG_SCALL::DecrementRefCount() { Connection->Mutex.VerifyOwned();
--ReferenceCount;
LogEvent(SU_SCALL, EV_DEC, this, 0, ReferenceCount); }
inline void DG_SCALL::IncrementRefCount() { Connection->Mutex.VerifyOwned();
++ReferenceCount;
LogEvent(SU_SCALL, EV_INC, this, 0, ReferenceCount); }
void DG_SCALL::BindToConnection( PDG_SCONNECTION a_Connection ) { Connection = a_Connection;
ReadConnectionInfo(Connection, this + 1);
pSavedPacket->Header.ServerBootTime = ProcessStartTime; pSavedPacket->Header.ActivityHint = (unsigned short) Connection->ActivityHint; pSavedPacket->Header.InterfaceHint = 0xffff; }
inline BOOL DG_SCALL::IsSynchronous( ) /*++
Routine Description:
Simply tells whether the call is sycnhronous or asynchronous.
The return value won't be reliable if the call was instantiated by a packet other than a REQUEST and no REQUEST has yet arrived, so be careful to call it only after a REQUEST has arrived.
Arguments:
none
Return Value:
TRUE if synchronous FALSE if asynchronous
--*/
{ if (BufferFlags & RPC_BUFFER_ASYNC) { return FALSE; } else { return TRUE; } }
inline RPC_STATUS DG_SCALL::AssembleBufferFromPackets( IN OUT PRPC_MESSAGE Message ) { RPC_STATUS Status = DG_PACKET_ENGINE::AssembleBufferFromPackets(Message, this);
if (RPC_S_OK == Status && (Message->RpcFlags & RPC_BUFFER_EXTRA)) { PRPC_RUNTIME_INFO Info = (PRPC_RUNTIME_INFO) Message->ReservedForRuntime;
Info->OldBuffer = Message->Buffer; }
return Status; }
inline RPC_STATUS DG_SCALL::InqTransportType( OUT unsigned int __RPC_FAR * Type ) { *Type = TRANSPORT_TYPE_DG ;
return (RPC_S_OK) ; }
inline RPC_STATUS DG_SCALL::SealAndSendPacket( NCA_PACKET_HEADER * Header ) { Header->ServerBootTime = ProcessStartTime; SetMyDataRep(Header);
unsigned Frag = (Header->PacketType << 16) | Header->FragmentNumber; LogEvent(SU_SCALL, EV_PKT_OUT, this, 0, Frag);
return Connection->SealAndSendPacket(SourceEndpoint, RemoteAddress, Header, 0); }
//------------------------------------------------------------------------
class SERVER_ACTIVITY_TABLE : private UUID_HASH_TABLE { public:
inline SERVER_ACTIVITY_TABLE( RPC_STATUS * pStatus ) : UUID_HASH_TABLE ( pStatus ) { LastFinishTime = 0; BucketCounter = 0; }
inline ~SERVER_ACTIVITY_TABLE( ) { }
inline DG_SCONNECTION * FindOrCreate( DG_ADDRESS * Address, PDG_PACKET pPacket );
inline void Prune();
BOOL PruneEntireTable( RPC_INTERFACE * Interface );
BOOL PruneSpecificBucket( unsigned Bucket, BOOL Aggressive, RPC_INTERFACE * Interface );
void SERVER_ACTIVITY_TABLE::BeginIdlePruning();
static void SERVER_ACTIVITY_TABLE::PruneWhileIdle( PVOID unused );
private:
long LastFinishTime; long BucketCounter;
DELAYED_ACTION_NODE IdleScavengerTimer; };
class ASSOC_GROUP_TABLE : private UUID_HASH_TABLE { public:
inline ASSOC_GROUP_TABLE( RPC_STATUS * pStatus ) : UUID_HASH_TABLE(pStatus) { }
inline ~ASSOC_GROUP_TABLE( ) { }
inline ASSOCIATION_GROUP * FindOrCreate( RPC_UUID * pUuid, unsigned short InitialPduSize );
inline void DecrementRefCount( ASSOCIATION_GROUP * pClient ); };
inline void DG_SCONNECTION::AddCallToCache( DG_SCALL * Call ) { Mutex.VerifyOwned();
ASSERT( !Call->InvalidHandle(DG_SCALL_TYPE) ); ASSERT( !CachedCalls || !CachedCalls->InvalidHandle(DG_SCALL_TYPE) );
Call->TimeStamp = GetTickCount(); Call->Next = CachedCalls; CachedCalls = Call;
LogEvent(SU_SCALL, EV_STOP, Call, this, Call->GetSequenceNumber() ); }
//------------------------------------------------------------------------
BOOL StripForwardedPacket( IN PDG_PACKET pPacket, IN void * pFromEndpoint );
extern unsigned long ServerBootTime;
#endif // __DGSVR_HXX__
|