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

1494 lines
30 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

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

/*++
Copyright (C) Microsoft Corporation, 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__