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.

271 lines
10 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. Protocol.hxx
  5. Abstract:
  6. The Protocol object definitions
  7. Author:
  8. Kamen Moutafov [KamenM]
  9. Revision History:
  10. KamenM 12/22/1998 Creation
  11. --*/
  12. #if _MSC_VER >= 1200
  13. #pragma once
  14. #endif
  15. #ifndef __PROTOCOL_HXX_
  16. #define __PROTOCOL_HXX_
  17. // uncomment this to turn on PNP debug spew
  18. //#define MAJOR_PNP_DEBUG
  19. enum TransportProtocolStates
  20. {
  21. ProtocolNotLoaded,
  22. ProtocolLoadedWithoutAddress,
  23. ProtocolWasLoadedOrNeedsActivation,
  24. ProtocolLoaded,
  25. ProtocolWasLoadedOrNeedsActivationWithoutAddress,
  26. ProtocolLoadedAndMonitored
  27. };
  28. struct BASE_ASYNC_OBJECT; // forwards
  29. extern RPC_ADDRESS_CHANGE_FN * AddressChangeFn;
  30. void RPC_ENTRY NullAddressChangeFn( PVOID arg );
  31. class TransportProtocol
  32. /*
  33. This object encapsulates a protocol on the transport level. Used primarily for PnP support.
  34. */
  35. {
  36. public:
  37. TransportProtocol(void)
  38. {
  39. State = ProtocolNotLoaded;
  40. RpcpInitializeListHead(&ObjectList);
  41. addressChangeSocket = 0;
  42. // provide arbitrary non-zero code, to indicate that this query has not succeeded
  43. addressChangeOverlapped.Internal = (ULONG_PTR)-1;
  44. }
  45. // If a piece of code detects that a protocol is functional through means other
  46. // than PnP, it may call this function to notify the PnP code that the protocol is functional
  47. // The only effect will be speedier processing of a potential PnP notification
  48. void DetectedAsFunctional(PROTOCOL_ID ProtocolId);
  49. // Whenever a PnP notification arrives, this method needs to be called for each protocol.
  50. // The method is idempotent - it saves the previous state and will no-op redundant calls
  51. // However, this method should not be called before the runtime is ready to accept
  52. // calls on transport addresses
  53. void HandleProtocolChange(IN WSAPROTOCOL_INFO *lpProtocolBuffer, IN int ProtocolCount,
  54. IN PROTOCOL_ID thisProtocolId);
  55. // Adds an object to the list of objects for this protocol. The list is used to track down
  56. // all instances of objects belonging to this protocol when a PnP notification arrives.
  57. void AddObjectToList(IN OUT BASE_ASYNC_OBJECT *pObj);
  58. // Removes an object from the list of objects on this protocol
  59. void RemoveObjectFromList(IN OUT BASE_ASYNC_OBJECT *pObj);
  60. // If a NewAddress query fails asynchronously, this function needs to be called which will
  61. // retry submitting all failed query for this protocol. For non-failed, or non-submitted queries,
  62. // this is a no-op
  63. BOOL ResubmitQueriesIfNecessary(PROTOCOL_ID ProtocolId);
  64. // Handle a PnP notification. Does all necessary processing
  65. static BOOL HandlePnPStateChange(void);
  66. // Calls ResubmitQueriesIfNecessary(PROTOCOL_ID ProtocolId) on all protocols.
  67. static BOOL ResubmitQueriesIfNecessary(void);
  68. // Same as the non-static FunctionalProtocolDetected, except that this one operates
  69. // without this pointer - it will retrieve the appropriate object and will call
  70. // FunctionalProtocolDetected on it.
  71. static void FunctionalProtocolDetected(PROTOCOL_ID ProtocolId);
  72. // Same as AddObjectToList except that it will call AddObjectToList on the appropriate
  73. // protocol
  74. static void AddObjectToProtocolList(IN OUT BASE_ASYNC_OBJECT *pObj);
  75. // Same as RemoveObjectFromList except that it will call RemoveObjectFromList on the appropriate
  76. // protocol
  77. static void RemoveObjectFromProtocolList(IN OUT BASE_ASYNC_OBJECT *pObj);
  78. #if defined(DBG) || defined(_DEBUG)
  79. // will ASSERT that all protocols are in a consistent state
  80. static void AssertTransportProtocolState(void);
  81. // will ASSSERT that this protocol is in a consistent state
  82. void AssertState(PROTOCOL_ID ProtocolId);
  83. // will ASSERT that a protocols list is in a consistent state
  84. static void AssertProtocolListIntegrity(IN BASE_ASYNC_OBJECT *pObj);
  85. void AssertListIntegrity (IN PROTOCOL_ID ProtocolId);
  86. #endif
  87. // Initializes transport address objects that listen on
  88. // interfaces that were recently assigned addresses.
  89. void InitNewAddresses(PROTOCOL_ID ProtocolId);
  90. private:
  91. // attempts to verify that a protocol is functional, and if found so, advances the state of
  92. // the protocol
  93. BOOL VerifyProtocolIsFunctional(PROTOCOL_ID ProtocolId);
  94. // checks whether the given protocol has an address
  95. BOOL DoesAddressSocketHaveAddress(void);
  96. // If there is a pending address change request (WSAIoctl), it cancels it
  97. // if fForceCancel is FALSE, monitored protocols don't have their
  98. // address change requests canceled. If fForceCancel is TRUE,
  99. // all protocols get their address change requests cancelled
  100. void CancelAddressChangeRequestIfNecessary(IN BOOL fForceCancel, IN PROTOCOL_ID ProtocolId);
  101. // Restarts a protocol that was unloaded.
  102. void RestartProtocol(PROTOCOL_ID ProtocolId);
  103. // Unloads a protocol that was loaded.
  104. void UnloadProtocol(PROTOCOL_ID ProtocolId);
  105. // Submits an address change query (WSAIoctl)
  106. BOOL SubmitAddressChangeQuery(void);
  107. // Sets the state of the given protocol. Other code should never directly set the State - it should
  108. // always go through this function. This allows for derivative protocols (like HTTP) to mirror
  109. // the state of their base protocols - TCP
  110. void SetState(TransportProtocolStates newState, PROTOCOL_ID ProtocolId);
  111. // will return whether address change monitoring is required for this protocol. Currently this
  112. // is used only by RPCSS for SPX (in order to start sending updated SAP broadcasts)
  113. // and to initialize TCP/IP transport addresses listening on the NICs that have had
  114. // their IP addresses changed in the selective binding scenarios.
  115. BOOL IsAddressChangeMonitoringOn(PROTOCOL_ID ProtocolId)
  116. {
  117. // If this is TCP & SPX, and somebody actually cares about this (i.e. somebody has
  118. // registered a notification callback), then turn on address monitoring.
  119. // Also turn it on if the firewall table has not yet been fully initialized.
  120. // We will use the address change notification to trigger an update of the table.
  121. return (
  122. (
  123. (
  124. #ifdef SPX_ON
  125. (ProtocolId == SPX)
  126. ||
  127. #endif
  128. (ProtocolId == TCP)
  129. )
  130. &&
  131. IsAddressChangeFnDefined()
  132. )
  133. ||
  134. (
  135. (ProtocolId == TCP)
  136. &&
  137. FirewallTableNeedsUpdating()
  138. )
  139. );
  140. }
  141. BOOL IsAddressChangeFnDefined(void)
  142. {
  143. return (AddressChangeFn != NullAddressChangeFn
  144. && AddressChangeFn != NULL);
  145. }
  146. BOOL FirewallTableNeedsUpdating(void)
  147. {
  148. return (pFirewallTable != NULL
  149. && fFirewallTableFullyInitialized == FALSE);
  150. }
  151. // Trailing protocols are protocols that don't have their own independent transport provider
  152. // They use the transport provider of another protocol, but for some reason we present it
  153. // to the upper layers as different protocols. We call them trailing, because their
  154. // state trails the state of the protocol whose transport they use.
  155. // Currently we have only one of those - HTTP which trails TCP
  156. BOOL IsTrailingProtocol(PROTOCOL_ID ProtocolId)
  157. {
  158. return (ProtocolId == HTTP);
  159. }
  160. void SetStateToLoadedAndMonitorProtocolIfNecessary(PROTOCOL_ID ProtocolId);
  161. // checks if there is an address change request pending, and if there isn't
  162. // submits one. Will also open an address change socket if necessary
  163. BOOL MonitorFunctionalProtocolForAddressChange(PROTOCOL_ID ProtocolId);
  164. // checks if these's an address change request socket, and if there
  165. // isn't it opens one
  166. BOOL OpenAddressChangeRequestSocket(PROTOCOL_ID ProtocolId);
  167. // if ThisProtocolsId is in ProtocolLoadedAndMonitored or ProtocolLoaded state
  168. // move the Mirrored protocol to the corresponding state
  169. void
  170. MirrorProtocolState (
  171. IN PROTOCOL_ID MirrorProtocolId
  172. );
  173. #ifdef MAJOR_PNP_DEBUG
  174. // Dumps the protocol state on the debugger for the current protocol
  175. void DumpProtocolState(PROTOCOL_ID ProtocolId);
  176. // Dumps the protocol state on the debugger for all protocols
  177. static void DumpProtocolState(void);
  178. #endif
  179. // the current state of this protocol
  180. TransportProtocolStates State;
  181. // the list of opened objects for this protocol
  182. LIST_ENTRY ObjectList;
  183. // iff there's address change request submitted on this socket, it will be non-null
  184. SOCKET addressChangeSocket;
  185. // the OVERLAPPED for the address change request (WSAIoctl). It's Internal member will be -1
  186. // if no request has been submitted. Other data members are as normal.
  187. OVERLAPPED addressChangeOverlapped;
  188. // NOTE: A TransportProtocol object is not aware of its PROTOCOL_ID - it must be
  189. // passed externally to it for all methods that require it. This is done to save memory.
  190. };
  191. extern TransportProtocol *TransportProtocolArray;
  192. // returns the TransportProtocol object for the ProtocolId. Ownership of the object does not pass
  193. // to the caller
  194. inline TransportProtocol *GetTransportProtocol(IN PROTOCOL_ID ProtocolId)
  195. {
  196. ASSERT(ProtocolId >= 1);
  197. ASSERT(ProtocolId < MAX_PROTOCOLS);
  198. return &TransportProtocolArray[ProtocolId];
  199. }
  200. inline void TransportProtocol::FunctionalProtocolDetected(PROTOCOL_ID ProtocolId)
  201. {
  202. GetTransportProtocol(ProtocolId)->DetectedAsFunctional(ProtocolId);
  203. }
  204. RPC_STATUS InitTransportProtocols(void);
  205. #if defined(DBG) || defined(_DEBUG)
  206. #define ASSERT_ALL_TRANSPORT_PROTOCOL_STATE() TransportProtocol::AssertTransportProtocolState()
  207. #define ASSERT_TRANSPORT_PROTOCOL_STATE(p) AssertState(p)
  208. #else
  209. #define ASSERT_ALL_TRANSPORT_PROTOCOL_STATE()
  210. #define ASSERT_TRANSPORT_PROTOCOL_STATE(p)
  211. #endif
  212. #endif