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.

1386 lines
36 KiB

  1. /*++
  2. Copyright (c) 1998-2002 Microsoft Corporation
  3. Module Name:
  4. ultdip.h
  5. Abstract:
  6. This module contains declarations private to the TDI component. These
  7. declarations are placed in a separate .H file to make it easier to access
  8. them from within the kernel debugger extension DLL.
  9. The TDI package manages two major object types: UL_ENDPOINT and
  10. UL_CONNECTION.
  11. A UL_ENDPOINT is basically a wrapper around a TDI address object. Each
  12. endpoint has a list of associated UL_CONNECTION objects for
  13. idle (non-connected) connections
  14. Active (connected) connections are on the global connection list.
  15. A UL_CONNECTION is basically a wrapper around a TDI connection object.
  16. Its main purpose is to manage TDI connection state. See the description
  17. of UL_CONNECTION_FLAGS below for the gory details.
  18. The relationship between these two objects is illustrated in the
  19. following diagram:
  20. +-----------+
  21. | |
  22. |UL_ENDPOINT|
  23. | |
  24. +---+----+--+
  25. |
  26. |
  27. | Idle Connections
  28. | +-------------+ +-------------+ +-------------+
  29. | | | | | | |
  30. +->|UL_CONNECTION|-->|UL_CONNECTION|-->|UL_CONNECTION|-->...
  31. | | | | | |
  32. +-------------+ +-------------+ +-------------+
  33. Note: Idle connections do not hold references to their owning endpoint,
  34. but active connections do. When a listening endpoint is shutdown, all
  35. idle connections are simply purged, but active connections must be
  36. forcibly disconnected first.
  37. Author:
  38. Keith Moore (keithmo) 15-Jun-1998
  39. Revision History:
  40. --*/
  41. #ifndef _ULTDIP_H_
  42. #define _ULTDIP_H_
  43. //
  44. // Forward references.
  45. //
  46. typedef struct _UL_ENDPOINT *PUL_ENDPOINT;
  47. typedef union _UL_CONNECTION_FLAGS *PUL_CONNECTION_FLAGS;
  48. typedef struct _UL_CONNECTION *PUL_CONNECTION;
  49. typedef struct _UL_RECEIVE_BUFFER *PUL_RECEIVE_BUFFER;
  50. //
  51. // Private constants.
  52. //
  53. #define MAX_ADDRESS_EA_BUFFER_LENGTH \
  54. (sizeof(FILE_FULL_EA_INFORMATION) - 1 + \
  55. TDI_TRANSPORT_ADDRESS_LENGTH + 1 + \
  56. sizeof(TA_IP6_ADDRESS))
  57. #define MAX_CONNECTION_EA_BUFFER_LENGTH \
  58. (sizeof(FILE_FULL_EA_INFORMATION) - 1 + \
  59. TDI_CONNECTION_CONTEXT_LENGTH + 1 + \
  60. sizeof(CONNECTION_CONTEXT))
  61. #define TL_INSTANCE 0
  62. //
  63. // Private types.
  64. //
  65. //
  66. // A generic IRP context. This is useful for storing additional completion
  67. // information associated with a pending IRP.
  68. //
  69. // WARNING! All fields of this structure must be explicitly initialized.
  70. //
  71. typedef struct _UL_IRP_CONTEXT
  72. {
  73. //
  74. // This MUST be the first field in the structure. This is the linkage
  75. // used by the lookaside package for storing entries in the lookaside
  76. // list.
  77. //
  78. SLIST_ENTRY LookasideEntry;
  79. //
  80. // Structure signature.
  81. //
  82. ULONG Signature;
  83. //
  84. // Either the endpoint or endpoint associated with the IRP.
  85. //
  86. PVOID pConnectionContext;
  87. //
  88. // Completion information.
  89. //
  90. PUL_COMPLETION_ROUTINE pCompletionRoutine;
  91. PVOID pCompletionContext;
  92. //
  93. // Our own allocated IRP if set.
  94. //
  95. PIRP pOwnIrp;
  96. //
  97. // The TDI send flag (0 or TDI_SEND_AND_DISCONNECT).
  98. //
  99. USHORT TdiSendFlag;
  100. //
  101. // Our own allocated UL_IRP_CONTEXT if set.
  102. //
  103. BOOLEAN OwnIrpContext;
  104. //
  105. // Total send length we passed to TDI_SEND.
  106. //
  107. ULONG_PTR SendLength;
  108. } UL_IRP_CONTEXT, *PUL_IRP_CONTEXT;
  109. #define UL_IRP_CONTEXT_SIGNATURE MAKE_SIGNATURE('IRPC')
  110. #define UL_IRP_CONTEXT_SIGNATURE_X MAKE_FREE_SIGNATURE(UL_IRP_CONTEXT_SIGNATURE)
  111. #define IS_VALID_IRP_CONTEXT(pIrpContext) \
  112. HAS_VALID_SIGNATURE(pIrpContext, UL_IRP_CONTEXT_SIGNATURE)
  113. typedef enum _CONN_LIST_STATE
  114. {
  115. NoConnList = 1,
  116. IdleConnList,
  117. ActiveNoConnList,
  118. RetiringNoConnList
  119. } CONN_LIST_STATE;
  120. //
  121. // A TDI Address Object and it's pre-allocated lists of idle connections.
  122. // This is allocated together with a UL_ENDPOINT, which always has at
  123. // least one of these objects.
  124. //
  125. // This does not need a ref count since it's "contained" as part of
  126. // a UL_ENDPOINT object.
  127. //
  128. // CODEWORK: When we want to do dynamic addition/removal of this object,
  129. // we'll need to add ref counting & add list-linkage to the endpoint,
  130. // rather than as an array tacked on the end.
  131. //
  132. // Methods on this pseudo-class:
  133. // UlpInitializeAddrIdleList
  134. // UlpCleanupAddrIdleList
  135. // UlpReplenishAddrIdleList
  136. // UlpReplenishAddrIdleListWorker
  137. // UlpTrimAddrIdleListWorker
  138. //
  139. typedef struct _UL_ADDR_IDLE_LIST
  140. {
  141. //
  142. // Structure signature: UL_ADDR_IDLE_LIST_SIGNATURE
  143. //
  144. ULONG Signature;
  145. //
  146. // The TDI address object.
  147. //
  148. UX_TDI_OBJECT AddressObject;
  149. //
  150. // The local address we're bound to.
  151. //
  152. UL_TRANSPORT_ADDRESS LocalAddress;
  153. ULONG LocalAddressLength;
  154. //
  155. // Heads of the per-address object connection lists.
  156. // Idle connections have a weak reference to 'this', the owning endpoint
  157. //
  158. HANDLE IdleConnectionSListsHandle;
  159. //
  160. // When replenish is scheduled, we need to remember the cpu.
  161. //
  162. USHORT CpuToReplenish;
  163. //
  164. // The owning endpoint
  165. //
  166. PUL_ENDPOINT pOwningEndpoint;
  167. //
  168. // Work item for replenishing
  169. //
  170. UL_WORK_ITEM WorkItem;
  171. LONG WorkItemScheduled;
  172. } UL_ADDR_IDLE_LIST, *PUL_ADDR_IDLE_LIST;
  173. #define UL_ADDR_IDLE_LIST_SIGNATURE MAKE_SIGNATURE('UlAI')
  174. #define UL_ADDR_IDLE_LIST_SIGNATURE_X MAKE_FREE_SIGNATURE(UL_ADDR_IDLE_LIST_SIGNATURE)
  175. #define IS_VALID_ADDR_IDLE_LIST(pAddrIdleList) \
  176. HAS_VALID_SIGNATURE(pAddrIdleList, UL_ADDR_IDLE_LIST_SIGNATURE)
  177. typedef struct _UL_TRIM_TIMER
  178. {
  179. //
  180. // Timer itself and the corresponding Dpc object.
  181. //
  182. KTIMER Timer;
  183. KDPC DpcObject;
  184. UL_WORK_ITEM WorkItem;
  185. LONG WorkItemScheduled;
  186. LIST_ENTRY ZombieConnectionListHead;
  187. //
  188. // Spinlock to protect the following state parameters
  189. //
  190. UL_SPIN_LOCK SpinLock;
  191. BOOLEAN Initialized;
  192. BOOLEAN Started;
  193. } UL_TRIM_TIMER, *PUL_TRIM_TIMER;
  194. //
  195. // An endpoint is basically our wrapper around TDI address objects.
  196. // There is one UL_ENDPOINT per TCP Port. In the common case, there will
  197. // be three ports: 80 (HTTP), 443 (HTTPS), and a random port for the
  198. // IIS Admin site.
  199. //
  200. typedef struct _UL_ENDPOINT
  201. {
  202. //
  203. // Structure signature: UL_ENDPOINT_SIGNATURE
  204. //
  205. ULONG Signature;
  206. //
  207. // Reference count.
  208. //
  209. LONG ReferenceCount;
  210. //
  211. // Usage count. This is used by the "URL-site-to-endpoint" thingie.
  212. //
  213. LONG UsageCount;
  214. //
  215. // Links onto the global endpoint list.
  216. //
  217. // GlobalEndpointListEntry.Flink is NULL if the endpoint is not
  218. // on the global list, g_TdiEndpointListHead, or the
  219. // to-be-deleted-soon list, g_TdiDeletedEndpointListHead.
  220. //
  221. LIST_ENTRY GlobalEndpointListEntry;
  222. //
  223. // Array of TDI Address Object + Connection Objects.
  224. // One per entry on the global "Listen Only" list, or one entry
  225. // representing INADDR_ANY/in6addr_any. Allocated at endpoint
  226. // creation time, directly after the UL_ENDPOINT.
  227. //
  228. ULONG AddrIdleListCount;
  229. // REVIEW: what's the team's hungarian notation for an array?
  230. PUL_ADDR_IDLE_LIST aAddrIdleLists;
  231. // CODEWORK: ability to change from INADDR_ANY to Listen Only List
  232. // and vice versa.
  233. // CODEWORK: ability to dynamicly add/remove AO's. (need spinlock)
  234. //
  235. // Indication handlers & user context.
  236. //
  237. PUL_CONNECTION_REQUEST pConnectionRequestHandler;
  238. PUL_CONNECTION_COMPLETE pConnectionCompleteHandler;
  239. PUL_CONNECTION_DISCONNECT pConnectionDisconnectHandler;
  240. PUL_CONNECTION_DISCONNECT_COMPLETE pConnectionDisconnectCompleteHandler;
  241. PUL_CONNECTION_DESTROYED pConnectionDestroyedHandler;
  242. PUL_DATA_RECEIVE pDataReceiveHandler;
  243. PVOID pListeningContext;
  244. //
  245. // The local TCP Port we're bound to.
  246. //
  247. USHORT LocalPort;
  248. //
  249. // Is this a secure endpoint?
  250. //
  251. BOOLEAN Secure;
  252. //
  253. // Thread work item for deferred actions.
  254. //
  255. UL_WORK_ITEM WorkItem;
  256. LONG WorkItemScheduled;
  257. //
  258. // An IRP context containing completion information necessary
  259. // while shutting down a listening endpoint.
  260. //
  261. UL_IRP_CONTEXT CleanupIrpContext;
  262. //
  263. // Has this endpoint taken a g_TdiEndpointCount?
  264. //
  265. BOOLEAN Counted;
  266. //
  267. // Has this endpoint been moved to the deleted list,
  268. // g_TdiDeletedEndpointListHead?
  269. //
  270. BOOLEAN Deleted;
  271. } UL_ENDPOINT;
  272. #define UL_ENDPOINT_SIGNATURE MAKE_SIGNATURE('ENDP')
  273. #define UL_ENDPOINT_SIGNATURE_X MAKE_FREE_SIGNATURE(UL_ENDPOINT_SIGNATURE)
  274. #define IS_VALID_ENDPOINT(pEndpoint) \
  275. HAS_VALID_SIGNATURE(pEndpoint, UL_ENDPOINT_SIGNATURE)
  276. //
  277. // Connection flags/state. These flags indicate the current state of a
  278. // connection.
  279. //
  280. // Some of these flags may be simply updated directly. Others require
  281. // UlInterlockedCompareExchange() to avoid race conditions.
  282. //
  283. // The following flags may be updated directly:
  284. //
  285. // AcceptPending - SET in the TDI connection handler, just before the
  286. // accept IRP is returned to the transport. RESET only if the accept
  287. // IRP fails.
  288. //
  289. // The following flags must be updated using UlInterlockedCompareExchange():
  290. //
  291. // AcceptComplete - SET in the accept IRP completion handler if the IRP
  292. // completed successfully. Once this flag is set, the connection must
  293. // be either gracefully disconnected or aborted before the connection
  294. // can be closed or reused.
  295. //
  296. // DisconnectPending - SET just before a graceful disconnect IRP is
  297. // issued.
  298. //
  299. // DisconnectComplete - SET in the graceful disconnect IRP completion
  300. // handler.
  301. //
  302. // AbortPending - SET just before an abortive disconnect IRP is issued.
  303. //
  304. // AbortComplete - SET in the abortive disconnect IRP completion handler.
  305. //
  306. // DisconnectIndicated - SET in the TDI disconnect handler for graceful
  307. // disconnects issued by the remote client.
  308. //
  309. // AbortIndicated - SET in the TDI disconnect handler for abortive
  310. // disconnects issued by the remote client.
  311. //
  312. // CleanupPending - SET when cleanup is begun for a connection. This
  313. // is necessary to know when the final reference to the connection
  314. // can be removed.
  315. //
  316. // CODEWORK: We can get rid of the CleanupPending flag. It is
  317. // only set when either a graceful or abortive disconnect is
  318. // issued, and only tested in UlpRemoveFinalReference(). The
  319. // test in UlpRemoveFinalReference() can just test for either
  320. // (DisconnectPending | AbortPending) instead.
  321. //
  322. // FinalReferenceRemoved - SET when the final (i.e. "connected")
  323. // reference is removed from the connection.
  324. //
  325. // Note that the flags requiring UlInterlockedCompareExchange() are only SET,
  326. // never RESET. This makes the implementation a bit simpler.
  327. //
  328. // And now a few words about connection management, TDI, and other mysteries.
  329. //
  330. // Some of the more annoying "features" of TDI are related to connection
  331. // management and lifetime. Two of the most onerous issues are:
  332. //
  333. // 1. Knowing when a connection object handle can be closed without
  334. // causing an unwanted connection reset.
  335. //
  336. // 2. Knowing when TDI has given its last indication on a connection
  337. // so that resources can be released, reused, recycled, whatever.
  338. //
  339. // And, of course, this is further complicated by the inherent asynchronous
  340. // nature of the NT I/O architecture and the parallelism of SMP systems.
  341. //
  342. // There are a few points worth keeping in mind while reading/modifying this
  343. // source code or writing clients of this code:
  344. //
  345. // 1. As soon as an accept IRP is returned from the TDI connection
  346. // handler to the transport, the TDI client must be prepared for
  347. // any incoming indications, including data receive and disconnect.
  348. // In other words, incoming data & disconnect may occur *before* the
  349. // accept IRP actually completes.
  350. //
  351. // 2. A connection is considered "in use" until either both sides have
  352. // gracefully disconnected OR either side has aborted the connection.
  353. // Closing an "in use" connection will usually result in an abortive
  354. // disconnect.
  355. //
  356. // 3. The various flavors of disconnect (initiated by the local server,
  357. // initiated by the remote client, graceful, abortive, etc) may occur
  358. // in any order.
  359. //
  360. typedef union _UL_CONNECTION_FLAGS
  361. {
  362. //
  363. // This field overlays all of the settable flags. This allows us to
  364. // update all flags in a thread-safe manner using the
  365. // UlInterlockedCompareExchange() API.
  366. //
  367. ULONG Value;
  368. struct
  369. {
  370. ULONG AcceptPending:1; // 00000001 Recv SYN
  371. ULONG AcceptComplete:1; // 00000002 Accepted
  372. ULONG :2;
  373. ULONG DisconnectPending:1; // 00000010 Send FIN
  374. ULONG DisconnectComplete:1; // 00000020 Send FIN
  375. ULONG :2;
  376. ULONG AbortPending:1; // 00000100 Send RST
  377. ULONG AbortComplete:1; // 00000200 Send RST
  378. ULONG :2;
  379. ULONG DisconnectIndicated:1; // 00001000 Recv FIN
  380. ULONG AbortIndicated:1; // 00002000 Recv RST
  381. ULONG :2;
  382. ULONG CleanupBegun:1; // 00010000
  383. ULONG FinalReferenceRemoved:1; // 00020000
  384. ULONG AbortDisconnect:1; // 00040000 Send RST after Send FIN
  385. ULONG :1;
  386. ULONG LocalAddressValid:1; // 00100000
  387. ULONG ReceivePending:1; // 00200000
  388. ULONG :2;
  389. ULONG TdiConnectionInvalid:1; // 01000000
  390. };
  391. } UL_CONNECTION_FLAGS;
  392. C_ASSERT( sizeof(UL_CONNECTION_FLAGS) == sizeof(ULONG) );
  393. #define MAKE_CONNECTION_FLAG_ROUTINE(name) \
  394. __inline ULONG Make##name##Flag() \
  395. { \
  396. UL_CONNECTION_FLAGS flags = { 0 }; \
  397. flags.name = 1; \
  398. return flags.Value; \
  399. }
  400. MAKE_CONNECTION_FLAG_ROUTINE( AcceptPending );
  401. MAKE_CONNECTION_FLAG_ROUTINE( AcceptComplete );
  402. MAKE_CONNECTION_FLAG_ROUTINE( DisconnectPending );
  403. MAKE_CONNECTION_FLAG_ROUTINE( DisconnectComplete );
  404. MAKE_CONNECTION_FLAG_ROUTINE( AbortPending );
  405. MAKE_CONNECTION_FLAG_ROUTINE( AbortComplete );
  406. MAKE_CONNECTION_FLAG_ROUTINE( DisconnectIndicated );
  407. MAKE_CONNECTION_FLAG_ROUTINE( AbortIndicated );
  408. MAKE_CONNECTION_FLAG_ROUTINE( CleanupBegun );
  409. MAKE_CONNECTION_FLAG_ROUTINE( FinalReferenceRemoved );
  410. MAKE_CONNECTION_FLAG_ROUTINE( AbortDisconnect );
  411. MAKE_CONNECTION_FLAG_ROUTINE( LocalAddressValid );
  412. MAKE_CONNECTION_FLAG_ROUTINE( ReceivePending );
  413. MAKE_CONNECTION_FLAG_ROUTINE( TdiConnectionInvalid );
  414. typedef enum _UL_CONNECTION_STATE
  415. {
  416. UlConnectStateConnectIdle, // Idle
  417. UlConnectStateConnectCleanup, // Cleanup
  418. UlConnectStateConnectReady, // In Use
  419. UlConnectStateDisconnectPending, // Sent FIN
  420. UlConnectStateDisconnectComplete, // FIN Completes
  421. UlConnectStateAbortPending, // Send RST
  422. UlConnectStateInvalid // TBD
  423. } UL_CONNECTION_STATE;
  424. //
  425. // A connection is basically our wrapper around a TDI connection object.
  426. //
  427. typedef struct _UL_CONNECTION
  428. {
  429. //
  430. // Link onto the per-endpoint idle connection list.
  431. //
  432. SLIST_ENTRY IdleSListEntry;
  433. //
  434. // Structure signature: UL_CONNECTION_SIGNATURE
  435. //
  436. ULONG Signature;
  437. //
  438. // Reference count.
  439. //
  440. LONG ReferenceCount;
  441. //
  442. // Connection flags.
  443. //
  444. UL_CONNECTION_FLAGS ConnectionFlags;
  445. //
  446. // To synchronize the RawCloseHandler
  447. //
  448. UL_CONNECTION_STATE ConnectionState;
  449. UL_SPIN_LOCK ConnectionStateSpinLock;
  450. //
  451. // Cached Irp
  452. //
  453. PIRP pIrp;
  454. //
  455. // Addresses and ports. These are in host order.
  456. //
  457. USHORT AddressType;
  458. USHORT AddressLength;
  459. union
  460. {
  461. UCHAR RemoteAddress[0];
  462. TDI_ADDRESS_IP RemoteAddrIn;
  463. TDI_ADDRESS_IP6 RemoteAddrIn6;
  464. };
  465. union
  466. {
  467. UCHAR LocalAddress[0];
  468. TDI_ADDRESS_IP LocalAddrIn;
  469. TDI_ADDRESS_IP6 LocalAddrIn6;
  470. };
  471. //
  472. // Structure to get LocalAddress when Accept completes
  473. //
  474. TDI_CONNECTION_INFORMATION TdiConnectionInformation;
  475. UL_TRANSPORT_ADDRESS Ta;
  476. //
  477. // The Inteface & Link IDs as reported by TCP. These are filled
  478. // only on demand.
  479. //
  480. ULONG InterfaceId;
  481. ULONG LinkId;
  482. BOOLEAN bRoutingLookupDone;
  483. //
  484. //
  485. // On the endpoint's idle, active, or retiring connections list
  486. //
  487. CONN_LIST_STATE ConnListState;
  488. //
  489. // The TDI connection object.
  490. //
  491. UX_TDI_OBJECT ConnectionObject;
  492. //
  493. // User context.
  494. //
  495. PVOID pConnectionContext;
  496. //
  497. // The endpoint associated with this connection. Note that this
  498. // ALWAYS points to a valid endpoint. For idle connections, it's
  499. // a weak (non referenced) pointer. For active connections, it's
  500. // a strong (referenced) pointer.
  501. //
  502. PUL_ENDPOINT pOwningEndpoint;
  503. //
  504. // TDI wrapper & list managment object associated with the
  505. // pOwningEndpoint.
  506. //
  507. PUL_ADDR_IDLE_LIST pOwningAddrIdleList;
  508. //
  509. // The processor where this connection was allocated from
  510. // the idle list
  511. //
  512. ULONG OriginProcessor;
  513. //
  514. // Thread work item for deferred actions.
  515. //
  516. UL_WORK_ITEM WorkItem;
  517. //
  518. // Data captured from the listening endpoint at the time the
  519. // connection is created. This is captured to reduce references
  520. // to the listening endpoint.
  521. //
  522. PUL_CONNECTION_DESTROYED pConnectionDestroyedHandler;
  523. PVOID pListeningContext;
  524. //
  525. // Pre-allocated IrpContext for disconnect.
  526. //
  527. UL_IRP_CONTEXT IrpContext;
  528. //
  529. // HTTP connection.
  530. //
  531. UL_HTTP_CONNECTION HttpConnection;
  532. //
  533. // Filter related info.
  534. //
  535. UX_FILTER_CONNECTION FilterInfo;
  536. //
  537. // We've had too many problems with orphaned UL_CONNECTIONs.
  538. // Let's make it easy to find them all in the debugger.
  539. //
  540. LIST_ENTRY GlobalConnectionListEntry;
  541. //
  542. // Link to the short-lived retiring list in
  543. // UlpDisconnectAllActiveConnections.
  544. //
  545. LIST_ENTRY RetiringListEntry;
  546. #if REFERENCE_DEBUG
  547. //
  548. // Private Reference trace log.
  549. //
  550. PTRACE_LOG pTraceLog;
  551. PTRACE_LOG pHttpTraceLog;
  552. #endif // REFERENCE_DEBUG
  553. } UL_CONNECTION, *PUL_CONNECTION;
  554. #define UL_CONNECTION_SIGNATURE MAKE_SIGNATURE('CONN')
  555. #define UL_CONNECTION_SIGNATURE_X MAKE_FREE_SIGNATURE(UL_CONNECTION_SIGNATURE)
  556. #define IS_VALID_CONNECTION(pConnection) \
  557. HAS_VALID_SIGNATURE(pConnection, UL_CONNECTION_SIGNATURE)
  558. //
  559. // A buffer, containing a precreated receive IRP, a precreated MDL, and
  560. // sufficient space for a partial MDL. These buffers are typically used
  561. // when passing a receive IRP back to the transport from within our receive
  562. // indication handler.
  563. //
  564. // The buffer structure, IRP, MDLs, and data area are all allocated in a
  565. // single pool block. The layout of the block is:
  566. //
  567. // +-------------------+
  568. // | |
  569. // | UL_RECEIVE_BUFFER |
  570. // | |
  571. // +-------------------+
  572. // | |
  573. // | IRP |
  574. // | |
  575. // +-------------------+
  576. // | |
  577. // | MDL |
  578. // | |
  579. // +-------------------+
  580. // | |
  581. // | Partial MDL |
  582. // | |
  583. // +-------------------+
  584. // | |
  585. // | Data Area |
  586. // | |
  587. // +-------------------+
  588. //
  589. // WARNING! All fields of this structure must be explicitly initialized.
  590. //
  591. typedef struct _UL_RECEIVE_BUFFER
  592. {
  593. //
  594. // This MUST be the first field in the structure. This is the linkage
  595. // used by the lookaside package for storing entries in the lookaside
  596. // list.
  597. //
  598. SLIST_ENTRY LookasideEntry;
  599. //
  600. // Structure signature: UL_RECEIVE_BUFFER_SIGNATURE
  601. //
  602. ULONG Signature;
  603. //
  604. // Amount of unread data in the data area.
  605. //
  606. ULONG UnreadDataLength;
  607. //
  608. // The pre-built receive IRP.
  609. //
  610. PIRP pIrp;
  611. //
  612. // The pre-built MDL describing the entire data area.
  613. //
  614. PMDL pMdl;
  615. //
  616. // A secondary MDL describing part of the data area.
  617. //
  618. PMDL pPartialMdl;
  619. //
  620. // Pointer to the data area for this buffer.
  621. //
  622. PVOID pDataArea;
  623. //
  624. // Pointer to the connection referencing this buffer.
  625. //
  626. PVOID pConnectionContext;
  627. } UL_RECEIVE_BUFFER;
  628. #define UL_RECEIVE_BUFFER_SIGNATURE MAKE_SIGNATURE('RBUF')
  629. #define UL_RECEIVE_BUFFER_SIGNATURE_X MAKE_FREE_SIGNATURE(UL_RECEIVE_BUFFER_SIGNATURE)
  630. #define IS_VALID_RECEIVE_BUFFER(pBuffer) \
  631. HAS_VALID_SIGNATURE(pBuffer, UL_RECEIVE_BUFFER_SIGNATURE)
  632. //
  633. // Private prototypes.
  634. //
  635. VOID
  636. UlpDestroyEndpoint(
  637. IN PUL_ENDPOINT pEndpoint
  638. );
  639. VOID
  640. UlpDestroyConnectionWorker(
  641. IN PUL_WORK_ITEM pWorkItem
  642. );
  643. VOID
  644. UlpDestroyConnection(
  645. IN PUL_CONNECTION pConnection
  646. );
  647. PUL_CONNECTION
  648. UlpDequeueIdleConnection(
  649. IN PUL_ADDR_IDLE_LIST pAddrIdleList
  650. );
  651. PUL_CONNECTION
  652. UlpDequeueIdleConnectionToDrain(
  653. IN PUL_ADDR_IDLE_LIST pAddrIdleList
  654. );
  655. VOID
  656. UlpEnqueueActiveConnection(
  657. IN PUL_CONNECTION pConnection
  658. );
  659. NTSTATUS
  660. UlpConnectHandler(
  661. IN PVOID pTdiEventContext,
  662. IN LONG RemoteAddressLength,
  663. IN PVOID pRemoteAddress,
  664. IN LONG UserDataLength,
  665. IN PVOID pUserData,
  666. IN LONG OptionsLength,
  667. IN PVOID pOptions,
  668. OUT CONNECTION_CONTEXT *pConnectionContext,
  669. OUT PIRP *pAcceptIrp
  670. );
  671. NTSTATUS
  672. UlpDisconnectHandler(
  673. IN PVOID pTdiEventContext,
  674. IN CONNECTION_CONTEXT ConnectionContext,
  675. IN LONG DisconnectDataLength,
  676. IN PVOID pDisconnectData,
  677. IN LONG DisconnectInformationLength,
  678. IN PVOID pDisconnectInformation,
  679. IN ULONG DisconnectFlags
  680. );
  681. VOID
  682. UlpDoDisconnectNotification(
  683. IN PVOID pConnectionContext
  684. );
  685. NTSTATUS
  686. UlpCloseRawConnection(
  687. IN PVOID pConnectionContext,
  688. IN BOOLEAN AbortiveDisconnect,
  689. IN PUL_COMPLETION_ROUTINE pCompletionRoutine,
  690. IN PVOID pCompletionContext
  691. );
  692. NTSTATUS
  693. UlpSendRawData(
  694. IN PVOID pConnectionContext,
  695. IN PMDL pMdlChain,
  696. IN ULONG Length,
  697. IN PUL_IRP_CONTEXT pIrpContext,
  698. IN BOOLEAN InitiateDisconnect
  699. );
  700. NTSTATUS
  701. UlpReceiveRawData(
  702. IN PVOID pConnectionContext,
  703. IN PVOID pBuffer,
  704. IN ULONG BufferLength,
  705. IN PUL_COMPLETION_ROUTINE pCompletionRoutine,
  706. IN PVOID pCompletionContext
  707. );
  708. NTSTATUS
  709. UlpDummyReceiveHandler(
  710. IN PVOID pTdiEventContext,
  711. IN PVOID ConnectionContext,
  712. IN PVOID pTsdu,
  713. IN ULONG BytesIndicated,
  714. IN ULONG BytesUnreceived,
  715. OUT ULONG *pBytesTaken
  716. );
  717. NTSTATUS
  718. UlpReceiveHandler(
  719. IN PVOID pTdiEventContext,
  720. IN CONNECTION_CONTEXT ConnectionContext,
  721. IN ULONG ReceiveFlags,
  722. IN ULONG BytesIndicated,
  723. IN ULONG BytesAvailable,
  724. OUT ULONG *pBytesTaken,
  725. IN PVOID pTsdu,
  726. OUT PIRP *pIrp
  727. );
  728. NTSTATUS
  729. UlpReceiveExpeditedHandler(
  730. IN PVOID pTdiEventContext,
  731. IN CONNECTION_CONTEXT ConnectionContext,
  732. IN ULONG ReceiveFlags,
  733. IN ULONG BytesIndicated,
  734. IN ULONG BytesAvailable,
  735. OUT ULONG *pBytesTaken,
  736. IN PVOID pTsdu,
  737. OUT PIRP *pIrp
  738. );
  739. NTSTATUS
  740. UlpRestartAccept(
  741. IN PDEVICE_OBJECT pDeviceObject,
  742. IN PIRP pIrp,
  743. IN PVOID pContext
  744. );
  745. NTSTATUS
  746. UlpRestartSendData(
  747. IN PDEVICE_OBJECT pDeviceObject,
  748. IN PIRP pIrp,
  749. IN PVOID pContext
  750. );
  751. VOID
  752. UlpReferenceEndpoint(
  753. IN PUL_ENDPOINT pEndpoint,
  754. IN REFTRACE_ACTION Action
  755. REFERENCE_DEBUG_FORMAL_PARAMS
  756. );
  757. VOID
  758. UlpDereferenceEndpoint(
  759. IN PUL_ENDPOINT pEndpoint,
  760. IN PUL_CONNECTION pConnToEnqueue,
  761. IN REFTRACE_ACTION Action
  762. REFERENCE_DEBUG_FORMAL_PARAMS
  763. );
  764. #define REFERENCE_ENDPOINT(endp, action) \
  765. UlpReferenceEndpoint( \
  766. (endp), \
  767. (action) \
  768. REFERENCE_DEBUG_ACTUAL_PARAMS \
  769. )
  770. #define DEREFERENCE_ENDPOINT_SELF(endp, action) \
  771. UlpDereferenceEndpoint( \
  772. (endp), \
  773. NULL, \
  774. (action) \
  775. REFERENCE_DEBUG_ACTUAL_PARAMS \
  776. )
  777. #define DEREFERENCE_ENDPOINT_CONNECTION(endp, conn, action) \
  778. UlpDereferenceEndpoint( \
  779. (endp), \
  780. (conn), \
  781. (action) \
  782. REFERENCE_DEBUG_ACTUAL_PARAMS \
  783. )
  784. VOID
  785. UlpEndpointCleanupWorker(
  786. IN PUL_WORK_ITEM pWorkItem
  787. );
  788. VOID
  789. UlpCleanupConnectionId(
  790. IN PUL_CONNECTION pConnection
  791. );
  792. VOID
  793. UlpConnectionCleanupWorker(
  794. IN PUL_WORK_ITEM pWorkItem
  795. );
  796. NTSTATUS
  797. UlpAssociateConnection(
  798. IN PUL_CONNECTION pConnection,
  799. IN PUL_ADDR_IDLE_LIST pAddrIdleList
  800. );
  801. NTSTATUS
  802. UlpDisassociateConnection(
  803. IN PUL_CONNECTION pConnection
  804. );
  805. NTSTATUS
  806. UlpInitializeAddrIdleList(
  807. IN PUL_ENDPOINT pEndpoint,
  808. IN USHORT Port,
  809. IN PUL_TRANSPORT_ADDRESS pTa,
  810. IN OUT PUL_ADDR_IDLE_LIST pAddrIdleList
  811. );
  812. VOID
  813. UlpCleanupAddrIdleList(
  814. PUL_ADDR_IDLE_LIST pAddrIdleList
  815. );
  816. NTSTATUS
  817. UlpReplenishAddrIdleList(
  818. IN PUL_ADDR_IDLE_LIST pAddrIdleList,
  819. IN BOOLEAN PopulateAll
  820. );
  821. VOID
  822. UlpReplenishAddrIdleListWorker(
  823. IN PUL_WORK_ITEM pWorkItem
  824. );
  825. VOID
  826. UlpTrimAddrIdleListWorker(
  827. IN PUL_WORK_ITEM pWorkItem
  828. );
  829. NTSTATUS
  830. UlpCreateConnection(
  831. IN PUL_ADDR_IDLE_LIST pAddrIdleList,
  832. OUT PUL_CONNECTION *ppConnection
  833. );
  834. NTSTATUS
  835. UlpInitializeConnection(
  836. IN PUL_CONNECTION pConnection
  837. );
  838. __inline
  839. VOID
  840. UlpSetConnectionFlag(
  841. IN OUT PUL_CONNECTION pConnection,
  842. IN ULONG NewFlag
  843. )
  844. {
  845. UL_CONNECTION_FLAGS oldFlags;
  846. UL_CONNECTION_FLAGS newFlags;
  847. //
  848. // Sanity check.
  849. //
  850. ASSERT( IS_VALID_CONNECTION( pConnection ) );
  851. for (;;)
  852. {
  853. //
  854. // Capture the current value and initialize the new value.
  855. //
  856. newFlags.Value = oldFlags.Value =
  857. *((volatile LONG *) &pConnection->ConnectionFlags.Value);
  858. newFlags.Value |= NewFlag;
  859. if (InterlockedCompareExchange(
  860. (PLONG) &pConnection->ConnectionFlags.Value,
  861. (LONG) newFlags.Value,
  862. (LONG) oldFlags.Value
  863. ) == (LONG) oldFlags.Value)
  864. {
  865. break;
  866. }
  867. PAUSE_PROCESSOR;
  868. }
  869. } // UlpSetConnectionFlag
  870. NTSTATUS
  871. UlpBeginDisconnect(
  872. IN PIRP pIrp,
  873. IN PUL_IRP_CONTEXT pIrpContext,
  874. IN PUL_CONNECTION pConnection,
  875. IN PUL_COMPLETION_ROUTINE pCompletionRoutine,
  876. IN PVOID pCompletionContext
  877. );
  878. NTSTATUS
  879. UlpRestartDisconnect(
  880. IN PDEVICE_OBJECT pDeviceObject,
  881. IN PIRP pIrp,
  882. IN PVOID pContext
  883. );
  884. NTSTATUS
  885. UlpBeginAbort(
  886. IN PUL_CONNECTION pConnection,
  887. IN PUL_COMPLETION_ROUTINE pCompletionRoutine,
  888. IN PVOID pCompletionContext
  889. );
  890. NTSTATUS
  891. UlpRestartAbort(
  892. IN PDEVICE_OBJECT pDeviceObject,
  893. IN PIRP pIrp,
  894. IN PVOID pContext
  895. );
  896. VOID
  897. UlpRemoveFinalReference(
  898. IN PUL_CONNECTION pConnection
  899. );
  900. NTSTATUS
  901. UlpRestartReceive(
  902. IN PDEVICE_OBJECT pDeviceObject,
  903. IN PIRP pIrp,
  904. IN PVOID pContext
  905. );
  906. NTSTATUS
  907. UlpRestartClientReceive(
  908. IN PDEVICE_OBJECT pDeviceObject,
  909. IN PIRP pIrp,
  910. IN PVOID pContext
  911. );
  912. NTSTATUS
  913. UlpDisconnectAllActiveConnections(
  914. IN PUL_ENDPOINT pEndpoint
  915. );
  916. VOID
  917. UlpUnbindConnectionFromEndpoint(
  918. IN PUL_CONNECTION pConnection
  919. );
  920. VOID
  921. UlpSynchronousIoComplete(
  922. IN PVOID pCompletionContext,
  923. IN NTSTATUS Status,
  924. IN ULONG_PTR Information
  925. );
  926. PUL_ENDPOINT
  927. UlpFindEndpointForPort(
  928. IN USHORT Port
  929. );
  930. NTSTATUS
  931. UlpOptimizeForInterruptModeration(
  932. IN PUX_TDI_OBJECT pTdiObject,
  933. IN BOOLEAN Flag
  934. );
  935. NTSTATUS
  936. UlpSetNagling(
  937. IN PUX_TDI_OBJECT pTdiObject,
  938. IN BOOLEAN Flag
  939. );
  940. NTSTATUS
  941. UlpRestartQueryAddress(
  942. IN PDEVICE_OBJECT pDeviceObject,
  943. IN PIRP pIrp,
  944. IN PVOID pContext
  945. );
  946. VOID
  947. UlpCleanupEarlyConnection(
  948. IN PUL_CONNECTION pConnection
  949. );
  950. NTSTATUS
  951. UlpQueryTcpFastSend(
  952. PWSTR DeviceName,
  953. OUT PUL_TCPSEND_DISPATCH* pDispatchRoutine
  954. );
  955. NTSTATUS
  956. UlpBuildTdiReceiveBuffer(
  957. IN PUX_TDI_OBJECT pTdiObject,
  958. IN PUL_CONNECTION pConnection,
  959. OUT PIRP *pIrp
  960. );
  961. BOOLEAN
  962. UlpConnectionIsOnValidList(
  963. IN PUL_CONNECTION pConnection
  964. );
  965. NTSTATUS
  966. UlpPopulateIdleList(
  967. IN OUT PUL_ADDR_IDLE_LIST pAddrIdleList,
  968. IN ULONG Proc
  969. );
  970. VOID
  971. UlpTrimAddrIdleList(
  972. IN OUT PUL_ADDR_IDLE_LIST pAddrIdleList,
  973. OUT PLIST_ENTRY pZombieList
  974. );
  975. VOID
  976. UlpIdleListTrimTimerWorker(
  977. IN PUL_WORK_ITEM pWorkItem
  978. );
  979. VOID
  980. UlpIdleListTrimTimerDpcRoutine(
  981. PKDPC Dpc,
  982. PVOID DeferredContext,
  983. PVOID SystemArgument1,
  984. PVOID SystemArgument2
  985. );
  986. BOOLEAN
  987. UlpIsUrlRouteableInListenScope(
  988. IN PHTTP_PARSED_URL pParsedUrl
  989. );
  990. #if DBG
  991. #define SHOW_LIST_INFO(Caller,Info,List,Proc) \
  992. UlTrace(TDI_STATS, \
  993. ("%s: %s List %p Endp %p Proc %d " \
  994. "Delta %6d Conn Served P/C %5d:%5d PD/BD BLC %d [%5d]:[%5d]\n", \
  995. ##Caller, \
  996. Info, \
  997. List, \
  998. List->pOwningEndpoint, \
  999. Proc, \
  1000. PpslQueryDelta( \
  1001. List->IdleConnectionSListsHandle, \
  1002. Proc \
  1003. ), \
  1004. PpslQueryPrevServed( \
  1005. List->IdleConnectionSListsHandle, \
  1006. Proc \
  1007. ), \
  1008. PpslQueryServed( \
  1009. List->IdleConnectionSListsHandle, \
  1010. Proc \
  1011. ), \
  1012. PpslQueryTotalServed( \
  1013. List->IdleConnectionSListsHandle \
  1014. ), \
  1015. PpslQueryDepth( \
  1016. List->IdleConnectionSListsHandle, \
  1017. Proc \
  1018. ), \
  1019. PpslQueryBackingListDepth( \
  1020. List->IdleConnectionSListsHandle \
  1021. ) \
  1022. ))
  1023. __inline
  1024. VOID
  1025. UlpTraceIdleConnections(
  1026. VOID
  1027. )
  1028. {
  1029. ULONG Proc;
  1030. ULONG Index;
  1031. PLIST_ENTRY pLink;
  1032. PUL_ENDPOINT pEndpoint;
  1033. PUL_ADDR_IDLE_LIST pAddrIdleList;
  1034. for (pLink = g_TdiEndpointListHead.Flink;
  1035. pLink != &g_TdiEndpointListHead;
  1036. pLink = pLink->Flink
  1037. )
  1038. {
  1039. pEndpoint = CONTAINING_RECORD(
  1040. pLink,
  1041. UL_ENDPOINT,
  1042. GlobalEndpointListEntry
  1043. );
  1044. ASSERT(IS_VALID_ENDPOINT(pEndpoint));
  1045. UlTrace(TDI_STATS,("ENDPOINT: %p AFTER TRIM\n",pEndpoint));
  1046. for (Index = 0; Index < pEndpoint->AddrIdleListCount; Index++)
  1047. {
  1048. pAddrIdleList = &pEndpoint->aAddrIdleLists[Index];
  1049. for (Proc = 0; Proc <= g_UlNumberOfProcessors; Proc++)
  1050. {
  1051. UlTrace(TDI_STATS,
  1052. ("\tList %p Proc %d Delta %6d P/C [%5d]/[%5d] BLC %d Depth [%5d]\n",
  1053. pAddrIdleList,
  1054. Proc,
  1055. PpslQueryDelta(
  1056. pAddrIdleList->IdleConnectionSListsHandle,
  1057. Proc
  1058. ),
  1059. PpslQueryPrevServed(
  1060. pAddrIdleList->IdleConnectionSListsHandle,
  1061. Proc
  1062. ),
  1063. PpslQueryServed(
  1064. pAddrIdleList->IdleConnectionSListsHandle,
  1065. Proc
  1066. ),
  1067. PpslQueryTotalServed(
  1068. pAddrIdleList->IdleConnectionSListsHandle
  1069. ),
  1070. PpslQueryDepth(
  1071. pAddrIdleList->IdleConnectionSListsHandle,
  1072. Proc
  1073. )
  1074. ));
  1075. }
  1076. UlTrace(TDI_STATS,("\n"));
  1077. }
  1078. }
  1079. }
  1080. #define TRACE_IDLE_CONNECTIONS() \
  1081. IF_DEBUG(TDI_STATS) \
  1082. { \
  1083. UlpTraceIdleConnections(); \
  1084. }
  1085. __inline
  1086. ULONG
  1087. UlpZombieListDepth(
  1088. IN PLIST_ENTRY pList
  1089. )
  1090. {
  1091. PLIST_ENTRY pLink = pList;
  1092. ULONG Depth = 0;
  1093. while (pLink->Flink != pList)
  1094. {
  1095. Depth++;
  1096. pLink = pLink->Flink;
  1097. }
  1098. return Depth;
  1099. }
  1100. #else
  1101. #define SHOW_LIST_INFO(Caller,Info,List,Proc)
  1102. #define TRACE_IDLE_CONNECTIONS()
  1103. #endif // DBG
  1104. #endif // _ULTDIP_H_