Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1678 lines
35 KiB

  1. /*++ b
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. dgclnt.hxx
  5. Abstract:
  6. This file contains the definitions used by the datagram client.
  7. Revision History:
  8. NT 3.5 was the first version shipped, supporting IPX and UDP. (connieh)
  9. NT 3.51 added secure calls over NTLM and DEC Kerberos. (jroberts)
  10. NT 4.0 added sliding window, larger packet sizes, cancels. (jroberts)
  11. NT 5.0 added asynchronous calls and SSL/PCT security. (jroberts)
  12. --*/
  13. #ifndef __DGCLNT_HXX__
  14. #define __DGCLNT_HXX__
  15. class DG_CCALL;
  16. typedef DG_CCALL * PDG_CCALL;
  17. class DG_CCONNECTION;
  18. typedef DG_CCONNECTION * PDG_CCONNECTION;
  19. class DG_CASSOCIATION;
  20. typedef DG_CASSOCIATION * PDG_CASSOCIATION;
  21. class DG_BINDING_HANDLE;
  22. typedef DG_BINDING_HANDLE * PDG_BINDING_HANDLE;
  23. class INTERFACE_AND_OBJECT_LIST
  24. {
  25. public:
  26. inline
  27. INTERFACE_AND_OBJECT_LIST(
  28. )
  29. {
  30. Head = 0;
  31. Cache1Available = TRUE;
  32. Cache2Available = TRUE;
  33. }
  34. ~INTERFACE_AND_OBJECT_LIST(
  35. );
  36. BOOL
  37. Insert(
  38. void * Interface,
  39. RPC_UUID * Object
  40. );
  41. BOOL
  42. Find(
  43. void * Interface,
  44. RPC_UUID * Object
  45. );
  46. BOOL
  47. Delete(
  48. void * Interface,
  49. RPC_UUID * Object
  50. );
  51. private:
  52. #define MAX_ELEMENTS 10
  53. struct INTERFACE_AND_OBJECT
  54. {
  55. INTERFACE_AND_OBJECT * Next;
  56. void * Interface;
  57. RPC_UUID Object;
  58. inline void
  59. Update(
  60. void * a_Interface,
  61. RPC_UUID * a_Object
  62. )
  63. {
  64. Interface = a_Interface;
  65. Object = *a_Object;
  66. }
  67. };
  68. INTERFACE_AND_OBJECT * Head;
  69. unsigned Cache1Available : 1;
  70. unsigned Cache2Available : 1;
  71. INTERFACE_AND_OBJECT Cache1;
  72. INTERFACE_AND_OBJECT Cache2;
  73. };
  74. class DG_CCONNECTION : public DG_COMMON_CONNECTION
  75. {
  76. public:
  77. long TimeStamp;
  78. DG_CCONNECTION * Next;
  79. boolean CallbackCompleted;
  80. boolean fServerSupportsAsync;
  81. boolean fSecurePacketReceived;
  82. boolean ServerResponded;
  83. boolean fBusy;
  84. boolean InConnectionTable;
  85. signed char AckPending;
  86. boolean AckOrphaned;
  87. boolean PossiblyRunDown;
  88. boolean fAutoReconnect;
  89. boolean fError;
  90. DWORD ThreadId;
  91. PDG_BINDING_HANDLE BindingHandle;
  92. int AssociationKey;
  93. PDG_CASSOCIATION Association;
  94. PDG_CCALL CurrentCall;
  95. //--------------------------------------------------------------------
  96. DG_CCALL * AllocateCall();
  97. inline void
  98. AddCallToCache(
  99. PDG_CCALL Call
  100. );
  101. RPC_STATUS
  102. BeginCall(
  103. IN PDG_CCALL Call
  104. );
  105. void
  106. EndCall(
  107. IN PDG_CCALL Call
  108. );
  109. long DecrementRefCount();
  110. long DecrementRefCountAndKeepMutex();
  111. void
  112. IncrementRefCount(
  113. void
  114. );
  115. inline int
  116. IsSupportedAuthInfo(
  117. IN const CLIENT_AUTH_INFO * ClientAuthInfo
  118. );
  119. RPC_STATUS
  120. DealWithAuthCallback(
  121. IN void * InToken,
  122. IN long InTokenLengh,
  123. OUT void * OutToken,
  124. OUT long MaxOutTokenLength,
  125. OUT long * OutTokenLength
  126. );
  127. RPC_STATUS
  128. DealWithAuthMore(
  129. IN long Index,
  130. OUT void * OutToken,
  131. OUT long MaxOutTokenLength,
  132. OUT long * OutTokenLength
  133. );
  134. DG_CCONNECTION(
  135. IN PDG_CASSOCIATION a_Association,
  136. IN const CLIENT_AUTH_INFO * AuthInfo,
  137. IN OUT RPC_STATUS * pStatus
  138. );
  139. ~DG_CCONNECTION();
  140. void PostDelayedAck();
  141. void SendDelayedAck();
  142. void CancelDelayedAck(
  143. BOOL Flush = FALSE
  144. );
  145. inline void UpdateAssociation();
  146. RPC_STATUS
  147. UpdateServerAddress(
  148. IN DG_PACKET * Packet,
  149. IN DG_TRANSPORT_ADDRESS Address
  150. );
  151. void EnableOverlappedCalls();
  152. unsigned long
  153. GetSequenceNumber()
  154. {
  155. return LowestActiveSequence;
  156. }
  157. unsigned long
  158. GetLowestActiveSequence()
  159. {
  160. return LowestActiveSequence;
  161. }
  162. RPC_STATUS WillNextCallBeQueued();
  163. RPC_STATUS MaybeTransmitNextCall();
  164. DG_CCALL *
  165. FindIdleCalls(
  166. long CurrentTime
  167. );
  168. void
  169. DispatchPacket(
  170. PDG_PACKET Packet,
  171. void * Address
  172. );
  173. inline unsigned long CurrentSequenceNumber();
  174. virtual RPC_STATUS
  175. SealAndSendPacket(
  176. IN DG_ENDPOINT * SourceEndpoint,
  177. IN DG_TRANSPORT_ADDRESS RemoteAddress,
  178. IN UNALIGNED NCA_PACKET_HEADER * Header,
  179. IN unsigned long BufferOffset
  180. );
  181. RPC_STATUS
  182. VerifyPacket(
  183. IN DG_PACKET * Packet
  184. );
  185. static inline DG_CCONNECTION *
  186. FromHashNode(
  187. IN UUID_HASH_TABLE_NODE * Node
  188. )
  189. {
  190. return CONTAINING_RECORD( Node, DG_CCONNECTION, ActivityNode );
  191. }
  192. inline void *
  193. operator new(
  194. IN size_t ObjectLength,
  195. IN const RPC_DATAGRAM_TRANSPORT * Transport
  196. );
  197. void WaitForNoReferences()
  198. {
  199. while (ReferenceCount)
  200. {
  201. Sleep(10);
  202. }
  203. fBusy = FALSE;
  204. }
  205. RPC_STATUS
  206. TransferCallsToNewConnection(
  207. PDG_CCALL FirstCall,
  208. PDG_CCONNECTION NewConnection
  209. );
  210. const CLIENT_AUTH_INFO *
  211. InqAuthInfo()
  212. {
  213. return &AuthInfo;
  214. }
  215. BOOL MutexTryRequest()
  216. {
  217. BOOL result = Mutex.TryRequest();
  218. if (result)
  219. {
  220. LogEvent( SU_MUTEX, EV_INC, this, 0, 0, TRUE, 1);
  221. }
  222. return result;
  223. }
  224. void MutexRequest()
  225. {
  226. Mutex.Request();
  227. LogEvent( SU_MUTEX, EV_INC, this, 0, 0, TRUE, 1);
  228. #ifdef CHECK_MUTEX_INVERSION
  229. ThreadSelf()->ConnectionMutexHeld = this;
  230. #endif
  231. }
  232. void MutexClear()
  233. {
  234. LogEvent( SU_MUTEX, EV_DEC, this, 0, 0, TRUE, 1);
  235. Mutex.Clear();
  236. #ifdef CHECK_MUTEX_INVERSION
  237. ThreadSelf()->ConnectionMutexHeld = 0;
  238. #endif
  239. }
  240. private:
  241. CLIENT_AUTH_INFO AuthInfo;
  242. DELAYED_ACTION_NODE DelayedAckTimer;
  243. unsigned SecurityContextId;
  244. long LastScavengeTime;
  245. unsigned CachedCallCount;
  246. PDG_CCALL CachedCalls;
  247. PDG_CCALL ActiveCallHead;
  248. PDG_CCALL ActiveCallTail;
  249. //--------------------------------------------------------------------
  250. RPC_STATUS InitializeSecurityContext();
  251. unsigned char * SecurityBuffer;
  252. long SecurityBufferLength;
  253. public:
  254. long LastCallbackTime;
  255. };
  256. NEW_SDICT(DG_CCONNECTION);
  257. inline void *
  258. DG_CCONNECTION::operator new(
  259. IN size_t ObjectLength,
  260. IN const RPC_DATAGRAM_TRANSPORT * Transport
  261. )
  262. {
  263. return new char[ObjectLength + Transport->AddressSize];
  264. }
  265. inline void
  266. DG_CCONNECTION::IncrementRefCount()
  267. {
  268. Mutex.VerifyOwned();
  269. ++ReferenceCount;
  270. LogEvent(SU_CCONN, EV_INC, this, 0, ReferenceCount, TRUE);
  271. }
  272. class DG_CCALL : public CCALL, public DG_PACKET_ENGINE
  273. {
  274. friend RPC_STATUS DG_CCONNECTION::WillNextCallBeQueued();
  275. public:
  276. //
  277. // The call's Next pointer is NOT_ACTIVE until the call is added
  278. // to a connection's active call list.
  279. //
  280. #define DG_CCALL_NOT_ACTIVE ((DG_CCALL *) (~0))
  281. long TimeStamp;
  282. DG_CCALL * Next;
  283. DG_CCALL * Previous;
  284. boolean LastSendTimedOut;
  285. boolean CancelPending;
  286. boolean CancelComplete;
  287. boolean AutoReconnectOk;
  288. //-----------------------------------------------
  289. DG_CCALL(
  290. IN PDG_CCONNECTION Connection,
  291. OUT RPC_STATUS * pStatus
  292. );
  293. virtual
  294. ~DG_CCALL();
  295. RPC_STATUS
  296. DispatchPacket(
  297. PDG_PACKET Packet
  298. );
  299. inline void IncrementRefCount();
  300. long DecrementRefCount();
  301. long DecrementRefCountAndKeepMutex();
  302. //------------------------------------------------
  303. //
  304. // implementations of CCALL virtual functions
  305. //
  306. virtual RPC_STATUS
  307. NegotiateTransferSyntax (
  308. IN OUT PRPC_MESSAGE Message
  309. )
  310. {
  311. // datagrams don't support multiple syntax
  312. // negotiation. They always return the transfer
  313. // syntax the stub prefers
  314. return RPC_S_OK;
  315. }
  316. virtual RPC_STATUS
  317. GetBuffer (
  318. IN OUT PRPC_MESSAGE Message,
  319. IN UUID *ObjectUuid = 0
  320. );
  321. virtual RPC_STATUS
  322. SendReceive (
  323. IN OUT PRPC_MESSAGE Message
  324. );
  325. virtual RPC_STATUS
  326. Send(
  327. PRPC_MESSAGE Message
  328. );
  329. virtual RPC_STATUS
  330. Receive(
  331. PRPC_MESSAGE Message,
  332. unsigned MinimumSize
  333. );
  334. virtual RPC_STATUS
  335. AsyncSend(
  336. PRPC_MESSAGE Message
  337. );
  338. virtual RPC_STATUS
  339. AsyncReceive(
  340. PRPC_MESSAGE Message,
  341. unsigned MinimumSize
  342. );
  343. virtual void
  344. FreeBuffer (
  345. IN PRPC_MESSAGE Message
  346. );
  347. virtual void
  348. FreePipeBuffer (
  349. IN PRPC_MESSAGE Message
  350. ) ;
  351. virtual RPC_STATUS
  352. ReallocPipeBuffer (
  353. IN PRPC_MESSAGE Message,
  354. IN unsigned int NewSize
  355. ) ;
  356. virtual BOOL
  357. IssueNotification (
  358. IN RPC_ASYNC_EVENT Event
  359. ) ;
  360. virtual void
  361. FreeAPCInfo (
  362. IN RPC_APC_INFO *pAPCInfo
  363. ) ;
  364. RPC_STATUS
  365. CancelAsyncCall (
  366. IN BOOL fAbort
  367. );
  368. void SendAck();
  369. virtual RPC_STATUS
  370. Cancel(
  371. void * ThreadHandle
  372. );
  373. virtual unsigned TestCancel();
  374. void ExecuteDelayedSend();
  375. RPC_STATUS SendSomeFragments();
  376. inline RPC_STATUS
  377. GetInitialBuffer(
  378. IN OUT RPC_MESSAGE * Message,
  379. IN UUID *MyObjectUuid
  380. );
  381. inline void
  382. SwitchConnection(
  383. PDG_CCONNECTION NewConnection
  384. );
  385. BOOL IsBroadcast()
  386. {
  387. if (BasePacketFlags & RPC_NCA_FLAGS_BROADCAST)
  388. {
  389. return TRUE;
  390. }
  391. return FALSE;
  392. }
  393. RPC_STATUS
  394. ProcessFaultOrRejectData(
  395. PDG_PACKET Packet
  396. );
  397. BOOL
  398. InProgress()
  399. {
  400. if (AsyncStatus == RPC_S_ASYNC_CALL_PENDING)
  401. {
  402. return TRUE;
  403. }
  404. return FALSE;
  405. }
  406. private:
  407. enum DG_CLIENT_STATE
  408. {
  409. CallInit = 0x900,
  410. CallQuiescent,
  411. CallSend,
  412. CallSendReceive,
  413. CallReceive,
  414. CallCancellingSend,
  415. CallComplete
  416. };
  417. DG_CLIENT_STATE State;
  418. DG_CLIENT_STATE PreviousState;
  419. PRPC_CLIENT_INTERFACE InterfacePointer;
  420. PDG_CCONNECTION Connection;
  421. DELAYED_ACTION_NODE TransmitTimer;
  422. // unused
  423. unsigned WorkingCount;
  424. unsigned UnansweredRequestCount;
  425. long ReceiveTimeout;
  426. unsigned long PipeReceiveSize;
  427. long TimeoutLimit;
  428. long LastReceiveTime;
  429. long CancelTime;
  430. boolean StaticArgsSent;
  431. boolean AllArgsSent;
  432. boolean _unused;
  433. boolean ForceAck;
  434. long DelayedSendPending;
  435. //--------------------------------------------------------------------
  436. RPC_STATUS
  437. BeforeSendReceive(
  438. PRPC_MESSAGE Message
  439. );
  440. RPC_STATUS
  441. AfterSendReceive(
  442. PRPC_MESSAGE Message,
  443. RPC_STATUS Status
  444. );
  445. RPC_STATUS
  446. MaybeSendReceive(
  447. IN OUT PRPC_MESSAGE Message
  448. );
  449. void
  450. BuildNcaPacketHeader(
  451. OUT PNCA_PACKET_HEADER pNcaPacketHeader,
  452. IN OUT PRPC_MESSAGE Message
  453. );
  454. RPC_STATUS AttemptAutoReconnect();
  455. void PostDelayedSend();
  456. void CancelDelayedSend();
  457. void SendDelayedAck();
  458. RPC_STATUS
  459. SendFragment(
  460. PRPC_MESSAGE pMessage,
  461. PNCA_PACKET_HEADER pBaseHeader
  462. );
  463. RPC_STATUS SendQuit();
  464. RPC_STATUS SendPing();
  465. RPC_STATUS ReceiveSinglePacket();
  466. //-----------------------------------------------
  467. RPC_STATUS
  468. DealWithNocall(
  469. PDG_PACKET pPacket
  470. );
  471. RPC_STATUS
  472. DealWithFault(
  473. PDG_PACKET pPacket
  474. );
  475. RPC_STATUS
  476. DealWithReject(
  477. PDG_PACKET pPacket
  478. );
  479. RPC_STATUS
  480. DealWithWorking(
  481. PDG_PACKET pPacket
  482. );
  483. RPC_STATUS
  484. DealWithResponse(
  485. PDG_PACKET pPacket
  486. );
  487. RPC_STATUS
  488. DealWithFack(
  489. PDG_PACKET pPacket
  490. );
  491. RPC_STATUS
  492. DealWithQuack(
  493. PDG_PACKET pPacket
  494. );
  495. RPC_STATUS
  496. DealWithTimeout();
  497. RPC_STATUS
  498. DealWithRequest(
  499. IN PDG_PACKET Packet,
  500. IN DG_TRANSPORT_ADDRESS RemoteAddress
  501. );
  502. void IncreaseReceiveTimeout();
  503. RPC_STATUS
  504. MapErrorCode(
  505. RPC_STATUS Status
  506. );
  507. RPC_STATUS
  508. GetEndpoint(
  509. DWORD EndpointFlags
  510. );
  511. void
  512. SetState(
  513. IN DG_CLIENT_STATE NewState
  514. )
  515. {
  516. if (NewState != State)
  517. {
  518. LogEvent(SU_CCALL, EV_STATE, this, 0, NewState);
  519. }
  520. PreviousState = State;
  521. State = NewState;
  522. }
  523. };
  524. class DG_CASSOCIATION : public GENERIC_OBJECT
  525. {
  526. friend class DG_ASSOCIATION_TABLE;
  527. public:
  528. RPC_DATAGRAM_TRANSPORT * TransportInterface;
  529. unsigned long ServerBootTime;
  530. unsigned long ServerDataRep;
  531. unsigned CurrentPduSize;
  532. unsigned RemoteWindowSize;
  533. boolean fServerSupportsAsync;
  534. boolean fLoneBindingHandle;
  535. enum
  536. {
  537. BROADCAST = 0x100,
  538. UNRESOLVEDEP = 0x200
  539. };
  540. //----------------------------------------------------------
  541. DG_CASSOCIATION(
  542. IN RPC_DATAGRAM_TRANSPORT * a_Transport,
  543. IN LONG a_AssociationFlag,
  544. IN DCE_BINDING * a_DceBinding,
  545. IN BOOL a_Unique,
  546. IN OUT RPC_STATUS * pStatus
  547. );
  548. ~DG_CASSOCIATION();
  549. RPC_STATUS
  550. SendPacket(
  551. IN DG_ENDPOINT Endpoint,
  552. IN PNCA_PACKET_HEADER Header,
  553. IN unsigned SecurityTrailerLength = 0
  554. );
  555. virtual RPC_STATUS
  556. ToStringBinding (
  557. OUT RPC_CHAR * * StringBinding,
  558. IN RPC_UUID * ObjectUuid
  559. );
  560. void IncrementRefCount();
  561. void DecrementRefCount();
  562. int
  563. CompareWithBinding(
  564. IN PDG_BINDING_HANDLE pBinding
  565. );
  566. BOOL
  567. ComparePartialBinding(
  568. IN PDG_BINDING_HANDLE pBinding,
  569. void * Interface
  570. );
  571. BOOL
  572. AddInterface(
  573. void * InterfaceInformation,
  574. RPC_UUID * ObjectUuid
  575. );
  576. BOOL
  577. RemoveInterface(
  578. void * InterfaceInformation,
  579. RPC_UUID * ObjectUuid
  580. );
  581. RPC_STATUS
  582. AllocateCall(
  583. IN PDG_BINDING_HANDLE BindingHandle,
  584. IN const CLIENT_AUTH_INFO * AuthInfo,
  585. OUT PDG_CCALL * ppCall,
  586. IN BOOL fAsync
  587. );
  588. void
  589. ReleaseCall(
  590. IN PDG_CCALL Call
  591. );
  592. PDG_CCONNECTION
  593. AllocateConnection(
  594. IN PDG_BINDING_HANDLE BindingHandle,
  595. IN const CLIENT_AUTH_INFO * AuthInfo,
  596. IN DWORD ThreadId,
  597. IN BOOL fAsync,
  598. OUT RPC_STATUS * pStatus
  599. );
  600. void
  601. ReleaseConnection(
  602. IN PDG_CCONNECTION Call
  603. );
  604. void
  605. DeleteIdleConnections(
  606. long CurrentTime
  607. );
  608. RPC_STATUS
  609. UpdateAssociationWithAddress(
  610. PDG_PACKET Packet,
  611. void * Address
  612. );
  613. BOOL SendKeepAlive();
  614. DCE_BINDING * DuplicateDceBinding ();
  615. void SetErrorFlag () { fErrorFlag = TRUE; }
  616. void ClearErrorFlag() { fErrorFlag = FALSE; }
  617. BOOL ErrorFlag () { return fErrorFlag; }
  618. DG_TRANSPORT_ADDRESS
  619. InqServerAddress ()
  620. {
  621. return ServerAddress;
  622. }
  623. void
  624. CopyServerAddress(
  625. IN DG_TRANSPORT_ADDRESS Destination
  626. );
  627. inline void *
  628. operator new(
  629. IN size_t ObjectLength,
  630. IN const RPC_DATAGRAM_TRANSPORT * Transport
  631. );
  632. BOOL IsAckPending();
  633. void FlushAcks();
  634. void IncrementBindingRefCount(
  635. unsigned ContextHandleRef
  636. );
  637. void DecrementBindingRefCount(
  638. unsigned ContextHandleRef
  639. );
  640. void VerifyNotLocked()
  641. {
  642. Mutex.VerifyNotOwned();
  643. }
  644. BOOL LockOwnedByMe()
  645. {
  646. return Mutex.OwnedByMe();
  647. }
  648. private:
  649. void MutexRequest()
  650. {
  651. #ifdef CHECK_MUTEX_INVERSION
  652. if (!Mutex.OwnedByMe() )
  653. {
  654. DG_CCONNECTION * conn = (DG_CCONNECTION *) ThreadSelf()->ConnectionMutexHeld;
  655. ASSERT( 0 == conn || conn->ThreadId == GetCurrentThreadId() );
  656. }
  657. #endif
  658. Mutex.Request();
  659. }
  660. void MutexClear()
  661. {
  662. Mutex.Clear();
  663. }
  664. INTERLOCKED_INTEGER ReferenceCount;
  665. MUTEX Mutex;
  666. LONG AssociationFlag;
  667. boolean fErrorFlag;
  668. DCE_BINDING * pDceBinding;
  669. long LastScavengeTime;
  670. DG_TRANSPORT_ADDRESS ServerAddress;
  671. DG_CCONNECTION_DICT ActiveConnections;
  672. DG_CCONNECTION_DICT InactiveConnections;
  673. INTERFACE_AND_OBJECT_LIST InterfaceAndObjectDict;
  674. RPC_CHAR * ResolvedEndpoint;
  675. long BindingHandleReferences;
  676. long InternalTableIndex;
  677. DG_BINDING_HANDLE * KeepAliveHandle;
  678. public:
  679. long LastReceiveTime;
  680. };
  681. inline DCE_BINDING *
  682. DG_CASSOCIATION::DuplicateDceBinding (
  683. )
  684. {
  685. CLAIM_MUTEX lock( Mutex );
  686. ASSERT( !InvalidHandle(DG_CASSOCIATION_TYPE) );
  687. return(pDceBinding->DuplicateDceBinding());
  688. }
  689. inline
  690. void
  691. DG_CASSOCIATION::IncrementRefCount(
  692. void
  693. )
  694. {
  695. ASSERT( !InvalidHandle(DG_CASSOCIATION_TYPE) );
  696. long Count = ReferenceCount.Increment();
  697. LogEvent(SU_CASSOC, EV_INC, this, 0, Count);
  698. }
  699. inline void *
  700. DG_CASSOCIATION::operator new(
  701. IN size_t ObjectLength,
  702. IN const RPC_DATAGRAM_TRANSPORT * Transport
  703. )
  704. {
  705. return new char[ObjectLength + 2 * Transport->AddressSize];
  706. }
  707. class DG_ASSOCIATION_TABLE
  708. {
  709. public:
  710. BOOL fCasUuidReady;
  711. UUID CasUuid;
  712. //--------------------------------------------------------------------
  713. typedef LONG HINT;
  714. DG_ASSOCIATION_TABLE(
  715. RPC_STATUS * pStatus
  716. );
  717. ~DG_ASSOCIATION_TABLE()
  718. {
  719. if (Associations != InitialAssociations)
  720. delete Associations;
  721. }
  722. HINT
  723. MakeHint(
  724. DCE_BINDING * pDceBinding
  725. );
  726. RPC_STATUS
  727. Add(
  728. DG_CASSOCIATION * Association
  729. );
  730. DG_CASSOCIATION *
  731. Find(
  732. DG_BINDING_HANDLE * Binding,
  733. RPC_CLIENT_INTERFACE * Interface,
  734. BOOL fContextHandle,
  735. BOOL fPartial,
  736. BOOL fReconnect
  737. );
  738. void
  739. Delete(
  740. DG_CASSOCIATION * Association
  741. );
  742. BOOL
  743. DeleteIdleEntries(
  744. long CurrentTime
  745. );
  746. BOOL
  747. SendContextHandleKeepalives();
  748. void
  749. IncrementContextHandleCount(
  750. DG_CASSOCIATION * Association
  751. );
  752. void
  753. DecrementContextHandleCount(
  754. DG_CASSOCIATION * Association
  755. );
  756. long
  757. GetContextHandleCount(
  758. DG_CASSOCIATION * Association
  759. );
  760. void
  761. UpdateTimeStamp(
  762. DG_CASSOCIATION * Association
  763. );
  764. void LockExclusive()
  765. {
  766. Mutex.LockExclusive();
  767. }
  768. void UnlockExclusive()
  769. {
  770. Mutex.UnlockExclusive();
  771. }
  772. private:
  773. struct NODE
  774. {
  775. DG_CASSOCIATION * Association;
  776. HINT Hint;
  777. BOOL fBusy;
  778. long ContextHandleCount;
  779. long TimeStamp;
  780. };
  781. enum
  782. {
  783. INITIAL_ARRAY_LENGTH = 4,
  784. MINIMUM_IDLE_ENTRIES = 10
  785. };
  786. CSharedLock Mutex;
  787. NODE * Associations;
  788. LONG AssociationsLength;
  789. NODE InitialAssociations[ INITIAL_ARRAY_LENGTH ];
  790. long PreviousFreedCount;
  791. };
  792. extern DG_ASSOCIATION_TABLE * ActiveAssociations;
  793. inline void
  794. DG_CASSOCIATION::IncrementBindingRefCount(
  795. unsigned ContextHandleRef
  796. )
  797. {
  798. ASSERT( ContextHandleRef <= 1 );
  799. // ASSERT( ContextHandleReferences < 100 );
  800. // ASSERT( BindingHandleReferences < 100 );
  801. ++BindingHandleReferences;
  802. if (ContextHandleRef)
  803. {
  804. ActiveAssociations->IncrementContextHandleCount(this);
  805. }
  806. IncrementRefCount();
  807. }
  808. inline void
  809. DG_CASSOCIATION::DecrementBindingRefCount(
  810. unsigned ContextHandleRef
  811. )
  812. {
  813. ASSERT( ContextHandleRef <= 1 );
  814. ASSERT( BindingHandleReferences > 0 );
  815. if (ContextHandleRef)
  816. {
  817. ActiveAssociations->DecrementContextHandleCount(this);
  818. }
  819. // ASSERT( ContextHandleReferences >= 0 );
  820. if (0 == --BindingHandleReferences)
  821. {
  822. FlushAcks();
  823. }
  824. DecrementRefCount();
  825. }
  826. class DG_BINDING_HANDLE : public BINDING_HANDLE
  827. /*++
  828. Class Description:
  829. This class represents a handle pointing at a particular server/endpoint.
  830. Fields:
  831. pDceBinding - Until a DG_CASSOCIATION is found (or created) for this
  832. binding handle, pDceBinding will point at the appropriate DCE_BINDING.
  833. Mutex - Protects this binding handle.
  834. ReferenceCount - Number of DG_CCALLs currently associated with this
  835. binding handle.
  836. DecrementReferenceCount - Decrements the reference count to this binding
  837. handle. If the reference count hits 0, the binding handle is deleted.
  838. DisassociateFromServer - If this is a BH that we couldnt
  839. successfully use, tear down the association
  840. --*/
  841. {
  842. public:
  843. DCE_BINDING * pDceBinding;
  844. DWORD EndpointFlags;
  845. DG_BINDING_HANDLE(
  846. IN OUT RPC_STATUS * RpcStatus
  847. );
  848. //
  849. // This is not a general-purpose constructor.
  850. // The context handle keep-alive code uses it.
  851. //
  852. DG_BINDING_HANDLE(
  853. IN PDG_CASSOCIATION Association,
  854. IN DCE_BINDING * DceBinding,
  855. IN OUT RPC_STATUS * RpcStatus
  856. );
  857. ~DG_BINDING_HANDLE();
  858. virtual RPC_STATUS
  859. NegotiateTransferSyntax (
  860. IN OUT PRPC_MESSAGE Message
  861. )
  862. {
  863. // datagrams don't support multiple syntax
  864. // negotiation. They always return the transfer
  865. // syntax the stub prefers
  866. return RPC_S_OK;
  867. }
  868. RPC_STATUS
  869. GetBuffer (
  870. IN OUT PRPC_MESSAGE Message,
  871. IN UUID *ObjectUuid
  872. );
  873. RPC_STATUS
  874. BindingCopy (
  875. OUT BINDING_HANDLE * * DestinationBinding,
  876. IN unsigned int MaintainContext
  877. );
  878. RPC_STATUS BindingFree ();
  879. PDG_CCONNECTION
  880. GetReplacementConnection(
  881. PDG_CCONNECTION OldConnection,
  882. PRPC_CLIENT_INTERFACE Interface
  883. );
  884. RPC_STATUS
  885. PrepareBindingHandle (
  886. IN TRANS_INFO * TransportInterface,
  887. IN DCE_BINDING * DceBinding
  888. );
  889. RPC_STATUS
  890. ToStringBinding (
  891. OUT RPC_CHAR * * StringBinding
  892. );
  893. RPC_STATUS
  894. ResolveBinding (
  895. IN RPC_CLIENT_INTERFACE * RpcClientInterface
  896. );
  897. RPC_STATUS
  898. BindingReset ();
  899. virtual RPC_STATUS
  900. InquireTransportType(
  901. OUT unsigned int * Type
  902. )
  903. {
  904. *Type = TRANSPORT_TYPE_DG;
  905. return(RPC_S_OK);
  906. }
  907. inline void IncrementRefCount()
  908. {
  909. long Count = ReferenceCount.Increment();
  910. LogEvent(SU_HANDLE, EV_INC, this, 0, Count);
  911. }
  912. void DecrementRefCount();
  913. void
  914. FreeCall(
  915. DG_CCALL * Call
  916. );
  917. void DisassociateFromServer();
  918. unsigned long
  919. MapAuthenticationLevel (
  920. IN unsigned long AuthenticationLevel
  921. );
  922. BOOL
  923. SetTransportAuthentication(
  924. IN unsigned long ulAuthenticationLevel,
  925. IN unsigned long ulAuthenticationService,
  926. OUT RPC_STATUS *pStatus
  927. );
  928. inline BOOL
  929. IsDynamic()
  930. {
  931. return fDynamicEndpoint;
  932. }
  933. RPC_STATUS
  934. SetTransportOption(
  935. IN unsigned long option,
  936. IN ULONG_PTR optionValue
  937. );
  938. RPC_STATUS
  939. InqTransportOption(
  940. IN unsigned long option,
  941. OUT ULONG_PTR * pOptionValue
  942. );
  943. void MutexRequest()
  944. {
  945. #ifdef CHECK_MUTEX_INVERSION
  946. if (!BindingMutex.OwnedByMe() )
  947. {
  948. DG_CCONNECTION * conn = (DG_CCONNECTION *) ThreadSelf()->ConnectionMutexHeld;
  949. ASSERT( 0 == conn || conn->ThreadId == GetCurrentThreadId() );
  950. if (Association)
  951. {
  952. if (Association->LockOwnedByMe() == FALSE)
  953. {
  954. Association->VerifyNotLocked();
  955. }
  956. }
  957. }
  958. #endif
  959. BindingMutex.Request();
  960. }
  961. void MutexClear()
  962. {
  963. BindingMutex.Clear();
  964. }
  965. private:
  966. TRANS_INFO * TransportObject;
  967. RPC_DATAGRAM_TRANSPORT *TransportInterface;
  968. DG_CASSOCIATION * Association;
  969. INTERLOCKED_INTEGER ReferenceCount;
  970. boolean fDynamicEndpoint;
  971. unsigned fContextHandle;
  972. RPC_STATUS
  973. FindOrCreateAssociation(
  974. IN const PRPC_CLIENT_INTERFACE Interface,
  975. IN BOOL fReconnect,
  976. IN BOOL fBroadcast
  977. );
  978. };
  979. inline DG_BINDING_HANDLE::DG_BINDING_HANDLE(
  980. IN OUT RPC_STATUS * pStatus
  981. )
  982. : BINDING_HANDLE (pStatus),
  983. Association (0),
  984. ReferenceCount(1),
  985. pDceBinding (0),
  986. fContextHandle(0),
  987. EndpointFlags (0)
  988. /*++
  989. Routine Description:
  990. The constructor for DG_BINDING_HANDLE. This object represents a
  991. binding to a server. Most of the important members
  992. are set in DG_BINDING_HANDLE::PrepareBindingHandle.
  993. --*/
  994. {
  995. ObjectType = DG_BINDING_HANDLE_TYPE;
  996. LogEvent(SU_HANDLE, EV_CREATE, this);
  997. }
  998. inline DG_BINDING_HANDLE::DG_BINDING_HANDLE(
  999. IN PDG_CASSOCIATION a_Association,
  1000. IN DCE_BINDING * a_DceBinding,
  1001. IN OUT RPC_STATUS * a_pStatus
  1002. )
  1003. : BINDING_HANDLE(a_pStatus),
  1004. Association (a_Association),
  1005. ReferenceCount(1),
  1006. pDceBinding (a_DceBinding),
  1007. fContextHandle(0),
  1008. EndpointFlags (0)
  1009. /*++
  1010. Routine Description:
  1011. The constructor for DG_BINDING_HANDLE. This is a quick and dirty constructor;
  1012. in particular it does not clone the DCE_BINDING.
  1013. --*/
  1014. {
  1015. ObjectType = DG_BINDING_HANDLE_TYPE;
  1016. LogEvent(SU_HANDLE, EV_CREATE, this, 0, *a_pStatus);
  1017. if (0 != *a_pStatus)
  1018. {
  1019. Association = 0;
  1020. }
  1021. }
  1022. inline DG_BINDING_HANDLE::~DG_BINDING_HANDLE()
  1023. /*++
  1024. Routine Description:
  1025. Destructor for the DG_BINDING_HANDLE. Let the association know we aren't
  1026. using it anymore; this may cause it to be deleted.
  1027. Arguments:
  1028. <none>
  1029. Return Value:
  1030. <none>
  1031. --*/
  1032. {
  1033. LogEvent(SU_HANDLE, EV_DELETE, this);
  1034. if (Association != 0)
  1035. {
  1036. Association->DecrementBindingRefCount(fContextHandle);
  1037. }
  1038. delete pDceBinding;
  1039. }
  1040. inline void
  1041. DG_BINDING_HANDLE::DecrementRefCount()
  1042. {
  1043. long Count = ReferenceCount.Decrement();
  1044. LogEvent(SU_HANDLE, EV_DEC, this, 0, Count, TRUE);
  1045. if (Count == 0)
  1046. {
  1047. delete this;
  1048. }
  1049. }
  1050. class DG_CLIENT_CALLBACK : public MESSAGE_OBJECT
  1051. {
  1052. public:
  1053. DG_PACKET * Request;
  1054. DG_CCONNECTION * Connection;
  1055. DG_ENDPOINT * LocalEndpoint;
  1056. DG_TRANSPORT_ADDRESS RemoteAddress;
  1057. //--------------------------------------------------------------------
  1058. inline DG_CLIENT_CALLBACK()
  1059. {
  1060. ObjectType = DG_CALLBACK_TYPE;
  1061. Request = 0;
  1062. }
  1063. inline ~DG_CLIENT_CALLBACK()
  1064. {
  1065. if (Request)
  1066. {
  1067. Request->Free(FALSE);
  1068. }
  1069. }
  1070. virtual RPC_STATUS
  1071. NegotiateTransferSyntax (
  1072. IN OUT PRPC_MESSAGE Message
  1073. )
  1074. {
  1075. // datagrams don't support multiple syntax
  1076. // negotiation. They always return the transfer
  1077. // syntax the stub prefers
  1078. return RPC_S_OK;
  1079. }
  1080. virtual RPC_STATUS
  1081. GetBuffer(
  1082. IN OUT PRPC_MESSAGE Message,
  1083. IN UUID *ObjectUuid
  1084. );
  1085. virtual void
  1086. FreeBuffer(
  1087. IN OUT PRPC_MESSAGE Message
  1088. );
  1089. // not really implemented
  1090. virtual RPC_STATUS
  1091. SendReceive (
  1092. IN OUT PRPC_MESSAGE Message
  1093. );
  1094. virtual RPC_STATUS
  1095. Send(
  1096. PRPC_MESSAGE Message
  1097. );
  1098. virtual RPC_STATUS
  1099. AsyncSend(
  1100. PRPC_MESSAGE Message
  1101. );
  1102. virtual RPC_STATUS
  1103. Receive(
  1104. PRPC_MESSAGE Message,
  1105. unsigned MinimumSize
  1106. );
  1107. virtual RPC_STATUS
  1108. SetAsyncHandle (
  1109. IN RPC_ASYNC_STATE * hAsync
  1110. );
  1111. virtual BOOL
  1112. IsSyncCall ()
  1113. {
  1114. return FALSE;
  1115. }
  1116. inline void
  1117. SendPacket(
  1118. NCA_PACKET_HEADER * Header
  1119. )
  1120. {
  1121. unsigned Frag = (Header->PacketType << 16) | Header->GetFragmentNumber();
  1122. LogEvent( SU_CCONN, EV_PKT_OUT, Connection, 0, Frag);
  1123. LocalEndpoint->TransportInterface->Send(
  1124. &LocalEndpoint->TransportEndpoint,
  1125. RemoteAddress,
  1126. 0,
  1127. 0,
  1128. Header,
  1129. sizeof(NCA_PACKET_HEADER) + Header->GetPacketBodyLen(),
  1130. 0,
  1131. 0
  1132. );
  1133. }
  1134. };
  1135. typedef DG_CLIENT_CALLBACK * PDG_CLIENT_CALLBACK;
  1136. class CLIENT_ACTIVITY_TABLE : private UUID_HASH_TABLE
  1137. {
  1138. public:
  1139. inline
  1140. CLIENT_ACTIVITY_TABLE(
  1141. RPC_STATUS * pStatus
  1142. )
  1143. : UUID_HASH_TABLE(pStatus)
  1144. {
  1145. }
  1146. inline
  1147. ~CLIENT_ACTIVITY_TABLE(
  1148. )
  1149. {
  1150. }
  1151. PDG_CCONNECTION
  1152. Lookup(
  1153. RPC_UUID * Uuid
  1154. );
  1155. inline RPC_STATUS
  1156. Add(
  1157. PDG_CCONNECTION Connection
  1158. );
  1159. inline RPC_STATUS
  1160. Remove(
  1161. PDG_CCONNECTION Connection
  1162. );
  1163. };
  1164. RPC_STATUS
  1165. CLIENT_ACTIVITY_TABLE::Add(
  1166. PDG_CCONNECTION Connection
  1167. )
  1168. {
  1169. ASSERT( !Connection->InConnectionTable );
  1170. Connection->InConnectionTable = TRUE;
  1171. unsigned Hash = MakeHash(&Connection->ActivityNode.Uuid);
  1172. RequestHashMutex(Hash);
  1173. UUID_HASH_TABLE::Add(&Connection->ActivityNode);
  1174. ReleaseHashMutex(Hash);
  1175. return RPC_S_OK;
  1176. }
  1177. RPC_STATUS
  1178. CLIENT_ACTIVITY_TABLE::Remove(
  1179. PDG_CCONNECTION Connection
  1180. )
  1181. {
  1182. if( !Connection->InConnectionTable )
  1183. {
  1184. return RPC_S_OK;
  1185. }
  1186. Connection->InConnectionTable = FALSE;
  1187. unsigned Hash = MakeHash(&Connection->ActivityNode.Uuid);
  1188. RequestHashMutex(Hash);
  1189. UUID_HASH_TABLE::Remove(&Connection->ActivityNode);
  1190. ReleaseHashMutex(Hash);
  1191. return RPC_S_OK;
  1192. }
  1193. class ENDPOINT_MANAGER
  1194. {
  1195. public:
  1196. ENDPOINT_MANAGER(
  1197. IN OUT RPC_STATUS * pStatus
  1198. );
  1199. DG_ENDPOINT *
  1200. RequestEndpoint(
  1201. IN RPC_DATAGRAM_TRANSPORT * TransportInterface,
  1202. IN BOOL Async,
  1203. IN DWORD Flags,
  1204. IN DG_CCALL *Call
  1205. );
  1206. void
  1207. ReleaseEndpoint(
  1208. IN DG_ENDPOINT * Endpoint
  1209. );
  1210. BOOL
  1211. DeleteIdleEndpoints(
  1212. long CurrentTime
  1213. );
  1214. private:
  1215. #define DG_TRANSPORT_COUNT 2
  1216. MUTEX Mutex;
  1217. DWORD LastScavengeTime;
  1218. DG_ENDPOINT_STATS Stats;
  1219. DG_ENDPOINT * AsyncEndpoints[DG_TRANSPORT_COUNT];
  1220. DG_ENDPOINT * Endpoints;
  1221. };
  1222. //------------------------------------------------------------------------
  1223. inline void
  1224. DG_CCONNECTION::AddCallToCache(
  1225. PDG_CCALL Call
  1226. )
  1227. {
  1228. Mutex.VerifyOwned();
  1229. Call->Next = CachedCalls;
  1230. CachedCalls = Call;
  1231. LogEvent(SU_CCALL, EV_STOP, Call, this, Call->GetSequenceNumber() );
  1232. #ifdef DEBUGRPC
  1233. PDG_CCALL Node = ActiveCallHead;
  1234. while (Node)
  1235. {
  1236. ASSERT( Node != Call );
  1237. Node = Node->Next;
  1238. }
  1239. #endif
  1240. }
  1241. void
  1242. DG_CCONNECTION::UpdateAssociation(
  1243. )
  1244. {
  1245. Association->CurrentPduSize = CurrentPduSize;
  1246. Association->RemoteWindowSize = RemoteWindowSize;
  1247. }
  1248. unsigned long
  1249. DG_CCONNECTION::CurrentSequenceNumber()
  1250. {
  1251. return CurrentCall->GetSequenceNumber();
  1252. }
  1253. inline void DG_CCALL::IncrementRefCount()
  1254. {
  1255. ++ReferenceCount;
  1256. LogEvent(SU_CCALL, EV_INC, this, 0, ReferenceCount);
  1257. }
  1258. inline void
  1259. DG_CCALL::SwitchConnection(
  1260. PDG_CCONNECTION NewConnection
  1261. )
  1262. {
  1263. Connection = NewConnection;
  1264. ReadConnectionInfo(NewConnection, 0);
  1265. ActivityHint = 0xffff;
  1266. pSavedPacket->Header.ServerBootTime = NewConnection->Association->ServerBootTime;
  1267. pSavedPacket->Header.ActivityHint = ActivityHint;
  1268. }
  1269. RPC_STATUS
  1270. StandardPacketChecks(
  1271. PDG_PACKET Packet
  1272. );
  1273. #endif // if __DGCLNT_HXX__