/*++ 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, OUT NETWORK_ADDRESS_VECTOR **ppNetworkAddressVector ) ; #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 ); } //-------------------------------------------------------------------- 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; } } 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; } 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__