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.

5442 lines
160 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 2001
  3. Module Name:
  4. Http2.hxx
  5. Abstract:
  6. HTTP2 transport-specific constants and types.
  7. Author:
  8. KamenM 08-30-01 Created
  9. Revision History:
  10. --*/
  11. /*
  12. ====== DATA STRUCTURES & BASIC SCENARIOS ======
  13. Client/Server Side General Map:
  14. +------------------------------+
  15. | |
  16. | Runtime Connection |
  17. | |
  18. +------------------------------+
  19. | |
  20. | Transport Connection |
  21. | |
  22. +------------------------------+
  23. |
  24. |
  25. +--------------------------+--------------------------+
  26. \ \ \ \
  27. +---------+ +---------+ +---------+ +---------+
  28. | IN | | IN | | OUT | | OUT |
  29. | Channel | | Channel | | Channel | | Channel |
  30. | Stack 0 | | Stack 1 | | Stack 0 | | Stack 1 |
  31. +---------+ +---------+ +---------+ +---------+
  32. Note that unless channel recycling is in progress, we will have only one
  33. channel of a given type active at a time. That is the data structure will
  34. look like this:
  35. +------------------------------+
  36. | |
  37. | Runtime Connection |
  38. | |
  39. +------------------------------+
  40. | |
  41. | Transport Connection |
  42. | |
  43. +------------------------------+
  44. |
  45. |
  46. +--------------------------+--------------------------+
  47. \ \ \ \
  48. +---------+ = +---------+ =
  49. | IN | | OUT |
  50. | Channel | | Channel |
  51. | Stack 0 | | Stack 0 |
  52. +---------+ +---------+
  53. When we recycle a channel (let's say an IN channel), we will attach the new IN channel
  54. in the empty slot:
  55. +------------------------------+
  56. | |
  57. | Runtime Connection |
  58. | |
  59. +------------------------------+
  60. | |
  61. | Transport Connection |
  62. | |
  63. +------------------------------+
  64. |
  65. |
  66. +--------------------------+--------------------------+
  67. \ \ \ \
  68. +---------+ +---------+ +---------+ =
  69. | IN | | IN | | OUT |
  70. | Channel | | Channel | | Channel |
  71. | Stack 0 | | Stack 1 | | Stack 0 |
  72. +---------+ +---------+ +---------+
  73. When we're done establishing the new channel, we will discard the old channel and the data
  74. structure will look like this:
  75. +------------------------------+
  76. | |
  77. | Runtime Connection |
  78. | |
  79. +------------------------------+
  80. | |
  81. | Transport Connection |
  82. | |
  83. +------------------------------+
  84. |
  85. |
  86. +--------------------------+--------------------------+
  87. \ \ \ \
  88. = +---------+ +---------+ =
  89. | IN | | OUT |
  90. | Channel | | Channel |
  91. | Stack 1 | | Stack 0 |
  92. +---------+ +---------+
  93. The connection between the transport connection (the virtual connection)
  94. and the channel stacks is a "soft" connection (denoted by '\' in the diagram).
  95. Both keep a pointer to each other, but the object on the other end can disappear
  96. in a safe manner. This is done in the following way. Before each party can
  97. dereference the pointer, it must lock it. The lock operation can fail if the
  98. pointer is gone or is going away. The disconnect always originates
  99. from the virtual connection. If the virtual connection decides to disconnect a
  100. channel stack, it calls into the channel (after locking) to tell it it is going
  101. away. This operation will block until all calls from the channel stack up have
  102. completed. New locks from the channel to the virtual connection (called Parent)
  103. will fail. Once all upcalls have been drained, the channel->parent pointer will
  104. be zero'ed out and execution will return to the virtual connection which will
  105. zero out its pointer to the channel.
  106. The Runtime Connection/Virtual Connection pair resides in a single block of memory
  107. and has a single lifetime (refcounted) with the lifetime controlled by the runtime.
  108. Each channel stack has its own lifetime and refcounting. This allows it to go away
  109. earlier or stay behind the virtual connection.
  110. IN/OUT Proxy General Map:
  111. +------------------------------+
  112. | |
  113. | Transport Connection |
  114. | |
  115. +------------------------------+
  116. |
  117. |
  118. +--------------------------+--------------------------+
  119. \ \ \ \
  120. +---------+ +---------+ +---------+ +---------+
  121. | IN | | IN | | OUT | | OUT |
  122. | Channel | | Channel | | Channel | | Channel |
  123. | Stack 0 | | Stack 1 | | Stack 0 | | Stack 1 |
  124. +---------+ +---------+ +---------+ +---------+
  125. The same rules apply as in the Client/Server case.
  126. CHANNEL STACKS:
  127. The top and bottom channel have somewhat special functions. All other channels fit
  128. the same pattern. The stack is modeled similiarly to the NT IO System driver
  129. stack (where a channel corresponds to a driver and the virtual connection and the top
  130. channel map to the IO System). Each channel interacts uniformly with its neighbouring
  131. channels and its top channel. It doesn't care what the neighbouring channels are and
  132. what the top channel is. A single channel type (class) can and does participate in
  133. multiple channel stacks. It can handle a certain number of operations (see the virtual
  134. methods in HTTP2TransportChannel for a list of the operations) though if it doesn't want
  135. to handle a particular operation, it doesn't need to override it and it can just delegate
  136. to the base class (which in most cases sends down). Each operation has a direction. For
  137. example, receives (reads) go down. This means that if a read is issued to the channel
  138. stack, the channel on the top is given a crack at it. If it wants to do something special
  139. during receives, it can do so. If not, it simply delegates to the channel below it (it
  140. doesn't know what channel is below it and it doesn't care). Thus the read operation travels
  141. through the whole stack with each party getting a crack at the operation (very much like
  142. an IRP travelling through the driver stack except that C++ classes are used here).
  143. The basic map of a channel stack is like this:
  144. /////////////////////////////////
  145. / Top Channel /<------+
  146. ///////////////////////////////// |
  147. | /\ |
  148. \/ | |
  149. +-------------------------------+ |
  150. | Channel 1 +-------+
  151. +-------------------------------+ /\
  152. | /\ |
  153. \/ | |
  154. ... |
  155. ... |
  156. ... |
  157. | /\ |
  158. \/ | |
  159. +-------------------------------+ |
  160. | Channel N +-------+
  161. +-------------------------------+ /\
  162. | /\ |
  163. \/ | |
  164. (-------------------------------) |
  165. ( Bottom Channel )-------+
  166. (-------------------------------)
  167. Each channel points to its upper and lower layer (with the exception of top and bottom). Each
  168. channel also points to the top channel while provides special functionality like refcounting
  169. to all other channels. The bottom channel has some special responsibilities in terms of
  170. completing the async requests whose completion was initiated by the IO System.
  171. Client Side IN Channel Stack (top channel denoted by /// box and bottom by (-) box):
  172. //////////////////////////////////
  173. / HTTP2ClientInChannel /
  174. +--------------------------------+
  175. | HTTP2PlugChannel |
  176. +--------------------------------+
  177. | HTTP2FlowControlSender |
  178. +--------------------------------+
  179. | HTTP2PingOriginator |
  180. +--------------------------------+
  181. | HTTP2ChannelDataOriginator |
  182. (--------------------------------)
  183. ( HTTP2WinHttpTransportChannel )
  184. (--------------------------------)
  185. Client Side OUT Channel Stack (same notation):
  186. //////////////////////////////////
  187. / HTTP2ClientOutChannel /
  188. +--------------------------------+
  189. | HTTP2EndpointReceiver |
  190. +--------------------------------+
  191. | HTTP2PingReceiver |
  192. (--------------------------------)
  193. ( HTTP2WinHttpTransportChannel )
  194. (--------------------------------)
  195. In Proxy IN Channel Stack (same notation):
  196. //////////////////////////////////
  197. / HTTP2InProxyInChannel /
  198. +--------------------------------+
  199. | HTTP2ProxyReceiver |
  200. +--------------------------------+
  201. | HTTP2PingReceiver |
  202. (--------------------------------)
  203. ( HTTP2IISTransportChannel )
  204. (--------------------------------)
  205. In Proxy OUT Channel Stack (same notation):
  206. //////////////////////////////////
  207. / HTTP2InProxyOutChannel /
  208. +--------------------------------+
  209. | HTTP2ProxyPlugChannel |
  210. +--------------------------------+
  211. | HTTP2FlowControlSender |
  212. (--------------------------------)
  213. (HTTP2ProxySocketTransportChannel)
  214. (--------------------------------)
  215. | /\
  216. \/ |
  217. +--------------------------------+
  218. | WS_HTTP2_CONNECTION |
  219. +--------------------------------+
  220. Note how the OUT channel points to a simple transport connection. The connection
  221. is not part of the stack semantically (though it does have the same lifetime) but
  222. it does perform a lot of the functions of the stack.
  223. Out Proxy IN Channel Stack (same notation):
  224. //////////////////////////////////
  225. / HTTP2OutProxyInChannel /
  226. +--------------------------------+
  227. | HTTP2ProxyReceiver |
  228. (--------------------------------)
  229. (HTTP2ProxySocketTransportChannel)
  230. (--------------------------------)
  231. | /\
  232. \/ |
  233. +--------------------------------+
  234. | WS_HTTP2_CONNECTION |
  235. +--------------------------------+
  236. Out Proxy OUT Channel Stack (same notation):
  237. //////////////////////////////////
  238. / HTTP2OutProxyOutChannel /
  239. +--------------------------------+
  240. | HTTP2ProxyPlugChannel |
  241. +--------------------------------+
  242. | HTTP2FlowControlSender |
  243. +--------------------------------+
  244. | HTTP2PingOriginator |
  245. +--------------------------------+
  246. | HTTP2PingReceiver |
  247. (--------------------------------)
  248. ( HTTP2IISSenderTransportChannel )
  249. (--------------------------------)
  250. Server IN Channel Stack (same notation):
  251. //////////////////////////////////
  252. / HTTP2ServerInChannel /
  253. +--------------------------------+
  254. | HTTP2EndpointReceiver |
  255. (--------------------------------)
  256. ( HTTP2SocketTransportChannel )
  257. (--------------------------------)
  258. | /\
  259. \/ |
  260. +--------------------------------+
  261. | WS_HTTP2_CONNECTION |
  262. +--------------------------------+
  263. Server OUT Channel Stack (same notation):
  264. //////////////////////////////////
  265. / HTTP2ServerOutChannel /
  266. +--------------------------------+
  267. | HTTP2PlugChannel |
  268. +--------------------------------+
  269. | HTTP2FlowControlSender |
  270. +--------------------------------+
  271. | HTTP2ChannelDataOriginator |
  272. (--------------------------------)
  273. ( HTTP2SocketTransportChannel )
  274. (--------------------------------)
  275. | /\
  276. \/ |
  277. +--------------------------------+
  278. | WS_HTTP2_CONNECTION |
  279. +--------------------------------+
  280. EXAMPLE SCENARIOS:
  281. Client side send (steps numbered next to diagram):
  282. +------------------------------+
  283. | |
  284. | Runtime Connection |<-----------------------------+
  285. | | |
  286. +------------------------------+ |
  287. 1 | /\ |
  288. \/ | |
  289. +------------------------------+ |
  290. | | |
  291. | Transport Connection | |
  292. | | |
  293. +------------------------------+ |
  294. 16 | |
  295. | |
  296. +--------------------------+------------------------------+ |
  297. 2 \ 15 \ \ \ |
  298. ///////////////////////////////// = +---------+ = |
  299. / HTTP2ClientInChannel / | OUT | |
  300. ///////////////////////////////// | Channel | |
  301. 3 | /\ 14 | Stack 0 | |
  302. \/ | +---------+ |
  303. +-------------------------------+ |
  304. | HTTP2PlugChannel + |
  305. +-------------------------------+ |
  306. 4 | /\ 13 |
  307. \/ | |
  308. +-------------------------------+ |
  309. | HTTP2FlowControlSender + |
  310. +-------------------------------+ |
  311. 5 | /\ 12 |
  312. \/ | |
  313. +-------------------------------+ |
  314. | HTTP2PingOriginator + |
  315. +-------------------------------+ |
  316. 6 | /\ 11 |
  317. \/ | |
  318. +-------------------------------+ |
  319. | HTTP2ChannelDataOriginator + |
  320. +-------------------------------+ |
  321. 7 | /\ 10 |
  322. \/ | |
  323. (-------------------------------) |
  324. ( HTTP2WinHttpTransportChannel ) |
  325. (-------------------------------) |
  326. |
  327. 8 9 17 -------------------------------------------+
  328. 1. Runtime calls HTTP_Send (in order to do a send)
  329. 2. Virtual connection locks default out channel, adds a reference and submits
  330. the send to the top channel.
  331. 3. Top channel optionally does some processing and submits to lower layer.
  332. 4. HTTP2PlugChannel optionally does some processing and submits to lower layer.
  333. 5. HTTP2FlowControlSender optionally does some processing and submits to lower layer.
  334. 6. HTTP2PingOriginator optionally does some processing and submits to lower layer.
  335. 7. HTTP2ChannelDataOriginator optionally does some processing and submits to lower layer.
  336. 8. HTTP2WinHttpTransportChannel optionally does some processing, submits to WinHTTP and
  337. returns. The return goes all the way to the runtime.
  338. 9. A send complete will be indicated by WinHTTP on a different thread. Our WinHTTP callback
  339. gets called and it posts a request on an RPC worker thread to process the send complete.
  340. 10. HTTP2WinHttpTransportChannel optionally does some processing and sends to upper layer by
  341. calling SendComplete on it.
  342. 11. HTTP2ChannelDataOriginator optionally does some processing and sends to upper layer by
  343. calling SendComplete on it.
  344. 12. HTTP2PingOriginator optionally does some processing and sends to upper layer by
  345. calling SendComplete on it.
  346. 13. HTTP2FlowControlSender optionally does some processing and sends to upper layer by
  347. calling SendComplete on it.
  348. 14. HTTP2PlugChannel optionally does some processing and sends to upper layer by
  349. calling SendComplete on it.
  350. 15. HTTP2ClientInChannel optionally does some processing and sends to virtual connection by
  351. calling SendComplete on it.
  352. 16. Virtual connection may do some processing on it and returns. The call returns all the way
  353. to the worker thread.
  354. 17. Depending on the return code it returned with, it will either
  355. go to the runtime, or the worker thread will return to the pool. If return code is not
  356. RPC_P_PACKET_CONSUMED, the runtime will be called. Else the thread will return directly to
  357. the pool.
  358. Server Side Connection Establishment (steps numbered next to diagram):
  359. A1. A2.
  360. ////////////////////// /////////////////////////////////////
  361. / HTTP Address / <-------+ / Runtime Connection /
  362. ////////////////////// | /////////////////////////////////////
  363. +---- / WS_HTTP2_INITIAL_CONNECTION /
  364. /////////////////////////////////////
  365. A1. A listen (AcceptEx) on the address completes.
  366. A2. Address object creates a runtime connection and an object of type
  367. WS_HTTP2_INITIAL_CONNECTION. Note that the transport doesn't know whether it
  368. will be talking the new or the old http protocol. Therefore it establishes
  369. the WS_HTTP2_INITIAL_CONNECTION object which will look into the first received
  370. data packet on this connection and then decide what object it will create. If the
  371. first data packet is an old HTTP data packet, it goes into the old protocol. If it is
  372. a new data packet, it proceeds to step B1.
  373. +------------------------------+
  374. | |
  375. | Runtime Connection |
  376. | |
  377. +------------------------------+ B1
  378. | |~/////////////////////////////////////
  379. | Transport Connection |~/ WS_HTTP2_INITIAL_CONNECTION /
  380. | |~/////////////////////////////////////
  381. +------------------------------+ B3 |
  382. | |
  383. | |
  384. +--------------------------+------------------------------+ |
  385. \ \ \ \ |
  386. ///////////////////////////////// = = = |
  387. / HTTP2ServerInChannel / |
  388. +-------------------------------+ |
  389. | HTTP2EndpointReceiver + | B2
  390. (-------------------------------) B4 |
  391. ( HTTP2SocketTransportChannel ) |
  392. (-------------------------------) |
  393. | /\ |
  394. \/ | |
  395. +--------------------------------+ |
  396. | WS_HTTP2_CONNECTION |~---------------------------------------------------+
  397. +--------------------------------+
  398. B1. The WS_HTTP2_INITIAL_CONNECTION receives a packet from the new protocol. Assume it
  399. is D1/A1.
  400. B2. WS_HTTP2_INITIAL_CONNECTION allocates space for the IN channel stack and migrates the
  401. WS_HTTP2_INITIAL_CONNECTION object into its proper location on the stack turning it into
  402. WS_HTTP2_CONNECTION (the tilde (~) stands for morph into - sure enough Booch didn't have a
  403. symbol for this operation :-)). It initializes the rest of the stack.
  404. B3. The place where WS_HTTP2_INITIAL_CONNECTION used to be becomes a virtual connection
  405. (again morphing).
  406. B4. A connection with this cookie is searched for. If none is found, the current
  407. virtual connection is added to the cookie collection.
  408. If one is found, it will look this way:
  409. +------------------------------+
  410. | |
  411. | Runtime Connection |
  412. | |
  413. +------------------------------+
  414. | |
  415. | Transport Connection |
  416. | |
  417. +------------------------------+
  418. |
  419. |
  420. +--------------------------+--------------------------+
  421. \ \ \ \
  422. = = +---------+ =
  423. | OUT |
  424. | Channel |
  425. | Stack 0 |
  426. +---------+
  427. In this case we don't attach the newly created stack to the virtual connection, so the
  428. current virtual connection looks like this:
  429. +------------------------------+
  430. | |
  431. | Runtime Connection |
  432. | |
  433. +------------------------------+
  434. | |
  435. | Transport Connection |
  436. | |
  437. +------------------------------+
  438. |
  439. |
  440. +--------------------------+--------------------------+
  441. \ \ \ \
  442. = = = =
  443. We add the newly created stack to the existing virtual connection so that it now looks like
  444. this:
  445. +------------------------------+
  446. | |
  447. | Runtime Connection |
  448. | |
  449. +------------------------------+
  450. | |
  451. | Transport Connection |
  452. | |
  453. +------------------------------+
  454. |
  455. |
  456. +--------------------------+--------------------------+
  457. \ \ \ \
  458. +---------+ = +---------+ =
  459. | IN | | OUT |
  460. | Channel | | Channel |
  461. | Stack 0 | | Stack 0 |
  462. +---------+ +---------+
  463. Then we return failure so that the old virtual connection is destroyed (we have
  464. effectively attached a leg to the existing virtual connection).
  465. ====== RULES =======
  466. Rule 1: Can't issue upcalls from submission context
  467. Rule 2: _Can_ issue upcalls from upcall context
  468. Rule 3: Can't disconnect channels from upcall context (unless
  469. the calling channel is exempt or we disconnect a different
  470. channel than the one we're making the upcall on)
  471. Rule 4: Channels above EndpointReceiver need not consume failed
  472. receives. If they choose to consume them, they can do
  473. so, but they can always delegate this to EndpointReceiver.
  474. If they delegate and return an error, the connection will
  475. be aborted by the endpoint receiver. This only applies to
  476. received that came in as failures, not to successful receives
  477. converted to failures. In the conversion case, rule 8 needs
  478. to be observed.
  479. Rule 5: Whoever consumes the packet must send the return status
  480. to RPC_P_CONSUME_PACKET, free the packet and possibly do the
  481. abort work in case of failure.
  482. Rule 6: Fatal errors on the proxy abort the whole tomato using
  483. AbortAndDestroy. Fatal errors on the client or server
  484. should only abort the channels or the connection, but
  485. not destroy the connection. The runtime will do that
  486. on client/server.
  487. Rule 7: EndpointReceiver will not consume success RTS receives.
  488. Rule 8: Failed RTS receives do not have a valid buffer. Corollary is that
  489. if channels convert successfull RTS receive to a failure, they must
  490. consume the packet
  491. Rule 9: Channels that initiate operations on lower channels from upcall or
  492. neutral context must use BeginSimpleSubmitAsync to synchronize with aborts.
  493. Channels that are from submission context already have that
  494. synchronization provided.
  495. Rule 10: Receive traffic below the endpoint receiver or in the absence of an endpoint
  496. receiver must be raw only.
  497. Rule 11: Abort on client/server must completely destroy the object without damaging
  498. the data. Abort may be closed multiple times, and subsequent aborts must
  499. be able to figure out the abort was already done (which they do by looking
  500. at the data)
  501. Rule 12: All elements in a proxy can return any error code to an upcall. The bottom
  502. channel will consume it if not consumed already.
  503. Rule 13: All elements in a client or server must be careful to consume the packets
  504. the runtime is not supposed to see.
  505. Rule 14: Upcall contexts and aborts are not synchronized. Corollary - if code in
  506. upcall context wants to submit something, it must call
  507. TopChannel->BeginSimpleSubmitAsync. Exception is when channel is detached
  508. before aborted.
  509. Rule 15: Submission contexts and aborts are sycnhronized.
  510. Rule 16: Failed sends may have a buffer, but it must not be touched. It is owned
  511. by the transport
  512. Rule 17: All lower channels are guaranteed single abort by the top channel.
  513. Rule 18: All channels above HTTP2ChannelDataOriginator must monitor send return codes
  514. and if channel recycling is needed, initiate one. Those in runtime context just pass
  515. the error code to the virtual connection. Those in neutral context get this for free
  516. when they call AsyncCompleteHelper.
  517. Rule 19: Channel detach can happen before Abort.
  518. Rule 20: Unlinked Send Context must be channel agnostic. During channel recycling, we may
  519. start a send on one channel, but then migrate the send to a different channel and
  520. actually complete (including wait for it) on a different channel.
  521. Rule 21: You can't synchronously wait for result in submission context
  522. Rule 22: If a send is migrated b/n channels during recycling, care must be exercised
  523. to complete the send in case of failure, and not just drop it on the floor.
  524. Rule 23: The periodic timer holds one refcount to the channel. It will be removed during Abort
  525. Rule 24: Each ping started holds one refcount (like all async operations)
  526. Rule 25: Timeouts must be set only in upcalls in the proxy. This is because the cancelling
  527. is synchronized with upcalls. Otherwise we have a race. If you decide to change this rule
  528. you must modify HTTP2ProxyVirtualConnection::DisconnectChannels and provide other
  529. synchronization mechanism.
  530. Rule 26: All code that initiates sends on the endpoints must watch for and handle
  531. channel recycling
  532. Rule 27: During HTTP proxy search, the in channel will be direct connection while the out
  533. channel will be through the proxy
  534. Rule 28: If the RPC proxy is a web farm, and clients access it through an HTTP proxy that does
  535. not support keep alive connections, and RPC_C_HTTP_FLAG_USE_FIRST_AUTH_SCHEME is not specified
  536. and at least one machine supports only Basic authentication or anonymous access, then all
  537. machines in the web farm must also support Basic/anonymous respectively.
  538. Rule 29: If anybody calls HandleSendResultFromNeutralContext, all necessary cleanup will be done
  539. inside HandleSendResultFromNeutralContext. Callers can handle error code only if they want.
  540. Rule 30: The last send on the server will be sync from the runtime. There will be exactly one such
  541. send. The transport will complete it immediately for the sake of unblocking the runtime thread
  542. but will keep working on it in the background.
  543. Rule 31: The channels must not touch the send context after the upper layer SendComplete has
  544. completed - it may have been freed.
  545. Rule 32: The Winsock providers will touch the overlapped on the return path of an IO. If the
  546. overlapped may not be around for the return path of an IO submission, Winsock must not be used
  547. for the IO.
  548. Rule 33: If we're in a timer callback, we can't abort the connection from this thread. Abort will
  549. try to cancel the timer and will deadlock. The abort must be offloaded to an RPC worker thread.
  550. Rule 34: On the endpoints, if a receive complete will not return RPC_P_PACKET_CONSUMED, it must
  551. not free the packet - it is owned by runtime in both failure and success case.
  552. Rule 35: All abort paths on the client that can execute during open must check the IgnoreAborts flag
  553. or use an abort method that does.
  554. Rule 36: HTTP_Abort and HTTP_Close may be called on destroyed but unfreed objects. These functions
  555. and all their callees must not use virtual methods (the vtable is gone), or must check for already
  556. destroyed object.
  557. Rule 37: Callers of ClientOpenInternal must abort the connection if IsFromUpcall is true.
  558. ClientOpenInternal will not abort it in this case.
  559. Rule 38: Callers of FreeChannelPointer must make sure that there are no pending operations on the
  560. channel that carry runtime object refcounts. Otherwise, when they complete, their parent pointer
  561. will be set to NULL and they won't be able to free their refcount.
  562. Rule 39: If you are in an upcall on the virtual connection level on an endpoint (client or server)
  563. the only thing that keeps the virtual connection from disappearing from underneath you is
  564. the lock of the channel on the virtual connection. After this lock is gone (i.e. you call
  565. FreeChannelPointer), you must not touch anything on the virtual connection - it may be gone.
  566. Rule 40: HTTP2ChannelPointer::SetChannel() and HTTP2ChannelPointer::LockChannelPointer() can't race.
  567. This also implies that HTTP2ServerVirtualConnection::InitializeServerConnection() that may attach
  568. channels and call SetChannel should be synchronized with the paths that will LockChannelPointer,
  569. such as AbortChannels().
  570. */
  571. #if _MSC_VER >= 1200
  572. #pragma once
  573. #endif
  574. #ifndef __HTTP2_HXX__
  575. #define __HTTP2_HXX__
  576. typedef enum tagHTTPVersion
  577. {
  578. httpvHTTP = 0,
  579. httpvHTTP2
  580. } HTTPVersion;
  581. typedef enum tagHTTP2TrafficType
  582. {
  583. http2ttNone = 0,
  584. http2ttRTS,
  585. http2ttData,
  586. http2ttAny,
  587. http2ttRaw,
  588. http2ttRTSWithSpecialBit, // used on the client only
  589. http2ttDataWithSpecialBit, // to indicate additional conditions
  590. http2ttRawWithSpecialBit
  591. } HTTP2TrafficType;
  592. // the RTS and Data will be used as 'OR' variables as well. Make sure it fits
  593. C_ASSERT((http2ttRTS | http2ttData) == http2ttAny);
  594. const int SendContextFlagPutInFront = 0x01;
  595. const int SendContextFlagSendLast = 0x02;
  596. const int SendContextFlagNonChannelData = 0x04;
  597. const int SendContextFlagAbandonedSend = 0x08;
  598. const int SendContextFlagProxySend = 0x10;
  599. const int SendContextFlagPluggedChannel = 0x20;
  600. extern long ChannelIdCounter;
  601. class HTTP2SendContext : public CO_SEND_CONTEXT
  602. {
  603. public:
  604. #if DBG
  605. HTTP2SendContext (void)
  606. {
  607. ListEntryUsed = FALSE;
  608. }
  609. inline void SetListEntryUsed (
  610. void
  611. )
  612. {
  613. ASSERT(ListEntryUsed == FALSE);
  614. ListEntryUsed = TRUE;
  615. }
  616. inline void SetListEntryUnused (
  617. void
  618. )
  619. {
  620. ListEntryUsed = FALSE;
  621. }
  622. #else
  623. inline void SetListEntryUsed (
  624. void
  625. )
  626. {
  627. }
  628. inline void SetListEntryUnused (
  629. void
  630. )
  631. {
  632. }
  633. #endif
  634. union
  635. {
  636. HANDLE SyncEvent; // sync sends will send this event. The completion
  637. // path will check the event, and if it is set, it
  638. // will fire it instead of propagating the completion
  639. // beyond the channel. Cleared by the consumer of
  640. // the completed operation
  641. void *BufferToFree; // valid for abandoned sends only. Such sends are async
  642. // and will use this memory location to store the
  643. // pointer of the buffer to free once the send is done
  644. } u;
  645. LIST_ENTRY ListEntry; // used to queue packets
  646. HTTP2TrafficType TrafficType; // the type of traffic in this context
  647. #if DBG
  648. BOOL ListEntryUsed; // for debug builds, set to non-zero if this
  649. // packet is already queued. Otherwise zero. This
  650. // field prevents multiple use of the ListEntry
  651. // structure
  652. #endif // DBG
  653. unsigned int Flags; // currently can be SendContextFlagPutInFront
  654. unsigned int UserData; // place for the user to store stuff
  655. };
  656. // a utility class with storage and manipulation routines for
  657. // an HTTP2 RTS cookie
  658. class HTTP2Cookie
  659. {
  660. public:
  661. RPC_STATUS Create (
  662. void
  663. );
  664. BYTE *GetCookie (
  665. void
  666. )
  667. {
  668. return Cookie;
  669. }
  670. void SetCookie (
  671. IN BYTE *NewCookie
  672. )
  673. {
  674. RpcpMemoryCopy(Cookie, NewCookie, sizeof(Cookie));
  675. }
  676. int Compare (
  677. IN HTTP2Cookie *OtherCookie
  678. )
  679. {
  680. return RpcpMemoryCompare(Cookie, OtherCookie->Cookie, sizeof(Cookie));
  681. }
  682. void ZeroOut (
  683. void
  684. )
  685. {
  686. RpcpMemorySet(Cookie, 0, sizeof(Cookie));
  687. }
  688. private:
  689. BYTE Cookie[16];
  690. };
  691. class HTTP2VirtualConnection; // forward
  692. class CookieCollection;
  693. // a server cookie. Besides the capabilities of HTTP2Cookie,
  694. // it can be queued in a cookie collection and can
  695. // point to a virtual connection
  696. class HTTP2ServerCookie : public HTTP2Cookie
  697. {
  698. public:
  699. HTTP2ServerCookie (
  700. void
  701. ) : RefCount(1)
  702. {
  703. RpcpInitializeListHead(&ListEntry);
  704. Connection = NULL;
  705. }
  706. HTTP2ServerCookie (
  707. IN HTTP2ServerCookie &Cookie
  708. ) : RefCount(1)
  709. {
  710. ASSERT(RpcpIsListEmpty(&Cookie.ListEntry));
  711. ASSERT(Cookie.Connection == NULL);
  712. SetCookie(Cookie.GetCookie());
  713. RpcpInitializeListHead(&ListEntry);
  714. Connection = NULL;
  715. }
  716. inline void SetConnection (
  717. IN HTTP2VirtualConnection *NewConnection
  718. )
  719. {
  720. Connection = NewConnection;
  721. }
  722. inline void AddRefCount (
  723. void
  724. )
  725. {
  726. int LocalRefCount = RefCount.Increment();
  727. LogEvent(SU_REFOBJ, EV_INC, this, IntToPtr(0x77), LocalRefCount, 1, 1);
  728. }
  729. inline BOOL RemoveRefCount (
  730. void
  731. )
  732. {
  733. int LocalRefCount;
  734. LogEvent(SU_REFOBJ, EV_DEC, this, IntToPtr(0x77), RefCount.GetInteger(), 1, 1);
  735. LocalRefCount = RefCount.Decrement();
  736. ASSERT(LocalRefCount >= 0);
  737. return (LocalRefCount == 0);
  738. }
  739. friend CookieCollection;
  740. private:
  741. LIST_ENTRY ListEntry;
  742. HTTP2VirtualConnection *Connection;
  743. INTERLOCKED_INTEGER RefCount; // used when we fake web farms on the same machine. In this case
  744. // instead of having each channel register its own connection,
  745. // they use the refcount to coordinate the use of the entry in
  746. // the cookie collection. Adds are synchronzed through the cookie collection
  747. // but remove reference counts are not.
  748. };
  749. // the HTTP2 resolver hint. Essentially, a transport level
  750. // association.
  751. class HTTPResolverHint : public TCPResolverHint
  752. {
  753. public:
  754. HTTPVersion Version; // what version of HTTP did we choose
  755. // for the association
  756. RPCProxyAccessType AccessType; // do we access the server directly?
  757. char *RpcServer; // cache the converted name. If server name
  758. // is less than sizeof(RpcServerName),
  759. // RpcServerName will be used as storage. Otherwise
  760. // a heap block will be allocated.
  761. char RpcServerName[40]; // storage for the converted name
  762. int ServerNameLength; // in bytes without terminating NULL
  763. USHORT ServerPort;
  764. char *RpcProxy; // cache the RpcProxy name.
  765. int ProxyNameLength; // in bytes without terminating NULL
  766. USHORT RpcProxyPort;
  767. char *HTTPProxy; // cache the HTTPProxy name.
  768. USHORT HTTPProxyPort;
  769. HTTP2Cookie AssociationGroupId; // the transport association group id
  770. // helper functions
  771. inline void FreeHTTPProxy (void)
  772. {
  773. if (HTTPProxy)
  774. {
  775. delete HTTPProxy;
  776. HTTPProxy = NULL;
  777. }
  778. }
  779. inline void FreeRpcProxy (void)
  780. {
  781. if (RpcProxy)
  782. {
  783. delete RpcProxy;
  784. RpcProxy = NULL;
  785. }
  786. }
  787. inline void FreeRpcServer (void)
  788. {
  789. if (RpcServer && (RpcServer != RpcServerName))
  790. {
  791. delete RpcServer;
  792. RpcServer = NULL;
  793. }
  794. }
  795. void VerifyInitialized (
  796. void
  797. );
  798. void Initialize (
  799. void
  800. )
  801. {
  802. RpcProxy = NULL;
  803. HTTPProxy = NULL;
  804. RpcServer = NULL;
  805. }
  806. };
  807. class HTTP2Channel; // forward
  808. class HTTP2TransportChannel
  809. {
  810. public:
  811. HTTP2TransportChannel (
  812. void
  813. )
  814. {
  815. TopChannel = NULL;
  816. LowerLayer = NULL;
  817. UpperLayer = NULL;
  818. }
  819. // the destructor of the lower channels will never get called.
  820. // Don't put anything here. Use FreeObject
  821. virtual ~HTTP2TransportChannel (
  822. void
  823. )
  824. {
  825. }
  826. virtual RPC_STATUS Send (
  827. IN OUT HTTP2SendContext *SendContext
  828. );
  829. virtual RPC_STATUS Receive (
  830. IN HTTP2TrafficType TrafficType
  831. );
  832. virtual RPC_STATUS SendComplete (
  833. IN RPC_STATUS EventStatus,
  834. IN OUT HTTP2SendContext *SendContext
  835. );
  836. virtual RPC_STATUS ReceiveComplete (
  837. IN RPC_STATUS EventStatus,
  838. IN HTTP2TrafficType TrafficType,
  839. IN BYTE *Buffer,
  840. IN UINT BufferLength
  841. );
  842. // Abort travels from top to bottom only
  843. virtual void Abort (
  844. IN RPC_STATUS RpcStatus
  845. );
  846. // travels up
  847. virtual void SendCancelled (
  848. IN HTTP2SendContext *SendContext
  849. );
  850. virtual void FreeObject (
  851. void
  852. ) = 0;
  853. // travels down
  854. virtual void Reset (
  855. void
  856. );
  857. void SetLowerChannel (IN HTTP2TransportChannel *LowerChannel)
  858. {
  859. LowerLayer = LowerChannel;
  860. }
  861. void SetUpperChannel (IN HTTP2TransportChannel *UpperChannel)
  862. {
  863. UpperLayer = UpperChannel;
  864. }
  865. void SetTopChannel (IN HTTP2Channel *TopChannel)
  866. {
  867. this->TopChannel = TopChannel;
  868. }
  869. protected:
  870. // descendants may override this (specifically the proxies
  871. // use their own version)
  872. virtual RPC_STATUS AsyncCompleteHelper (
  873. IN RPC_STATUS CurrentStatus
  874. );
  875. RPC_STATUS HandleSendResultFromNeutralContext (
  876. IN RPC_STATUS CurrentStatus
  877. );
  878. HTTP2TransportChannel *LowerLayer;
  879. HTTP2TransportChannel *UpperLayer;
  880. HTTP2Channel *TopChannel;
  881. };
  882. class HTTP2BottomChannel : public HTTP2TransportChannel
  883. {
  884. public:
  885. virtual RPC_STATUS SendComplete (
  886. IN RPC_STATUS EventStatus,
  887. IN OUT HTTP2SendContext *SendContext
  888. );
  889. virtual RPC_STATUS ReceiveComplete (
  890. IN RPC_STATUS EventStatus,
  891. IN HTTP2TrafficType TrafficType,
  892. IN BYTE *Buffer,
  893. IN UINT BufferLength
  894. );
  895. };
  896. class HTTP2SocketTransportChannel : public HTTP2BottomChannel
  897. {
  898. public:
  899. HTTP2SocketTransportChannel (
  900. IN WS_HTTP2_CONNECTION *RawConnection,
  901. OUT RPC_STATUS *Status
  902. )
  903. {
  904. this->RawConnection = RawConnection;
  905. }
  906. virtual RPC_STATUS Send (
  907. IN OUT HTTP2SendContext *SendContext
  908. );
  909. virtual RPC_STATUS Receive (
  910. IN HTTP2TrafficType TrafficType
  911. );
  912. // SendComplete is inheritted
  913. // ReceiveComplete is inheritted
  914. virtual void Abort (
  915. IN RPC_STATUS RpcStatus
  916. );
  917. virtual void FreeObject (
  918. void
  919. );
  920. virtual void Reset (
  921. void
  922. );
  923. private:
  924. WS_HTTP2_CONNECTION *RawConnection;
  925. };
  926. class HTTP2FragmentReceiver : public HTTP2BottomChannel
  927. {
  928. public:
  929. HTTP2FragmentReceiver (
  930. void
  931. )
  932. {
  933. pReadBuffer = NULL;
  934. MaxReadBuffer = 0;
  935. iLastRead = 0;
  936. }
  937. virtual RPC_STATUS Receive (
  938. IN HTTP2TrafficType TrafficType
  939. );
  940. virtual RPC_STATUS ReceiveComplete (
  941. IN RPC_STATUS EventStatus,
  942. IN HTTP2TrafficType TrafficType,
  943. IN OUT BYTE **Buffer,
  944. IN OUT UINT *BufferLength
  945. );
  946. protected:
  947. virtual RPC_STATUS PostReceive (
  948. void
  949. ) = 0;
  950. virtual ULONG GetPostRuntimeEvent (
  951. void
  952. ) = 0;
  953. RPC_STATUS DepositReceivedData (
  954. IN ULONG DataSize,
  955. IN BYTE *Data
  956. );
  957. BYTE *pReadBuffer; // the buffer we have submitted a read on. The read
  958. // is actually submitted at pReadBuffer + iLastRead
  959. ULONG MaxReadBuffer; // the maximum size of pReadBuffer
  960. ULONG iLastRead; // next byte we will read in
  961. ULONG iPostSize; // our normal post size
  962. };
  963. //
  964. // Current state of the HTTP2WinHttpTransportChannel.
  965. //
  966. // The state diagram is as follows:
  967. //
  968. //
  969. // whtcsNew -> whtcsOpeningRequest ->
  970. // whtcsSendingRequest -> whtcsSentRequest -> whtcsReceivingResponse -> whtcsReceivedResponse
  971. // | /\ | /\
  972. // \/ | \/ |
  973. // whtcsWriting whtcsReading
  974. //
  975. typedef enum tagHTTP2WinHttpTransportChannelState
  976. {
  977. whtcsNew = 0,
  978. whtcsOpeningRequest,
  979. whtcsSendingRequest,
  980. whtcsSentRequest,
  981. whtcsReceivingResponse,
  982. whtcsReceivedResponse,
  983. whtcsWriting,
  984. whtcsReading,
  985. whtcsDraining
  986. } HTTP2WinHttpTransportChannelState;
  987. class HTTP2WinHttpTransportChannel : public HTTP2FragmentReceiver
  988. {
  989. public:
  990. friend void CALLBACK WinHttpCallback (
  991. IN HINTERNET hInternet,
  992. IN DWORD_PTR dwContext,
  993. IN DWORD dwInternetStatus,
  994. IN LPVOID lpvStatusInformation OPTIONAL,
  995. IN DWORD dwStatusInformationLength
  996. );
  997. HTTP2WinHttpTransportChannel (
  998. OUT RPC_STATUS *RpcStatus
  999. );
  1000. RPC_STATUS HTTP2WinHttpTransportChannel::Open (
  1001. IN HTTPResolverHint *Hint,
  1002. IN const RPC_CHAR *Verb,
  1003. IN const RPC_CHAR *Url,
  1004. IN const RPC_CHAR *AcceptType,
  1005. IN ULONG ContentLength,
  1006. IN ULONG CallTimeout,
  1007. IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials,
  1008. IN ULONG ChosenAuthScheme,
  1009. IN const BYTE *AdditionalData OPTIONAL
  1010. );
  1011. virtual RPC_STATUS Send (
  1012. IN OUT HTTP2SendContext *SendContext
  1013. );
  1014. virtual RPC_STATUS Receive (
  1015. IN HTTP2TrafficType TrafficType
  1016. );
  1017. virtual RPC_STATUS SendComplete (
  1018. IN RPC_STATUS EventStatus,
  1019. IN OUT HTTP2SendContext *SendContext
  1020. );
  1021. virtual void Abort (
  1022. IN RPC_STATUS RpcStatus
  1023. );
  1024. virtual void FreeObject (
  1025. void
  1026. );
  1027. RPC_STATUS DirectReceiveComplete (
  1028. OUT BYTE **ReceivedBuffer,
  1029. OUT ULONG *ReceivedBufferLength,
  1030. OUT void **RuntimeConnection
  1031. );
  1032. RPC_STATUS DirectSendComplete (
  1033. OUT BYTE **SentBuffer,
  1034. OUT void **SendContext
  1035. );
  1036. void DelayedReceive (
  1037. void
  1038. );
  1039. void VerifyServerCredentials (
  1040. void
  1041. );
  1042. inline ULONG GetChosenAuthScheme (
  1043. void
  1044. )
  1045. {
  1046. return ChosenAuthScheme;
  1047. }
  1048. inline BOOL IsKeepAlive (
  1049. void
  1050. )
  1051. {
  1052. return KeepAlive;
  1053. }
  1054. private:
  1055. virtual RPC_STATUS PostReceive (
  1056. void
  1057. );
  1058. virtual ULONG GetPostRuntimeEvent (
  1059. void
  1060. );
  1061. ULONG NegotiateAuthScheme (
  1062. void
  1063. );
  1064. void ContinueDrainChannel (
  1065. void
  1066. );
  1067. void TryClosingWinHttpHandle (
  1068. IN OUT HINTERNET *pHandle
  1069. );
  1070. HINTERNET hSession;
  1071. HINTERNET hConnect;
  1072. HINTERNET hRequest;
  1073. ULONG NumberOfBytesTransferred;
  1074. RPC_STATUS AsyncError;
  1075. MUTEX Mutex;
  1076. LIST_ENTRY BufferQueueHead;
  1077. long PreviousRequestContentLength;
  1078. // Used to wait for state transitions. This is actually the thread
  1079. // event borrowed.
  1080. HANDLE SyncEvent; // valid during waits
  1081. HTTP2TrafficType DelayedReceiveTrafficType; // valid during b/n delayed
  1082. // receive and its consumption
  1083. // Current state of the transport
  1084. HTTP2WinHttpTransportChannelState State;
  1085. HTTP2SendContext *CurrentSendContext; // the context we are currently
  1086. // sending. Set before we submit a write, and picked
  1087. // on write completion.
  1088. long SendsPending;
  1089. RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials; // the transport
  1090. // credentials as kept by the runtime. These are the
  1091. // encrypted version.
  1092. ULONG ChosenAuthScheme; // valid after RPC_P_AUTH_NEEDED failure
  1093. ULONG CredentialsSetForScheme; // the scheme for which credentials have
  1094. // already been set
  1095. BOOL KeepAlive; // TRUE if the WinHttp connection is keep alive
  1096. };
  1097. class HTTP2ProxySocketTransportChannel : public HTTP2SocketTransportChannel
  1098. {
  1099. public:
  1100. HTTP2ProxySocketTransportChannel (
  1101. IN WS_HTTP2_CONNECTION *RawConnection,
  1102. OUT RPC_STATUS *Status
  1103. ) : HTTP2SocketTransportChannel(RawConnection, Status)
  1104. {
  1105. }
  1106. virtual RPC_STATUS AsyncCompleteHelper (
  1107. IN RPC_STATUS CurrentStatus
  1108. );
  1109. };
  1110. typedef enum tagIISTransportChannelDirection
  1111. {
  1112. iistcdSend = 0,
  1113. iistcdReceive
  1114. } IISTransportChannelDirection;
  1115. // cannot have pending reads at the same time as pending writes
  1116. // Class must enforce that. Also, it must accept multiple
  1117. // sends at a time, but does one send in reality - all others
  1118. // are buffered pending completion of the first one. It has to
  1119. // provide defragmentation services for upper channels
  1120. class HTTP2IISTransportChannel : public HTTP2FragmentReceiver
  1121. {
  1122. public:
  1123. HTTP2IISTransportChannel (
  1124. IN void *ConnectionParameter
  1125. )
  1126. {
  1127. ControlBlock = (EXTENSION_CONTROL_BLOCK *)ConnectionParameter;
  1128. Direction = iistcdReceive; // all IIS channels start in receive mode
  1129. IISIoFlags = HSE_IO_ASYNC;
  1130. CurrentSendContext = NULL;
  1131. iPostSize = gPostSize;
  1132. ReadsPending = 0;
  1133. IISCloseEnabled = FALSE;
  1134. ECBDataConsumed = FALSE;
  1135. }
  1136. virtual RPC_STATUS Receive (
  1137. IN HTTP2TrafficType TrafficType
  1138. );
  1139. virtual RPC_STATUS ReceiveComplete (
  1140. IN RPC_STATUS EventStatus,
  1141. IN HTTP2TrafficType TrafficType,
  1142. IN BYTE *Buffer,
  1143. IN UINT BufferLength
  1144. );
  1145. virtual void Abort (
  1146. IN RPC_STATUS RpcStatus
  1147. );
  1148. virtual void FreeObject (
  1149. void
  1150. );
  1151. void IOCompleted (
  1152. IN ULONG Bytes,
  1153. DWORD Error
  1154. );
  1155. void DirectReceive (
  1156. void
  1157. );
  1158. inline void EnableIISSessionClose (
  1159. void
  1160. )
  1161. {
  1162. ASSERT(IISCloseEnabled == FALSE);
  1163. IISCloseEnabled = TRUE;
  1164. }
  1165. RPC_STATUS PostedEventStatus; // valid only on pick up from posts
  1166. protected:
  1167. virtual RPC_STATUS ReceiveCompleteInternal (
  1168. IN RPC_STATUS EventStatus,
  1169. IN HTTP2TrafficType TrafficType,
  1170. IN BOOL ReadCompleted,
  1171. IN OUT BYTE **Buffer,
  1172. IN OUT UINT *BufferLength
  1173. );
  1174. inline void ReverseDirection (
  1175. void
  1176. )
  1177. {
  1178. // direction can be reverted only once
  1179. ASSERT(Direction == iistcdReceive);
  1180. Direction = iistcdSend;
  1181. }
  1182. void FreeIISControlBlock (
  1183. void
  1184. );
  1185. virtual RPC_STATUS AsyncCompleteHelper (
  1186. IN RPC_STATUS CurrentStatus
  1187. );
  1188. virtual RPC_STATUS PostReceive (
  1189. void
  1190. );
  1191. virtual ULONG GetPostRuntimeEvent (
  1192. void
  1193. );
  1194. // the direction in which the channel is flowing
  1195. IISTransportChannelDirection Direction;
  1196. EXTENSION_CONTROL_BLOCK *ControlBlock;
  1197. ULONG BytesToTransfer; // valid only for the duration of a submission
  1198. // We never really use it, but we have to give
  1199. // some storage to IIS
  1200. DWORD IISIoFlags; // same thing here. Flags that we pass to IIS. They
  1201. // are always the same, but we have to have some
  1202. // storage to give to IIS.
  1203. HTTP2SendContext *CurrentSendContext; // the context we are currently
  1204. // sending. Set before we submit a write, and picked
  1205. // on write completion.
  1206. int ReadsPending; // the number of reads pending on the channel.
  1207. // Can be either 0 or 1. Not consumed in this class
  1208. // but derived classes make use of it to synchronize
  1209. // reads and writes
  1210. BOOL IISCloseEnabled; // if this flag is set to non-zero, IIS Close must be
  1211. // called on free object. Otherwise, IIS Close must
  1212. // not be called on free object. It starts as FALSE,
  1213. // and eventually becomes non-zero when we know
  1214. // we will not be returning a synchronous error to IIS.
  1215. // It never goes back to FALSE.
  1216. BOOL ECBDataConsumed; // if this flag is non-zero, the received data
  1217. // embedded in the ECB block have been consumed. If
  1218. // it is zero, receive must consume any data embedded
  1219. // in the ECB block
  1220. };
  1221. class HTTP2IISSenderTransportChannel : public HTTP2IISTransportChannel
  1222. {
  1223. public:
  1224. HTTP2IISSenderTransportChannel (
  1225. IN void *ConnectionParameter,
  1226. OUT RPC_STATUS *RpcStatus
  1227. ) : HTTP2IISTransportChannel(ConnectionParameter),
  1228. Mutex(RpcStatus,
  1229. FALSE, // pre-allocate semaphore
  1230. 5000 // spin count
  1231. ), SendsPending(0)
  1232. {
  1233. RpcpInitializeListHead(&BufferQueueHead);
  1234. }
  1235. virtual RPC_STATUS Send (
  1236. IN OUT HTTP2SendContext *SendContext
  1237. );
  1238. virtual RPC_STATUS SendComplete (
  1239. IN RPC_STATUS EventStatus,
  1240. IN OUT HTTP2SendContext *SendContext
  1241. );
  1242. virtual void Abort (
  1243. IN RPC_STATUS RpcStatus
  1244. );
  1245. virtual void FreeObject (
  1246. void
  1247. );
  1248. protected:
  1249. virtual RPC_STATUS ReceiveCompleteInternal (
  1250. IN RPC_STATUS EventStatus,
  1251. IN HTTP2TrafficType TrafficType,
  1252. IN BOOL ReadCompleted,
  1253. IN OUT BYTE **Buffer,
  1254. IN OUT UINT *BufferLength
  1255. );
  1256. private:
  1257. RPC_STATUS SendQueuedContextIfNecessary (
  1258. IN ULONG LocalSendsPending,
  1259. IN RPC_STATUS EventStatus
  1260. );
  1261. LIST_ENTRY BufferQueueHead;
  1262. INTERLOCKED_INTEGER SendsPending;
  1263. MUTEX Mutex;
  1264. };
  1265. // base class for the Endpoint receiver (used at endpoints)
  1266. // and the proxy receiver - used at both proxies
  1267. class HTTP2GenericReceiver : public HTTP2TransportChannel
  1268. {
  1269. public:
  1270. HTTP2GenericReceiver (
  1271. IN ULONG ReceiveWindowSize,
  1272. IN BOOL IsServer,
  1273. OUT RPC_STATUS *Status
  1274. ) : Mutex(Status)
  1275. {
  1276. this->IsServer = IsServer;
  1277. DirectCompletePosted = FALSE;
  1278. DirectReceiveInProgress = FALSE;
  1279. ReceiveWindow = ReceiveWindowSize;
  1280. BytesInWindow = 0;
  1281. BytesReceived = 0;
  1282. FreeWindowAdvertised = ReceiveWindowSize;
  1283. }
  1284. // inherit send from base class
  1285. // inherit receive from base class
  1286. // inherit send complete from base class
  1287. virtual RPC_STATUS ReceiveComplete (
  1288. IN RPC_STATUS EventStatus,
  1289. IN HTTP2TrafficType TrafficType,
  1290. IN BYTE *Buffer,
  1291. IN UINT BufferLength
  1292. ) = 0;
  1293. virtual void FreeObject (
  1294. void
  1295. );
  1296. void TransferStateToNewReceiver (
  1297. OUT HTTP2GenericReceiver *NewReceiver
  1298. );
  1299. RPC_STATUS BytesReceivedNotification (
  1300. IN ULONG Bytes
  1301. );
  1302. void BytesConsumedNotification (
  1303. IN ULONG Bytes,
  1304. IN BOOL OwnsMutex,
  1305. OUT BOOL *IssueAck,
  1306. OUT ULONG *BytesReceivedForAck,
  1307. OUT ULONG *WindowForAck
  1308. );
  1309. protected:
  1310. RPC_STATUS SendFlowControlAck (
  1311. IN ULONG BytesReceivedForAck,
  1312. IN ULONG WindowForAck
  1313. );
  1314. // for endpoint receivers, contains
  1315. // only the type of packets not requested. The buffers in the queue are "not wanted" -
  1316. // nobody asked for them. They arrived when we were waiting for something else. As such
  1317. // they do not carry any reference counts and do not need to be propagated to anybody.
  1318. // If we abort (or about to abort) the connection, we can just drop them on the floor.
  1319. // N.B. Packets with first bit set are transfers from an old channel and should
  1320. // not be accounted for in flow control
  1321. QUEUE BufferQueue;
  1322. MUTEX Mutex;
  1323. // a flag that indicates whether a direct receive has been posted. Only
  1324. // one direct receive can be posted as a time.
  1325. BOOL DirectCompletePosted;
  1326. BOOL DirectReceiveInProgress;
  1327. ULONG BytesInWindow;
  1328. ULONG ReceiveWindow;
  1329. ULONG BytesReceived; // counter of total data bytes received. Wraps
  1330. LONG FreeWindowAdvertised; // the size of the free window as advertised. This
  1331. // may differ from the actual because we do not advertise
  1332. // on every change
  1333. BOOL IsServer;
  1334. };
  1335. // provides complex receive at the endpoints - client and server.
  1336. // It has two main responsibilities:
  1337. // 1. It receives two receives - RTS and Data. It must translate
  1338. // them into 1 raw receive
  1339. // 2. It manages flow control between a producer - the transport
  1340. // and the cosumer - the runtime
  1341. class HTTP2EndpointReceiver : public HTTP2GenericReceiver
  1342. {
  1343. public:
  1344. HTTP2EndpointReceiver (
  1345. IN ULONG ReceiveWindowSize,
  1346. IN BOOL IsServer,
  1347. OUT RPC_STATUS *Status
  1348. ) : HTTP2GenericReceiver(ReceiveWindowSize,
  1349. IsServer,
  1350. Status)
  1351. {
  1352. ReceivesPosted = http2ttNone;
  1353. ReceivesQueued = http2ttNone;
  1354. }
  1355. // HTTP2EndpointReceiver inherits send from HTTP2TransportChannel
  1356. virtual RPC_STATUS Receive (
  1357. IN HTTP2TrafficType TrafficType
  1358. );
  1359. virtual RPC_STATUS ReceiveComplete (
  1360. IN RPC_STATUS EventStatus,
  1361. IN HTTP2TrafficType TrafficType,
  1362. IN BYTE *Buffer,
  1363. IN UINT BufferLength
  1364. );
  1365. virtual void Abort (
  1366. IN RPC_STATUS RpcStatus
  1367. );
  1368. virtual void FreeObject (
  1369. void
  1370. );
  1371. virtual RPC_STATUS DirectReceiveComplete (
  1372. OUT BYTE **ReceivedBuffer,
  1373. OUT ULONG *ReceivedBufferLength,
  1374. OUT void **RuntimeConnection,
  1375. OUT BOOL *IsServer
  1376. );
  1377. inline BOOL IsDataReceivePosted (
  1378. void
  1379. )
  1380. {
  1381. return (ReceivesPosted & http2ttData);
  1382. }
  1383. RPC_STATUS TransferStateToNewReceiver (
  1384. OUT HTTP2EndpointReceiver *NewReceiver
  1385. );
  1386. inline void BlockDataReceives (
  1387. void
  1388. )
  1389. {
  1390. Mutex.Request();
  1391. }
  1392. inline void UnblockDataReceives (
  1393. void
  1394. )
  1395. {
  1396. Mutex.Clear();
  1397. }
  1398. protected:
  1399. // map of posted receives. Can be any combination of http2ttRTS and http2ttData
  1400. // (including http2ttNone and http2ttAny). If a receive is posted, new receive
  1401. // request should be reflected on the map, but not really posted
  1402. HTTP2TrafficType ReceivesPosted;
  1403. // the type of receives in the queue. Can be http2ttRTS or http2ttData. If we
  1404. // have queued packets of a given type, this type cannot be in the map.
  1405. // Must be http2ttNone if we do not have any receives in the queue.
  1406. HTTP2TrafficType ReceivesQueued;
  1407. };
  1408. // Responsibility of this class is flow control between receiving leg
  1409. // of the proxy and sending leg of the proxies
  1410. class HTTP2ProxyReceiver : public HTTP2GenericReceiver
  1411. {
  1412. public:
  1413. HTTP2ProxyReceiver (
  1414. IN ULONG ReceiveWindowSize,
  1415. OUT RPC_STATUS *Status
  1416. ) : HTTP2GenericReceiver(ReceiveWindowSize,
  1417. FALSE, // IsServer - for proxies it actually doesn't matter
  1418. Status
  1419. )
  1420. {
  1421. }
  1422. // HTTP2ProxyReceiver inherits send from HTTP2GenericReceiver
  1423. // HTTP2ProxyReceiver inherits receive from HTTP2GenericReceiver
  1424. virtual RPC_STATUS ReceiveComplete (
  1425. IN RPC_STATUS EventStatus,
  1426. IN HTTP2TrafficType TrafficType,
  1427. IN BYTE *Buffer,
  1428. IN UINT BufferLength
  1429. );
  1430. virtual void Abort (
  1431. IN RPC_STATUS RpcStatus
  1432. );
  1433. virtual void FreeObject (
  1434. void
  1435. );
  1436. };
  1437. // N.B. Only transitions from unplugged to one of the plugged states are
  1438. // allowed after data were sent. Transitions b/n plugged states are not allowed
  1439. // The enum members are ordered in strict correspondence to the HTTP2TrafficType
  1440. // enum. This allows to determine whether a traffic goes through with single
  1441. // comparison
  1442. typedef enum tagHTTP2PlugLevels
  1443. {
  1444. http2plInvalid,
  1445. http2plRTSPlugged, // plugged for data and RTS, unplugged for raw
  1446. http2plDataPlugged, // plugged for data, unplugged for RTS and raw
  1447. http2plUnplugged // unplugged
  1448. } HTTP2PlugLevels;
  1449. // a channel that can be plugged/unplugged. When plugged,
  1450. // it doesn't send anything - it just queues packets. When
  1451. // unplugged, it shoots the whole queue down and then
  1452. // starts transmitting packets normally
  1453. class HTTP2PlugChannel : public HTTP2TransportChannel
  1454. {
  1455. public:
  1456. HTTP2PlugChannel (
  1457. OUT RPC_STATUS *Status
  1458. ) : Mutex(Status,
  1459. FALSE, // pre-allocate semaphore
  1460. 5000 // spin count
  1461. )
  1462. {
  1463. RpcpInitializeListHead(&BufferQueueHead);
  1464. PlugLevel = http2plDataPlugged;
  1465. #if DBG
  1466. TrafficSentOnChannel = FALSE;
  1467. #endif // DBG
  1468. SendFailedStatus = RPC_S_INTERNAL_ERROR;
  1469. }
  1470. virtual RPC_STATUS Send (
  1471. IN OUT HTTP2SendContext *SendContext
  1472. );
  1473. virtual void Abort (
  1474. IN RPC_STATUS RpcStatus
  1475. );
  1476. virtual void FreeObject (
  1477. void
  1478. );
  1479. virtual void Reset (
  1480. void
  1481. );
  1482. void InsertHeadBuffer (
  1483. HTTP2SendContext *SendContext
  1484. );
  1485. RPC_STATUS DirectSendComplete (
  1486. void
  1487. );
  1488. RPC_STATUS Unplug (
  1489. void
  1490. );
  1491. void SetStrongPlug (
  1492. void
  1493. );
  1494. protected:
  1495. HTTP2PlugLevels PlugLevel;
  1496. LIST_ENTRY BufferQueueHead;
  1497. MUTEX Mutex;
  1498. RPC_STATUS SendFailedStatus;
  1499. #if DBG
  1500. BOOL TrafficSentOnChannel;
  1501. #endif // DBG
  1502. };
  1503. class HTTP2ProxyPlugChannel : public HTTP2PlugChannel
  1504. {
  1505. public:
  1506. HTTP2ProxyPlugChannel (
  1507. OUT RPC_STATUS *Status
  1508. ) : HTTP2PlugChannel(Status)
  1509. {
  1510. }
  1511. protected:
  1512. virtual RPC_STATUS AsyncCompleteHelper (
  1513. IN RPC_STATUS CurrentStatus
  1514. );
  1515. };
  1516. class HTTP2FlowControlSender : public HTTP2TransportChannel
  1517. {
  1518. public:
  1519. HTTP2FlowControlSender (
  1520. IN BOOLEAN IsServer,
  1521. IN BOOLEAN SendToRuntime,
  1522. OUT RPC_STATUS *Status
  1523. ) : Mutex(Status),
  1524. SendsPending(0)
  1525. {
  1526. SendContextOnDrain = NULL;
  1527. PeerReceiveWindow = 0;
  1528. RpcpInitializeListHead(&BufferQueueHead);
  1529. DataBytesSent = 0;
  1530. PeerAvailableWindow = 0;
  1531. this->IsServer = IsServer;
  1532. this->SendToRuntime = SendToRuntime;
  1533. AbortStatus = RPC_S_OK;
  1534. }
  1535. virtual RPC_STATUS Send (
  1536. IN OUT HTTP2SendContext *SendContext
  1537. );
  1538. // Receive is inheritted from HTTP2TransportChannel
  1539. virtual RPC_STATUS SendComplete (
  1540. IN RPC_STATUS EventStatus,
  1541. IN OUT HTTP2SendContext *SendContext
  1542. );
  1543. // ReceiveComplete is inherrited
  1544. virtual void Abort (
  1545. IN RPC_STATUS RpcStatus
  1546. );
  1547. inline void SetPeerReceiveWindow (
  1548. IN ULONG PeerReceiveWindow
  1549. )
  1550. {
  1551. // the peer receive window can be set
  1552. // only once. We don't support
  1553. // dynamic resizing
  1554. ASSERT(this->PeerReceiveWindow == 0);
  1555. this->PeerReceiveWindow = PeerReceiveWindow;
  1556. PeerAvailableWindow = PeerReceiveWindow;
  1557. }
  1558. inline ULONG GetPeerReceiveWindow (
  1559. void
  1560. )
  1561. {
  1562. return PeerReceiveWindow;
  1563. }
  1564. virtual void FreeObject (
  1565. void
  1566. );
  1567. virtual void SendCancelled (
  1568. IN HTTP2SendContext *SendContext
  1569. );
  1570. RPC_STATUS FlowControlAckNotify (
  1571. IN ULONG BytesReceivedForAck,
  1572. IN ULONG WindowForAck
  1573. );
  1574. void GetBufferQueue (
  1575. OUT LIST_ENTRY *NewQueueHead
  1576. );
  1577. RPC_STATUS DirectSendComplete (
  1578. OUT BOOL *IsServer,
  1579. OUT BOOL *SendToRuntime,
  1580. OUT void **SendContext,
  1581. OUT BUFFER *Buffer,
  1582. OUT UINT *BufferLength
  1583. );
  1584. private:
  1585. RPC_STATUS SendInternal (
  1586. IN OUT HTTP2SendContext *SendContext,
  1587. IN BOOL IgnoreQueuedBuffers
  1588. );
  1589. LIST_ENTRY BufferQueueHead;
  1590. MUTEX Mutex;
  1591. ULONG DataBytesSent;
  1592. ULONG PeerAvailableWindow;
  1593. ULONG PeerReceiveWindow;
  1594. HTTP2SendContext *SendContextOnDrain; // if armed, last send complete or arming
  1595. // function if no sends pending will send this packet
  1596. INTERLOCKED_INTEGER SendsPending;
  1597. RPC_STATUS AbortStatus;
  1598. BOOLEAN IsServer;
  1599. BOOLEAN SendToRuntime;
  1600. };
  1601. class HTTP2ChannelDataOriginator : public HTTP2TransportChannel
  1602. {
  1603. public:
  1604. HTTP2ChannelDataOriginator (
  1605. IN ULONG ChannelLifetime,
  1606. IN BOOL IsServer,
  1607. OUT RPC_STATUS *Status
  1608. );
  1609. virtual RPC_STATUS Send (
  1610. IN OUT HTTP2SendContext *SendContext
  1611. );
  1612. // HTTP2ChannelDataOriginator inherits receive from HTTP2TransportChannel
  1613. // SendComplete is inheritted
  1614. // ReceiveComplete is inheritted
  1615. virtual void Abort (
  1616. IN RPC_STATUS RpcStatus
  1617. );
  1618. virtual void FreeObject (
  1619. void
  1620. );
  1621. virtual void Reset (
  1622. void
  1623. );
  1624. void GetBufferQueue (
  1625. OUT LIST_ENTRY *NewQueueHead
  1626. );
  1627. RPC_STATUS DirectSendComplete (
  1628. OUT BOOL *IsServer,
  1629. OUT void **SendContext,
  1630. OUT BUFFER *Buffer,
  1631. OUT UINT *BufferLength
  1632. );
  1633. inline void PlugChannel (
  1634. void
  1635. )
  1636. {
  1637. // fake true channel exhaustion to force the channel
  1638. // to queue things instead of sending
  1639. if (BytesSentOnChannel < NonreservedLifetime)
  1640. BytesSentOnChannel = NonreservedLifetime + 1;
  1641. }
  1642. RPC_STATUS RestartChannel (
  1643. void
  1644. );
  1645. RPC_STATUS NotifyTrafficSent (
  1646. IN ULONG TrafficSentSize
  1647. );
  1648. protected:
  1649. #if DBG
  1650. inline void RawDataBeingSent (
  1651. void
  1652. )
  1653. {
  1654. ASSERT(RawDataAlreadySent == FALSE);
  1655. RawDataAlreadySent = TRUE;
  1656. }
  1657. #else // DBG
  1658. inline void RawDataBeingSent (
  1659. void
  1660. )
  1661. {
  1662. }
  1663. #endif // DBG
  1664. private:
  1665. ULONG BytesSentOnChannel;
  1666. ULONG ChannelLifetime;
  1667. ULONG NonreservedLifetime;
  1668. LIST_ENTRY BufferQueueHead;
  1669. MUTEX Mutex;
  1670. BOOL ChannelReplacementTriggered;
  1671. BOOL IsServer;
  1672. RPC_STATUS AbortStatus; // valid only between abort and direct send completes
  1673. #if DBG
  1674. BOOL RawDataAlreadySent;
  1675. #endif // DBG
  1676. };
  1677. typedef enum tagHTTP2ReceiveType
  1678. {
  1679. http2rtNone = 0,
  1680. http2rtRTS,
  1681. http2rtData,
  1682. http2rtAny
  1683. } HTTP2ReceiveType;
  1684. class HTTP2ReceiveContext
  1685. {
  1686. HTTP2ReceiveType ReceiveType;
  1687. BYTE *Buffer;
  1688. ULONG BufferLength;
  1689. LIST_ENTRY ListEntry;
  1690. };
  1691. const ULONG ThresholdConsecutivePingsOnInterval = 10; // after 10 pings we'll start scaling back
  1692. const ULONG PingScaleBackInterval = 30 * 1000; // 30 seconds in milliseconds
  1693. class HTTP2PingOriginator : public HTTP2TransportChannel
  1694. {
  1695. public:
  1696. HTTP2PingOriginator (
  1697. IN BOOL NotifyTopChannelForPings
  1698. )
  1699. {
  1700. LastPacketSentTimestamp = 0;
  1701. PingInterval = 0;
  1702. PingTimer = NULL;
  1703. KeepAliveInterval = 0;
  1704. ConnectionTimeout = 0;
  1705. this->NotifyTopChannelForPings = NotifyTopChannelForPings;
  1706. }
  1707. virtual RPC_STATUS Send (
  1708. IN OUT HTTP2SendContext *SendContext
  1709. );
  1710. // HTTP2PingOriginator inherits receive from HTTP2TransportChannel
  1711. virtual RPC_STATUS SendComplete (
  1712. IN RPC_STATUS EventStatus,
  1713. IN OUT HTTP2SendContext *SendContext
  1714. );
  1715. // ReceiveComplete is inheritted
  1716. virtual void Abort (
  1717. IN RPC_STATUS RpcStatus
  1718. );
  1719. RPC_STATUS SetKeepAliveTimeout (
  1720. IN BOOL TurnOn,
  1721. IN BOOL bProtectIO,
  1722. IN KEEPALIVE_TIMEOUT_UNITS Units,
  1723. IN OUT KEEPALIVE_TIMEOUT KATime,
  1724. IN ULONG KAInterval = 5000 OPTIONAL
  1725. );
  1726. virtual void FreeObject (
  1727. void
  1728. );
  1729. // travels up
  1730. virtual void SendCancelled (
  1731. IN HTTP2SendContext *SendContext
  1732. );
  1733. virtual void Reset (
  1734. void
  1735. );
  1736. RPC_STATUS SetConnectionTimeout (
  1737. IN ULONG ConnectionTimeout
  1738. );
  1739. void DisablePings (
  1740. void
  1741. );
  1742. void TimerCallback (
  1743. void
  1744. );
  1745. RPC_STATUS ReferenceFromCallback (
  1746. void
  1747. );
  1748. inline ULONG GetGracePeriod (
  1749. void
  1750. )
  1751. {
  1752. // currently the policy is that the grace period is 1/2
  1753. // of the ping interval
  1754. return (PingInterval >> 1);
  1755. }
  1756. inline ULONG GetPingIntervalFromConnectionTimeout (
  1757. IN ULONG ConnectionTimeout
  1758. )
  1759. {
  1760. return (ConnectionTimeout >> 1);
  1761. }
  1762. inline ULONG GetPingInterval (
  1763. IN ULONG ConnectionTimeout,
  1764. IN ULONG KeepAliveInterval
  1765. )
  1766. {
  1767. ULONG ConnectionTimeoutPing;
  1768. ULONG ActualPingInterval;
  1769. ConnectionTimeoutPing = GetPingIntervalFromConnectionTimeout(ConnectionTimeout);
  1770. ASSERT(ConnectionTimeoutPing || KeepAliveInterval);
  1771. if (KeepAliveInterval)
  1772. {
  1773. if (ConnectionTimeoutPing)
  1774. ActualPingInterval = min(ConnectionTimeoutPing, KeepAliveInterval);
  1775. else
  1776. ActualPingInterval = KeepAliveInterval;
  1777. }
  1778. else
  1779. ActualPingInterval = ConnectionTimeoutPing;
  1780. return ActualPingInterval;
  1781. }
  1782. inline ULONG ScaleBackPingInterval (
  1783. void
  1784. )
  1785. {
  1786. ULONG LocalPingInterval;
  1787. LocalPingInterval = PingInterval + PingScaleBackInterval;
  1788. if (LocalPingInterval > GetPingIntervalFromConnectionTimeout(ConnectionTimeout))
  1789. LocalPingInterval = GetPingIntervalFromConnectionTimeout(ConnectionTimeout);
  1790. return LocalPingInterval;
  1791. }
  1792. RPC_STATUS SetNewPingInterval (
  1793. IN ULONG NewPingInterval
  1794. );
  1795. void RescheduleTimer (
  1796. void
  1797. );
  1798. private:
  1799. void DisablePingsInternal (
  1800. void
  1801. );
  1802. RPC_STATUS SendPingPacket (
  1803. void
  1804. );
  1805. RPC_STATUS SendInternal (
  1806. IN OUT HTTP2SendContext *SendContext
  1807. );
  1808. ULONG LastPacketSentTimestamp; // the timestamp of the last sent packet
  1809. ULONG PingInterval; // the ping interval
  1810. HANDLE PingTimer; // the handle for the periodic
  1811. // timer. If no timer is set, this is
  1812. // NULL
  1813. ULONG KeepAliveInterval; // current keep alive interval
  1814. ULONG ConnectionTimeout; // current connection timeout
  1815. ULONG ConsecutivePingsOnInterval; // how many consecutive pings did we
  1816. // see on this channel without other
  1817. // activities. If too many, we will
  1818. // scale back on the pings
  1819. BOOL NotifyTopChannelForPings;
  1820. };
  1821. class HTTP2PingReceiver : public HTTP2TransportChannel
  1822. {
  1823. public:
  1824. HTTP2PingReceiver::HTTP2PingReceiver (
  1825. IN BOOL PostAnotherReceive
  1826. )
  1827. {
  1828. this->PostAnotherReceive = PostAnotherReceive;
  1829. }
  1830. // Send is inheritted
  1831. // HTTP2PingReceiver inherits receive from HTTP2TransportChannel
  1832. // Send complete is inheritted
  1833. virtual RPC_STATUS ReceiveComplete (
  1834. IN RPC_STATUS EventStatus,
  1835. IN HTTP2TrafficType TrafficType,
  1836. IN BYTE *Buffer,
  1837. IN UINT BufferLength
  1838. );
  1839. // Abort is inherrited
  1840. virtual void FreeObject (
  1841. void
  1842. );
  1843. protected:
  1844. BOOL PostAnotherReceive;
  1845. };
  1846. typedef struct tagReceiveOverlapped
  1847. {
  1848. ULONG_PTR Internal; // same layout as stock overlapped
  1849. BYTE *Buffer;
  1850. ULONG BufferLength;
  1851. ULONG IOCompleted;
  1852. HANDLE hEvent;
  1853. } ReceiveOverlapped;
  1854. C_ASSERT(FIELD_OFFSET(ReceiveOverlapped, hEvent) == FIELD_OFFSET(OVERLAPPED, hEvent));
  1855. C_ASSERT(FIELD_OFFSET(ReceiveOverlapped, IOCompleted) == FIELD_OFFSET(OVERLAPPED, OffsetHigh));
  1856. // Channel checks the event in the request, and if
  1857. // set, fires it and doesn't forward any further. It also strips
  1858. // the receive event off receives. It still allows both async
  1859. // and sync requests down
  1860. class HTTP2Channel : public HTTP2TransportChannel
  1861. {
  1862. public:
  1863. HTTP2Channel (
  1864. IN int InitialFlag,
  1865. OUT RPC_STATUS *Status
  1866. ) : RefCount (1),
  1867. Aborted (0),
  1868. SubmitAsyncStarted (0),
  1869. ParentPointerLockCount(0)
  1870. {
  1871. AbortReason = RPC_S_OK;
  1872. ChannelId = 0;
  1873. Flags.SetFlagUnsafe(InitialFlag);
  1874. }
  1875. virtual RPC_STATUS Send (
  1876. IN OUT HTTP2SendContext *SendContext
  1877. );
  1878. virtual RPC_STATUS Receive (
  1879. IN HTTP2TrafficType TrafficType
  1880. );
  1881. virtual RPC_STATUS SendComplete (
  1882. IN RPC_STATUS EventStatus,
  1883. IN OUT HTTP2SendContext *SendContext
  1884. );
  1885. virtual RPC_STATUS ReceiveComplete (
  1886. IN RPC_STATUS EventStatus,
  1887. IN HTTP2TrafficType TrafficType,
  1888. IN BYTE *Buffer,
  1889. IN UINT BufferLength
  1890. );
  1891. // aborts the channel. Called from above or in neutral context
  1892. // only. Calling it from submit context will cause deadlock
  1893. virtual void Abort (
  1894. IN RPC_STATUS RpcStatus
  1895. );
  1896. void PrepareForSyncSend (
  1897. IN ULONG BufferLength,
  1898. IN BYTE *Buffer,
  1899. IN OUT HTTP2SendContext *SendContext
  1900. );
  1901. virtual RPC_STATUS SyncSend (
  1902. IN HTTP2TrafficType TrafficType,
  1903. IN ULONG BufferLength,
  1904. IN BYTE *Buffer,
  1905. IN BOOL fDisableCancelCheck,
  1906. IN ULONG Timeout,
  1907. IN BASE_ASYNC_OBJECT *Connection,
  1908. IN HTTP2SendContext *SendContext
  1909. );
  1910. // on receiving channels forwards traffic on
  1911. // the sending channel. On sending channels it gets
  1912. // sent down. The default implementation is
  1913. // for sending channels
  1914. virtual RPC_STATUS ForwardTraffic (
  1915. IN BYTE *Packet,
  1916. IN ULONG PacketLength
  1917. );
  1918. virtual RPC_STATUS ForwardFlowControlAck (
  1919. IN ULONG BytesReceivedForAck,
  1920. IN ULONG WindowForAck
  1921. );
  1922. virtual RPC_STATUS AsyncCompleteHelper (
  1923. IN RPC_STATUS CurrentStatus
  1924. );
  1925. virtual RPC_STATUS SetKeepAliveTimeout (
  1926. IN BOOL TurnOn,
  1927. IN BOOL bProtectIO,
  1928. IN KEEPALIVE_TIMEOUT_UNITS Units,
  1929. IN OUT KEEPALIVE_TIMEOUT KATime,
  1930. IN ULONG KAInterval = 5000 OPTIONAL
  1931. );
  1932. // some top channels provide notification
  1933. // mechanism for channels below them to
  1934. // notify them when the last packet is sent.
  1935. // Some channels don't support this and will ASSERT
  1936. virtual RPC_STATUS LastPacketSentNotification (
  1937. IN HTTP2SendContext *LastSendContext
  1938. );
  1939. // travels up
  1940. virtual void SendCancelled (
  1941. IN HTTP2SendContext *SendContext
  1942. );
  1943. virtual void PingTrafficSentNotify (
  1944. IN ULONG PingTrafficSize
  1945. );
  1946. void AddReference (
  1947. void
  1948. )
  1949. {
  1950. int Count;
  1951. // make sure we don't just make up refcounts
  1952. // out of thin air
  1953. ASSERT(RefCount.GetInteger() > 0);
  1954. Count = RefCount.Increment();
  1955. LogEvent(SU_REFOBJ, EV_INC, this, IntToPtr(ObjectType), Count, 1, 1);
  1956. }
  1957. void RemoveReference (
  1958. void
  1959. )
  1960. {
  1961. int Count;
  1962. LogEvent(SU_REFOBJ, EV_DEC, this, IntToPtr(ObjectType), RefCount.GetInteger(), 1, 1);
  1963. Count = RefCount.Decrement();
  1964. ASSERT(Count >= 0);
  1965. if (0 == Count)
  1966. {
  1967. FreeObject();
  1968. }
  1969. }
  1970. int GetReferenceCount ( // used only for debugging - never for code logic
  1971. void
  1972. )
  1973. {
  1974. return RefCount.GetInteger();
  1975. }
  1976. virtual void FreeObject (
  1977. void
  1978. );
  1979. // if it return FALSE, an abort has already been issued by somebody
  1980. // and there is no need to abort. If it returns TRUE, abort may proceed
  1981. BOOL InitiateAbort (
  1982. void
  1983. )
  1984. {
  1985. if (Aborted.Increment() > 1)
  1986. {
  1987. return FALSE;
  1988. }
  1989. LogEvent(SU_TRANS_CONN, EV_ABORT, this, 0, ObjectType, 1, 2);
  1990. while (SubmitAsyncStarted.GetInteger() > 0)
  1991. {
  1992. Sleep(1);
  1993. }
  1994. return TRUE;
  1995. }
  1996. // provides submission context (i.e. abort synchronization)
  1997. // without adding a refcount
  1998. RPC_STATUS BeginSimpleSubmitAsync (
  1999. void
  2000. )
  2001. {
  2002. int Count;
  2003. Count = SubmitAsyncStarted.Increment();
  2004. LogEvent(SU_HTTPv2, EV_INC, this, IntToPtr(ObjectType), Count, 1, 1);
  2005. if (Aborted.GetInteger() > 0)
  2006. {
  2007. LogEvent(SU_HTTPv2, EV_DEC, this, IntToPtr(ObjectType), Count, 1, 1);
  2008. SubmitAsyncStarted.Decrement();
  2009. return GetAbortReason();
  2010. }
  2011. return RPC_S_OK;
  2012. }
  2013. // if it returns error, the channel is aborted and the operation
  2014. // can be considered failed. If it returns RPC_S_OK, FinishSubmitAsync
  2015. // must be called when the submission is done, and RemoveReference
  2016. // when the async operation is done.
  2017. RPC_STATUS BeginSubmitAsync (
  2018. void
  2019. )
  2020. {
  2021. int Count;
  2022. Count = SubmitAsyncStarted.Increment();
  2023. LogEvent(SU_HTTPv2, EV_INC, this, IntToPtr(ObjectType), Count, 1, 1);
  2024. if (Aborted.GetInteger() > 0)
  2025. {
  2026. LogEvent(SU_HTTPv2, EV_DEC, this, IntToPtr(ObjectType), Count, 1, 1);
  2027. SubmitAsyncStarted.Decrement();
  2028. ASSERT(GetAbortReason() != RPC_S_OK);
  2029. return GetAbortReason();
  2030. }
  2031. AddReference();
  2032. return RPC_S_OK;
  2033. }
  2034. // Same as BeginSubmitAsync except that this API ignores pending aborts.
  2035. // It is used in cases where we submit an async send on a plugged channel
  2036. // and want the send to be queued even if the channel has an abort pending.
  2037. void BeginSubmitAsyncNonFailing (
  2038. void
  2039. )
  2040. {
  2041. int Count;
  2042. Count = SubmitAsyncStarted.Increment();
  2043. LogEvent(SU_HTTPv2, EV_INC, this, IntToPtr(ObjectType), Count, 1, 1);
  2044. AddReference();
  2045. }
  2046. void FinishSubmitAsync (
  2047. void
  2048. )
  2049. {
  2050. LogEvent(SU_HTTPv2, EV_DEC, this, IntToPtr(ObjectType), SubmitAsyncStarted.GetInteger(), 1, 1);
  2051. SubmitAsyncStarted.Decrement();
  2052. }
  2053. inline void VerifyAborted (
  2054. void
  2055. )
  2056. {
  2057. ASSERT(Aborted.GetInteger() > 0);
  2058. }
  2059. void SetParent (
  2060. IN HTTP2VirtualConnection *NewParent
  2061. )
  2062. {
  2063. Parent = NewParent;
  2064. }
  2065. void *GetRuntimeConnection (
  2066. void
  2067. )
  2068. {
  2069. // N.B. In some cases during channel recycling,
  2070. // the parent can be NULL (if the channel was
  2071. // detached before it was aborted).
  2072. return (void *)Parent;
  2073. }
  2074. void SetChannelId (
  2075. int NewChannelId
  2076. )
  2077. {
  2078. ASSERT(ChannelId == 0);
  2079. ASSERT(NewChannelId != 0);
  2080. ChannelId = NewChannelId;
  2081. }
  2082. HTTP2VirtualConnection *LockParentPointer (
  2083. void
  2084. )
  2085. {
  2086. HTTP2VirtualConnection *LocalParent;
  2087. ParentPointerLockCount.Increment();
  2088. LocalParent = (HTTP2VirtualConnection *)Parent;
  2089. if (LocalParent == NULL)
  2090. {
  2091. ParentPointerLockCount.Decrement();
  2092. }
  2093. return LocalParent; // may be NULL - that's ok
  2094. }
  2095. void UnlockParentPointer (
  2096. void
  2097. )
  2098. {
  2099. ASSERT(ParentPointerLockCount.GetInteger() > 0);
  2100. ParentPointerLockCount.Decrement();
  2101. }
  2102. inline void DrainUpcallsAndFreeParent (
  2103. void
  2104. )
  2105. {
  2106. DrainUpcallsAndFreeParentInternal (0);
  2107. }
  2108. inline void DrainUpcallsAndFreeParentFromUpcall (
  2109. void
  2110. )
  2111. {
  2112. DrainUpcallsAndFreeParentInternal (1);
  2113. }
  2114. void DrainPendingSubmissions (
  2115. void
  2116. )
  2117. {
  2118. #if DBG
  2119. int Retries = 0;
  2120. #endif
  2121. while (SubmitAsyncStarted.GetInteger() > 0)
  2122. {
  2123. Sleep(2);
  2124. #if DBG
  2125. Retries ++;
  2126. if (Retries > 100000)
  2127. {
  2128. ASSERT(!"Cannot drain pending submissions on channel");
  2129. Retries = 0;
  2130. }
  2131. #endif
  2132. }
  2133. }
  2134. inline void SetAbortReason (
  2135. RPC_STATUS RpcStatus
  2136. )
  2137. {
  2138. if (AbortReason == RPC_S_OK)
  2139. AbortReason = RpcStatus;
  2140. }
  2141. inline RPC_STATUS GetAbortReason (
  2142. void
  2143. )
  2144. {
  2145. ASSERT(Aborted.GetInteger() > 0);
  2146. if (AbortReason == RPC_S_OK)
  2147. return RPC_P_CONNECTION_CLOSED;
  2148. else
  2149. return AbortReason;
  2150. }
  2151. virtual void AbortConnection (
  2152. IN RPC_STATUS AbortReason
  2153. );
  2154. void AbortAndDestroyConnection (
  2155. IN RPC_STATUS AbortStatus
  2156. );
  2157. RPC_STATUS HandleSendResultFromNeutralContext (
  2158. IN RPC_STATUS CurrentStatus
  2159. );
  2160. RPC_STATUS IsInChannel (
  2161. OUT BOOL *InChannel
  2162. );
  2163. BOOL IsProxyChannel (
  2164. void
  2165. )
  2166. {
  2167. return Flags.GetFlag(ProxyChannelType);
  2168. }
  2169. protected:
  2170. BOOL SetDeletedFlag(
  2171. void
  2172. )
  2173. {
  2174. int SavedObjectType = ObjectType;
  2175. if (((SavedObjectType & OBJECT_DELETED) == 0) &&
  2176. InterlockedCompareExchange((long *)&ObjectType, SavedObjectType | OBJECT_DELETED, SavedObjectType) == SavedObjectType)
  2177. {
  2178. LogEvent(SU_REFOBJ, EV_DELETE, this, IntToPtr(SavedObjectType), RefCount.GetInteger(), 1, 1);
  2179. return TRUE;
  2180. }
  2181. return FALSE;
  2182. }
  2183. void DrainUpcallsAndFreeParentInternal (
  2184. IN int UpcallsToLeave
  2185. )
  2186. {
  2187. #if DBG
  2188. int Retries = 0;
  2189. #endif
  2190. LogEvent(SU_HTTPv2, EV_SET, &Parent, (void *)Parent, 0, 1, 0);
  2191. Parent = NULL;
  2192. while (ParentPointerLockCount.GetInteger() > UpcallsToLeave)
  2193. {
  2194. Sleep(2);
  2195. #if DBG
  2196. Retries ++;
  2197. if (Retries > 100000)
  2198. {
  2199. ASSERT(!"Cannot drain upcalls on channel");
  2200. Retries = 0;
  2201. }
  2202. #endif
  2203. }
  2204. }
  2205. RPC_STATUS CheckSendCompleteForSync (
  2206. IN RPC_STATUS EventStatus,
  2207. IN OUT HTTP2SendContext *SendContext
  2208. );
  2209. RPC_STATUS ForwardUpSendComplete (
  2210. IN RPC_STATUS EventStatus,
  2211. IN OUT HTTP2SendContext *SendContext
  2212. );
  2213. virtual RPC_STATUS CheckReceiveCompleteForSync (
  2214. IN RPC_STATUS EventStatus,
  2215. IN HTTP2TrafficType TrafficType,
  2216. IN BYTE *Buffer,
  2217. IN UINT BufferLength
  2218. );
  2219. RPC_STATUS ForwardUpReceiveComplete (
  2220. IN RPC_STATUS EventStatus,
  2221. IN BYTE *Buffer,
  2222. IN UINT BufferLength
  2223. );
  2224. HANDLE_TYPE ObjectType;
  2225. // the channel always has one lifetime reference +
  2226. // 1 reference for all async operations (sends,
  2227. // receives, timers)
  2228. INTERLOCKED_INTEGER RefCount;
  2229. INTERLOCKED_INTEGER Aborted;
  2230. INTERLOCKED_INTEGER SubmitAsyncStarted;
  2231. volatile HTTP2VirtualConnection *Parent;
  2232. INTERLOCKED_INTEGER ParentPointerLockCount;
  2233. static const ProxyChannelType = 1;
  2234. // can be ProxyChannelType
  2235. CompositeFlags Flags;
  2236. RPC_STATUS AbortReason;
  2237. int ChannelId; // opaque number set by the parent that the channel reports back
  2238. // on complete events
  2239. RPC_STATUS ForwardFlowControlAckOnDefaultChannel (
  2240. IN BOOL IsInChannel,
  2241. IN ForwardDestinations Destination,
  2242. IN ULONG BytesReceivedForAck,
  2243. IN ULONG WindowForAck
  2244. );
  2245. RPC_STATUS ForwardFlowControlAckOnThisChannel (
  2246. IN ULONG BytesReceivedForAck,
  2247. IN ULONG WindowForAck,
  2248. IN BOOL NonChannelData
  2249. );
  2250. };
  2251. typedef enum tagHTTP2StateValues
  2252. {
  2253. http2svInvalid = 0,
  2254. http2svClosed, // 1
  2255. http2svOpened, // 2
  2256. http2svA3W, // 3
  2257. http2svC2W, // 4
  2258. http2svOpened_A6W, // 5
  2259. http2svOpened_A10W, // 6
  2260. http2svOpened_A5W, // 7
  2261. http2svB2W, // 8
  2262. http2svB3W, // 9
  2263. http2svC1W, // 10
  2264. http2svOpened_CliW, // 11
  2265. http2svOpened_A9W, // 12
  2266. http2svA11W, // 13
  2267. http2svOpened_B1W, // 14
  2268. http2svA2W, // 15
  2269. http2svOpened_A4W, // 16
  2270. http2svOpened_A8W, // 17
  2271. http2svOpened_B3W, // 18
  2272. http2svOpened_D5A8W, // 19
  2273. http2svSearchProxy, // 20
  2274. http2svNonDefaultChannelCloseWait // 21
  2275. } HTTP2StateValues;
  2276. class HTTP2State
  2277. {
  2278. public:
  2279. HTTP2State (OUT RPC_STATUS *RpcStatus)
  2280. : Mutex(RpcStatus)
  2281. {
  2282. State = http2svClosed;
  2283. }
  2284. MUTEX Mutex;
  2285. HTTP2StateValues State;
  2286. };
  2287. // The maximum number of concurent locks on HTTP2ChannelPointer.
  2288. // When we free HTTP2ChannelPointer, we mark that it is freed by setting
  2289. // ChannelPointerLockCount to -(MAX_CHANNEL_POINTER_LOCKS+1). This way
  2290. // ChannelPointerLockCount will remain below zero even if MAX_CHANNEL_POINTER_LOCKS
  2291. // threads attempt to lock the channel pointer simultaneously.
  2292. #define MAX_CHANNEL_POINTER_LOCKS (100)
  2293. class HTTP2ChannelPointer
  2294. {
  2295. public:
  2296. HTTP2ChannelPointer (
  2297. void
  2298. ) : ChannelPointerLockCount(-1*(MAX_CHANNEL_POINTER_LOCKS+1)) // The channel pointer starts of not set.
  2299. {
  2300. Channel = NULL;
  2301. }
  2302. HTTP2Channel *LockChannelPointer (
  2303. void
  2304. )
  2305. {
  2306. int Count;
  2307. LogEvent(SU_HTTPv2, EV_INC, this, Channel, ChannelPointerLockCount.GetInteger(), 1, 1);
  2308. Count = ChannelPointerLockCount.Increment();
  2309. // If Count is below zero, the channel is freed and not set. It can't be locked.
  2310. if (Count < 0)
  2311. {
  2312. LogEvent(SU_HTTPv2, EV_DEC, this, Channel, Count, 1, 1);
  2313. ChannelPointerLockCount.Decrement();
  2314. return NULL;
  2315. }
  2316. return Channel;
  2317. }
  2318. void UnlockChannelPointer (
  2319. void
  2320. )
  2321. {
  2322. LogEvent(SU_HTTPv2, EV_DEC, this, Channel, ChannelPointerLockCount.GetInteger(), 1, 1);
  2323. // The channel pointer must have been locked.
  2324. ASSERT(ChannelPointerLockCount.GetInteger() > 0);
  2325. ChannelPointerLockCount.Decrement();
  2326. }
  2327. void FreeChannelPointer (
  2328. IN BOOL DrainUpCalls,
  2329. IN BOOL CalledFromUpcallContext,
  2330. IN BOOL Abort,
  2331. IN RPC_STATUS AbortStatus
  2332. )
  2333. {
  2334. HTTP2Channel *LocalChannel;
  2335. LogEvent(SU_HTTPv2, EV_DELETE, this, Channel, ChannelPointerLockCount.GetInteger(), 1, 1);
  2336. // verify input parameters
  2337. if (DrainUpCalls == FALSE)
  2338. {
  2339. ASSERT(CalledFromUpcallContext == FALSE);
  2340. }
  2341. if (Abort == FALSE)
  2342. {
  2343. ASSERT(AbortStatus == RPC_S_OK);
  2344. }
  2345. LocalChannel = Channel;
  2346. while (TRUE)
  2347. {
  2348. // Wait until the channel pointer becomes unlocked and then free it.
  2349. // To do this we wait until ChannelPointerLockCount drops to 0.
  2350. // and atomically set it to a negative number. ChannelPointerLockCount<0 signals
  2351. // a freed channel to the others.
  2352. if (ChannelPointerLockCount.CompareExchange(-1*(MAX_CHANNEL_POINTER_LOCKS+1), 0) == 0)
  2353. break;
  2354. // It is possible that the channel pointer
  2355. // is freed from two places. E.g. client freeing
  2356. // old channel while being aborted.
  2357. // If the ChannelPointer is already freed, we will bail out.
  2358. if (ChannelPointerLockCount.GetInteger() < 0)
  2359. return;
  2360. Sleep(2);
  2361. }
  2362. if (LocalChannel)
  2363. {
  2364. if (DrainUpCalls)
  2365. {
  2366. // make sure all calls to us have been drained
  2367. if (CalledFromUpcallContext)
  2368. LocalChannel->DrainUpcallsAndFreeParentFromUpcall();
  2369. else
  2370. LocalChannel->DrainUpcallsAndFreeParent();
  2371. }
  2372. if (Abort)
  2373. LocalChannel->Abort(AbortStatus);
  2374. // we're ready to detach - remove child lifetime reference
  2375. LocalChannel->RemoveReference();
  2376. }
  2377. }
  2378. inline void SetChannel (
  2379. HTTP2Channel *NewChannel
  2380. )
  2381. {
  2382. LogEvent(SU_HTTPv2, EV_SET, this, Channel, ChannelPointerLockCount.GetInteger(), 1, 1);
  2383. // The channel must have been in the freed state originally.
  2384. ASSERT(ChannelPointerLockCount.GetInteger() < 0);
  2385. // Initialize Channel before we adjust ChannelPointerLockCount.
  2386. // ChannelPointerLockCount>=0 implies a set channel to other threads.
  2387. Channel = NewChannel;
  2388. // Mark the channel as set.
  2389. ChannelPointerLockCount.Exchange(0);
  2390. }
  2391. inline BOOL IsChannelSet (
  2392. void
  2393. )
  2394. {
  2395. return (ChannelPointerLockCount.GetInteger() >= 0);
  2396. }
  2397. void DrainPendingLocks (
  2398. IN ULONG LocksToLeave
  2399. )
  2400. {
  2401. #if DBG
  2402. int Retries = 0;
  2403. #endif
  2404. while (ChannelPointerLockCount.GetInteger() > (long)LocksToLeave)
  2405. {
  2406. Sleep(2);
  2407. #if DBG
  2408. Retries ++;
  2409. if (Retries > 100000)
  2410. {
  2411. ASSERT(!"Cannot drain pending locks on channel");
  2412. Retries = 0;
  2413. }
  2414. #endif
  2415. }
  2416. }
  2417. private:
  2418. // This is the interlocked integer that is used for all syncronization needs as follows:
  2419. // - ChannelPointerLockCount == 0 - allocated/set and unlocked
  2420. // - ChannelPointerLockCount > 0 - locked
  2421. // - ChannelPointerLockCount < 0 - freed and not set
  2422. //
  2423. // ========== ============= ==========
  2424. // | Freed | -- SetChannel --> | Allocated | -- LockCP ---> | Locked |
  2425. // | lock<0 | <- FreeCP ------- | lock==0 | <- UnlockCP -- | lock>0 |
  2426. // ========== ============= ==========
  2427. //
  2428. INTERLOCKED_INTEGER ChannelPointerLockCount;
  2429. HTTP2Channel *Channel;
  2430. };
  2431. // the only members of BASE_ASYNC_OBJECT used are type and id. Think
  2432. // of better way to do this than wholesale inheritance
  2433. class HTTP2VirtualConnection : public BASE_ASYNC_OBJECT
  2434. {
  2435. public:
  2436. HTTP2VirtualConnection (
  2437. void
  2438. ) : Aborted(0)
  2439. {
  2440. InChannelIds[0] = InChannelIds[1] = 0;
  2441. OutChannelIds[0] = OutChannelIds[1] = 0;
  2442. DefaultLoopbackChannelSelector = 0;
  2443. }
  2444. virtual ~HTTP2VirtualConnection (
  2445. void
  2446. )
  2447. {
  2448. }
  2449. virtual RPC_STATUS Send (
  2450. IN UINT Length,
  2451. IN BUFFER Buffer,
  2452. IN PVOID SendContext
  2453. );
  2454. virtual RPC_STATUS Receive (
  2455. void
  2456. );
  2457. virtual RPC_STATUS SendComplete (
  2458. IN RPC_STATUS EventStatus,
  2459. IN OUT HTTP2SendContext *SendContext,
  2460. IN int ChannelId
  2461. ) = 0;
  2462. virtual RPC_STATUS ReceiveComplete (
  2463. IN RPC_STATUS EventStatus,
  2464. IN BYTE *Buffer,
  2465. IN UINT BufferLength,
  2466. IN int ChannelId
  2467. ) = 0;
  2468. virtual RPC_STATUS SyncSend (
  2469. IN ULONG BufferLength,
  2470. IN BYTE *Buffer,
  2471. IN BOOL fDisableShutdownCheck,
  2472. IN BOOL fDisableCancelCheck,
  2473. IN ULONG Timeout
  2474. );
  2475. virtual RPC_STATUS SyncRecv (
  2476. IN BYTE **Buffer,
  2477. IN ULONG *BufferLength,
  2478. IN ULONG Timeout
  2479. );
  2480. virtual void Abort (
  2481. void
  2482. ) = 0;
  2483. virtual void Close (
  2484. IN BOOL DontFlush
  2485. );
  2486. virtual RPC_STATUS TurnOnOffKeepAlives (
  2487. IN BOOL TurnOn,
  2488. IN BOOL bProtectIO,
  2489. IN BOOL IsFromUpcall,
  2490. IN KEEPALIVE_TIMEOUT_UNITS Units,
  2491. IN OUT KEEPALIVE_TIMEOUT KATime,
  2492. IN ULONG KAInterval = 5000 OPTIONAL
  2493. );
  2494. virtual RPC_STATUS QueryClientAddress (
  2495. OUT RPC_CHAR **pNetworkAddress
  2496. );
  2497. virtual RPC_STATUS QueryLocalAddress (
  2498. IN OUT void *Buffer,
  2499. IN OUT unsigned long *BufferSize,
  2500. OUT unsigned long *AddressFormat
  2501. );
  2502. virtual RPC_STATUS QueryClientId(
  2503. OUT RPC_CLIENT_PROCESS_IDENTIFIER *ClientProcess
  2504. );
  2505. virtual RPC_STATUS QueryClientIpAddress (
  2506. IN OUT RPC_CLIENT_IP_ADDRESS *ClientIpAddress
  2507. );
  2508. void AbortChannels (
  2509. IN RPC_STATUS RpcStatus
  2510. );
  2511. BOOL AbortAndDestroy (
  2512. IN BOOL IsFromChannel,
  2513. IN int CallingChannelId,
  2514. IN RPC_STATUS AbortStatus
  2515. );
  2516. virtual void LastPacketSentNotification (
  2517. IN int ChannelId,
  2518. IN HTTP2SendContext *LastSendContext
  2519. );
  2520. inline HTTP2Channel *LockDefaultInChannel (
  2521. OUT HTTP2ChannelPointer **ChannelPointer
  2522. )
  2523. {
  2524. return LockDefaultChannel (&DefaultInChannelSelector,
  2525. InChannels, ChannelPointer);
  2526. }
  2527. inline HTTP2Channel *LockDefaultOutChannel (
  2528. OUT HTTP2ChannelPointer **ChannelPointer
  2529. )
  2530. {
  2531. return LockDefaultChannel (&DefaultOutChannelSelector,
  2532. OutChannels, ChannelPointer);
  2533. }
  2534. RPC_STATUS PostReceiveOnChannel (
  2535. IN HTTP2ChannelPointer *ChannelPtr,
  2536. IN HTTP2TrafficType TrafficType
  2537. );
  2538. RPC_STATUS PostReceiveOnDefaultChannel (
  2539. IN BOOL IsInChannel,
  2540. IN HTTP2TrafficType TrafficType
  2541. );
  2542. RPC_STATUS ForwardTrafficToChannel (
  2543. IN HTTP2ChannelPointer *ChannelPtr,
  2544. IN BYTE *Packet,
  2545. IN ULONG PacketLength
  2546. );
  2547. RPC_STATUS ForwardTrafficToDefaultChannel (
  2548. IN BOOL IsInChannel,
  2549. IN BYTE *Packet,
  2550. IN ULONG PacketLength
  2551. );
  2552. RPC_STATUS SendTrafficOnChannel (
  2553. IN HTTP2ChannelPointer *ChannelPtr,
  2554. IN HTTP2SendContext *SendContext
  2555. );
  2556. RPC_STATUS SendTrafficOnDefaultChannel (
  2557. IN BOOL IsInChannel,
  2558. IN HTTP2SendContext *SendContext
  2559. );
  2560. virtual RPC_STATUS RecycleChannel (
  2561. IN BOOL IsFromUpcall
  2562. );
  2563. RPC_STATUS StartChannelRecyclingIfNecessary (
  2564. IN RPC_STATUS RpcStatus,
  2565. IN BOOL IsFromUpcall
  2566. );
  2567. // N.B.: The pointer to the cookie returned
  2568. // is safe only while the calling channel
  2569. // has a lock on its parent
  2570. inline HTTP2Cookie *MapChannelIdToCookie (
  2571. IN int ChannelId
  2572. )
  2573. {
  2574. if (ChannelId == InChannelIds[0])
  2575. {
  2576. return &InChannelCookies[0];
  2577. }
  2578. else if (ChannelId == InChannelIds[1])
  2579. {
  2580. return &InChannelCookies[1];
  2581. }
  2582. else if (ChannelId == OutChannelIds[0])
  2583. {
  2584. return &OutChannelCookies[0];
  2585. }
  2586. else if (ChannelId == OutChannelIds[1])
  2587. {
  2588. return &OutChannelCookies[1];
  2589. }
  2590. else
  2591. {
  2592. ASSERT(0);
  2593. return NULL;
  2594. }
  2595. }
  2596. HTTP2Channel *MapCookieToChannelPointer (
  2597. IN HTTP2Cookie *ChannelCookie,
  2598. OUT HTTP2ChannelPointer **ChannelPtr
  2599. );
  2600. HTTP2Channel *MapCookieToAnyChannelPointer (
  2601. IN HTTP2Cookie *ChannelCookie,
  2602. OUT HTTP2ChannelPointer **ChannelPtr
  2603. );
  2604. inline BOOL IsInChannel (
  2605. IN int ChannelId
  2606. )
  2607. {
  2608. return ((ChannelId == InChannelIds[0])
  2609. || (ChannelId == InChannelIds[1]));
  2610. }
  2611. inline BOOL IsInChannel (
  2612. IN HTTP2ChannelPointer *ChannelPtr
  2613. )
  2614. {
  2615. return ((ChannelPtr == &InChannels[0])
  2616. || (ChannelPtr == &InChannels[1]));
  2617. }
  2618. inline int GetDefaultInChannelId (
  2619. void
  2620. )
  2621. {
  2622. return InChannelIds[DefaultInChannelSelector];
  2623. }
  2624. inline BOOL IsDefaultInChannel (
  2625. IN int ChannelId
  2626. )
  2627. {
  2628. return (ChannelId == GetDefaultInChannelId());
  2629. }
  2630. inline BOOL IsOutChannel (
  2631. IN int ChannelId
  2632. )
  2633. {
  2634. return ((ChannelId == OutChannelIds[0])
  2635. || (ChannelId == OutChannelIds[1]));
  2636. }
  2637. inline BOOL IsOutChannel (
  2638. IN HTTP2ChannelPointer *ChannelPtr
  2639. )
  2640. {
  2641. return ((ChannelPtr == &OutChannels[0])
  2642. || (ChannelPtr == &OutChannels[1]));
  2643. }
  2644. inline int GetDefaultOutChannelId (
  2645. void
  2646. )
  2647. {
  2648. return OutChannelIds[DefaultOutChannelSelector];
  2649. }
  2650. inline BOOL IsDefaultOutChannel (
  2651. IN int ChannelId
  2652. )
  2653. {
  2654. return (ChannelId == GetDefaultOutChannelId());
  2655. }
  2656. inline BOOL IsAborted (
  2657. void
  2658. )
  2659. {
  2660. return (Aborted.GetInteger() > 0);
  2661. }
  2662. #if DBG
  2663. inline void VerifyValidChannelId (
  2664. IN int ChannelId
  2665. )
  2666. {
  2667. ASSERT(IsInChannel(ChannelId) || IsOutChannel(ChannelId));
  2668. }
  2669. #else
  2670. inline void VerifyValidChannelId (
  2671. IN int ChannelId
  2672. )
  2673. {
  2674. }
  2675. #endif
  2676. protected:
  2677. inline int GetNonDefaultInChannelSelector (
  2678. void
  2679. )
  2680. {
  2681. return (DefaultInChannelSelector ^ 1);
  2682. }
  2683. inline int GetNonDefaultOutChannelSelector (
  2684. void
  2685. )
  2686. {
  2687. // return 0 to 1 and 1 to 0
  2688. return (DefaultOutChannelSelector ^ 1);
  2689. }
  2690. inline void SwitchDefaultInChannelSelector (
  2691. void
  2692. )
  2693. {
  2694. DefaultInChannelSelector = DefaultInChannelSelector ^ 1;
  2695. }
  2696. inline void SwitchDefaultOutChannelSelector (
  2697. void
  2698. )
  2699. {
  2700. DefaultOutChannelSelector = DefaultOutChannelSelector ^ 1;
  2701. }
  2702. inline void SwitchDefaultLoopbackChannelSelector (
  2703. void
  2704. )
  2705. {
  2706. DefaultLoopbackChannelSelector = DefaultLoopbackChannelSelector ^ 1;
  2707. }
  2708. inline int CompareCookieWithDefaultInChannelCookie (
  2709. IN HTTP2Cookie *OtherCookie
  2710. )
  2711. {
  2712. return InChannelCookies[DefaultInChannelSelector].Compare(OtherCookie);
  2713. }
  2714. inline int CompareCookieWithDefaultOutChannelCookie (
  2715. IN HTTP2Cookie *OtherCookie
  2716. )
  2717. {
  2718. return OutChannelCookies[DefaultOutChannelSelector].Compare(OtherCookie);
  2719. }
  2720. inline int AllocateChannelId (
  2721. void
  2722. )
  2723. {
  2724. return InterlockedIncrement(&ChannelIdCounter);
  2725. }
  2726. inline HTTP2ChannelPointer *GetChannelPointerFromId (
  2727. IN int ChannelId
  2728. )
  2729. {
  2730. if (ChannelId == InChannelIds[0])
  2731. {
  2732. return &InChannels[0];
  2733. }
  2734. else if (ChannelId == InChannelIds[1])
  2735. {
  2736. return &InChannels[1];
  2737. }
  2738. else if (ChannelId == OutChannelIds[0])
  2739. {
  2740. return &OutChannels[0];
  2741. }
  2742. else if (ChannelId == OutChannelIds[1])
  2743. {
  2744. return &OutChannels[1];
  2745. }
  2746. else
  2747. {
  2748. ASSERT(0);
  2749. return NULL;
  2750. }
  2751. }
  2752. virtual HTTP2Channel *LockDefaultSendChannel (
  2753. OUT HTTP2ChannelPointer **ChannelPtr
  2754. );
  2755. virtual HTTP2Channel *LockDefaultReceiveChannel (
  2756. OUT HTTP2ChannelPointer **ChannelPtr
  2757. );
  2758. void SetFirstInChannel (
  2759. IN HTTP2Channel *NewChannel
  2760. );
  2761. void SetFirstOutChannel (
  2762. IN HTTP2Channel *NewChannel
  2763. );
  2764. void SetNonDefaultInChannel (
  2765. IN HTTP2Channel *NewChannel
  2766. );
  2767. void SetNonDefaultOutChannel (
  2768. IN HTTP2Channel *NewChannel
  2769. );
  2770. INTERLOCKED_INTEGER Aborted;
  2771. HTTP2ServerCookie EmbeddedConnectionCookie;
  2772. HTTP2ChannelPointer InChannels[2];
  2773. int InChannelIds[2];
  2774. HTTP2Cookie InChannelCookies[2];
  2775. volatile int DefaultInChannelSelector;
  2776. HTTP2ChannelPointer OutChannels[2];
  2777. int OutChannelIds[2];
  2778. HTTP2Cookie OutChannelCookies[2];
  2779. volatile int DefaultOutChannelSelector;
  2780. volatile int DefaultLoopbackChannelSelector; // selector to get
  2781. // target of loopback flow control traffic. Used to select an in channel
  2782. // on the client and an out channel on the server
  2783. virtual void DisconnectChannels (
  2784. IN BOOL ExemptChannel,
  2785. IN int ExemptChannelId
  2786. );
  2787. private:
  2788. HTTP2Channel *LockDefaultChannel (
  2789. IN volatile int *DefaultChannelSelector,
  2790. IN HTTP2ChannelPointer ChannelSet[],
  2791. OUT HTTP2ChannelPointer **ChannelPointer
  2792. )
  2793. {
  2794. int LocalDefaultChannelSelector;
  2795. HTTP2Channel *Channel;
  2796. // there is a small race condition we need to take care of
  2797. // By the time we grab the default channel with the
  2798. // selector, it could have changed and we could be referencing
  2799. // a non-default channel. We know the object will be there, so
  2800. // there is no danger of AV. It just may be the wrong channel
  2801. do
  2802. {
  2803. LocalDefaultChannelSelector = *DefaultChannelSelector;
  2804. Channel = ChannelSet[LocalDefaultChannelSelector].LockChannelPointer();
  2805. // channel is locked. Check whether we got what we wanted
  2806. if (LocalDefaultChannelSelector == *DefaultChannelSelector)
  2807. break;
  2808. if (Channel)
  2809. {
  2810. // the selector changed - unlock and loop around
  2811. ChannelSet[LocalDefaultChannelSelector].UnlockChannelPointer();
  2812. }
  2813. }
  2814. while (TRUE);
  2815. *ChannelPointer = &ChannelSet[LocalDefaultChannelSelector];
  2816. return (HTTP2Channel *) Channel;
  2817. }
  2818. };
  2819. class HTTP2ClientVirtualConnection; // forward
  2820. class HTTP2ClientChannel : public HTTP2Channel
  2821. {
  2822. public:
  2823. HTTP2ClientChannel (
  2824. OUT RPC_STATUS *Status
  2825. ) : HTTP2Channel (0, // InitialFlag
  2826. Status)
  2827. {
  2828. RpcpMemorySet(&Ol, 0, sizeof(Ol));
  2829. }
  2830. RPC_STATUS ClientOpen (
  2831. IN HTTPResolverHint *Hint,
  2832. IN const char *Verb,
  2833. IN int VerbLength,
  2834. IN BOOL InChannel,
  2835. IN BOOL ReplacementChannel,
  2836. IN BOOL UseWinHttp,
  2837. IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials, OPTIONAL
  2838. IN ULONG ChosenAuthScheme,OPTIONAL
  2839. IN HTTP2WinHttpTransportChannel *WinHttpChannel, OPTIONAL
  2840. IN ULONG CallTimeout,
  2841. IN const BYTE *AdditionalData, OPTIONAL
  2842. IN ULONG AdditionalDataLength OPTIONAL
  2843. );
  2844. virtual RPC_STATUS SendComplete (
  2845. IN RPC_STATUS EventStatus,
  2846. IN OUT HTTP2SendContext *SendContext
  2847. );
  2848. virtual RPC_STATUS CheckReceiveCompleteForSync (
  2849. IN RPC_STATUS EventStatus,
  2850. IN HTTP2TrafficType TrafficType,
  2851. IN BYTE *Buffer,
  2852. IN UINT BufferLength
  2853. );
  2854. HTTP2ClientVirtualConnection *LockParentPointer (
  2855. void
  2856. )
  2857. {
  2858. return (HTTP2ClientVirtualConnection *)HTTP2Channel::LockParentPointer();
  2859. }
  2860. void WaitInfiniteForSyncReceive (
  2861. void
  2862. );
  2863. inline BOOL IsSyncRecvPending (
  2864. void
  2865. )
  2866. {
  2867. return (Ol.ReceiveOverlapped.hEvent != NULL);
  2868. }
  2869. inline void RemoveEvent (
  2870. void
  2871. )
  2872. {
  2873. ASSERT(Ol.ReceiveOverlapped.hEvent != NULL);
  2874. Ol.ReceiveOverlapped.hEvent = NULL;
  2875. }
  2876. RPC_STATUS SubmitSyncRecv (
  2877. IN HTTP2TrafficType TrafficType
  2878. );
  2879. RPC_STATUS WaitForSyncRecv (
  2880. IN BYTE **Buffer,
  2881. IN ULONG *BufferLength,
  2882. IN ULONG Timeout,
  2883. IN ULONG ConnectionTimeout,
  2884. IN BASE_ASYNC_OBJECT *Connection,
  2885. OUT BOOL *AbortNeeded,
  2886. OUT BOOL *IoPending
  2887. );
  2888. virtual void AbortConnection (
  2889. IN RPC_STATUS AbortReason
  2890. );
  2891. protected:
  2892. union
  2893. {
  2894. OVERLAPPED Overlapped;
  2895. ReceiveOverlapped ReceiveOverlapped;
  2896. } Ol;
  2897. };
  2898. class HTTP2ClientInChannel : public HTTP2ClientChannel
  2899. {
  2900. public:
  2901. HTTP2ClientInChannel (
  2902. IN HTTP2ClientVirtualConnection *ClientVirtualConnection,
  2903. OUT RPC_STATUS *RpcStatus
  2904. ) : HTTP2ClientChannel (RpcStatus)
  2905. {
  2906. SetParent((HTTP2VirtualConnection *)ClientVirtualConnection);
  2907. }
  2908. RPC_STATUS ClientOpen (
  2909. IN HTTPResolverHint *Hint,
  2910. IN const char *Verb,
  2911. IN int VerbLength,
  2912. IN BOOL UseWinHttp,
  2913. IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials,
  2914. IN ULONG ChosenAuthScheme,
  2915. IN ULONG CallTimeout,
  2916. IN const BYTE *AdditionalData, OPTIONAL
  2917. IN ULONG AdditionalDataLength OPTIONAL
  2918. );
  2919. inline RPC_STATUS Unplug (
  2920. void
  2921. )
  2922. {
  2923. HTTP2PlugChannel *PlugChannel;
  2924. PlugChannel = GetPlugChannel();
  2925. return PlugChannel->Unplug();
  2926. }
  2927. inline void GetChannelOriginatorBufferQueue (
  2928. OUT LIST_ENTRY *NewBufferHead
  2929. )
  2930. {
  2931. GetDataOriginatorChannel()->GetBufferQueue(NewBufferHead);
  2932. }
  2933. inline RPC_STATUS SetConnectionTimeout (
  2934. IN ULONG ConnectionTimeout
  2935. )
  2936. {
  2937. return GetPingOriginatorChannel()->SetConnectionTimeout(ConnectionTimeout);
  2938. }
  2939. virtual RPC_STATUS SetKeepAliveTimeout (
  2940. IN BOOL TurnOn,
  2941. IN BOOL bProtectIO,
  2942. IN KEEPALIVE_TIMEOUT_UNITS Units,
  2943. IN OUT KEEPALIVE_TIMEOUT KATime,
  2944. IN ULONG KAInterval = 5000 OPTIONAL
  2945. );
  2946. inline RPC_STATUS FlowControlAckNotify (
  2947. IN ULONG BytesReceivedForAck,
  2948. IN ULONG WindowForAck
  2949. )
  2950. {
  2951. return GetFlowControlSenderChannel()->FlowControlAckNotify(BytesReceivedForAck,
  2952. WindowForAck
  2953. );
  2954. }
  2955. inline void SetPeerReceiveWindow (
  2956. IN ULONG PeerReceiveWindow
  2957. )
  2958. {
  2959. GetFlowControlSenderChannel()->SetPeerReceiveWindow (
  2960. PeerReceiveWindow
  2961. );
  2962. }
  2963. inline ULONG GetPeerReceiveWindow (
  2964. void
  2965. )
  2966. {
  2967. return GetFlowControlSenderChannel()->GetPeerReceiveWindow ();
  2968. }
  2969. inline void GetFlowControlSenderBufferQueue (
  2970. OUT LIST_ENTRY *NewBufferHead
  2971. )
  2972. {
  2973. GetFlowControlSenderChannel()->GetBufferQueue(NewBufferHead);
  2974. }
  2975. inline void DisablePings (
  2976. void
  2977. )
  2978. {
  2979. GetPingOriginatorChannel()->DisablePings();
  2980. }
  2981. inline ULONG GetChosenAuthScheme (
  2982. void
  2983. )
  2984. {
  2985. return GetWinHttpConnection()->GetChosenAuthScheme();
  2986. }
  2987. inline BOOL IsKeepAlive (
  2988. void
  2989. )
  2990. {
  2991. return GetWinHttpConnection()->IsKeepAlive();
  2992. }
  2993. private:
  2994. inline HTTP2PlugChannel *GetPlugChannel (
  2995. void
  2996. )
  2997. {
  2998. BYTE *Channel = (BYTE *)this;
  2999. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2ClientInChannel);
  3000. return (HTTP2PlugChannel *)Channel;
  3001. }
  3002. inline HTTP2ChannelDataOriginator *GetDataOriginatorChannel (
  3003. void
  3004. )
  3005. {
  3006. BYTE *Channel = (BYTE *)this;
  3007. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2ClientInChannel)
  3008. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PlugChannel)
  3009. + SIZE_OF_OBJECT_AND_PADDING(HTTP2FlowControlSender)
  3010. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PingOriginator)
  3011. ;
  3012. return (HTTP2ChannelDataOriginator *)Channel;
  3013. }
  3014. inline HTTP2FlowControlSender *GetFlowControlSenderChannel (
  3015. void
  3016. )
  3017. {
  3018. BYTE *Channel = (BYTE *)this;
  3019. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2ClientInChannel)
  3020. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PlugChannel)
  3021. ;
  3022. return (HTTP2FlowControlSender *)Channel;
  3023. }
  3024. inline HTTP2PingOriginator *GetPingOriginatorChannel (
  3025. void
  3026. )
  3027. {
  3028. BYTE *Channel = (BYTE *)this;
  3029. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2ClientInChannel)
  3030. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PlugChannel)
  3031. + SIZE_OF_OBJECT_AND_PADDING(HTTP2FlowControlSender)
  3032. ;
  3033. return (HTTP2PingOriginator *)Channel;
  3034. }
  3035. inline HTTP2WinHttpTransportChannel *GetWinHttpConnection (
  3036. void
  3037. )
  3038. {
  3039. BYTE *Channel = (BYTE *)this;
  3040. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2ClientInChannel)
  3041. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PlugChannel)
  3042. + SIZE_OF_OBJECT_AND_PADDING(HTTP2FlowControlSender)
  3043. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PingOriginator)
  3044. + SIZE_OF_OBJECT_AND_PADDING(HTTP2ChannelDataOriginator)
  3045. ;
  3046. return (HTTP2WinHttpTransportChannel *)Channel;
  3047. }
  3048. };
  3049. class HTTP2ClientOutChannel : public HTTP2ClientChannel
  3050. {
  3051. public:
  3052. HTTP2ClientOutChannel (
  3053. IN HTTP2ClientVirtualConnection *ClientVirtualConnection,
  3054. OUT RPC_STATUS *RpcStatus
  3055. ) : HTTP2ClientChannel (RpcStatus)
  3056. {
  3057. SetParent((HTTP2VirtualConnection *)ClientVirtualConnection);
  3058. }
  3059. RPC_STATUS ClientOpen (
  3060. IN HTTPResolverHint *Hint,
  3061. IN const char *Verb,
  3062. IN int VerbLength,
  3063. IN BOOL ReplacementChannel,
  3064. IN BOOL UseWinHttp,
  3065. IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials,
  3066. IN ULONG ChosenAuthScheme,
  3067. IN ULONG CallTimeout,
  3068. IN const BYTE *AdditionalData, OPTIONAL
  3069. IN ULONG AdditionalDataLength OPTIONAL
  3070. );
  3071. virtual RPC_STATUS ForwardFlowControlAck (
  3072. IN ULONG BytesReceivedForAck,
  3073. IN ULONG WindowForAck
  3074. );
  3075. inline BOOL IsDataReceivePosted (
  3076. void
  3077. )
  3078. {
  3079. return GetEndpointReceiver()->IsDataReceivePosted();
  3080. }
  3081. inline RPC_STATUS TransferReceiveStateToNewChannel (
  3082. OUT HTTP2ClientOutChannel *NewChannel
  3083. )
  3084. {
  3085. return GetEndpointReceiver()->TransferStateToNewReceiver (
  3086. NewChannel->GetEndpointReceiver()
  3087. );
  3088. }
  3089. inline void BlockDataReceives (
  3090. void
  3091. )
  3092. {
  3093. GetEndpointReceiver()->BlockDataReceives();
  3094. }
  3095. inline void UnblockDataReceives (
  3096. void
  3097. )
  3098. {
  3099. GetEndpointReceiver()->UnblockDataReceives();
  3100. }
  3101. virtual RPC_STATUS SetKeepAliveTimeout (
  3102. IN BOOL TurnOn,
  3103. IN BOOL bProtectIO,
  3104. IN KEEPALIVE_TIMEOUT_UNITS Units,
  3105. IN OUT KEEPALIVE_TIMEOUT KATime,
  3106. IN ULONG KAInterval = 5000 OPTIONAL
  3107. );
  3108. inline ULONG GetChosenAuthScheme (
  3109. void
  3110. )
  3111. {
  3112. return GetWinHttpConnection()->GetChosenAuthScheme();
  3113. }
  3114. inline BOOL IsKeepAlive (
  3115. void
  3116. )
  3117. {
  3118. return GetWinHttpConnection()->IsKeepAlive();
  3119. }
  3120. private:
  3121. inline HTTP2EndpointReceiver *GetEndpointReceiver (
  3122. void
  3123. )
  3124. {
  3125. BYTE *ThisChannelPtr = (BYTE *)this;
  3126. ThisChannelPtr += SIZE_OF_OBJECT_AND_PADDING(HTTP2ClientOutChannel);
  3127. return (HTTP2EndpointReceiver *)ThisChannelPtr;
  3128. }
  3129. inline HTTP2WinHttpTransportChannel *GetWinHttpConnection (
  3130. void
  3131. )
  3132. {
  3133. BYTE *Channel = (BYTE *)this;
  3134. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2ClientOutChannel)
  3135. + SIZE_OF_OBJECT_AND_PADDING(HTTP2EndpointReceiver)
  3136. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PingReceiver)
  3137. ;
  3138. return (HTTP2WinHttpTransportChannel *)Channel;
  3139. }
  3140. };
  3141. class HTTP2ClientVirtualConnection : public HTTP2VirtualConnection
  3142. {
  3143. public:
  3144. HTTP2ClientVirtualConnection (
  3145. IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *NewCredentials,
  3146. OUT RPC_STATUS *RpcStatus
  3147. ) : InChannelState(RpcStatus),
  3148. OutChannelState(RpcStatus),
  3149. BlockAbortsCounter (0)
  3150. {
  3151. ConnectionTimeout = 0;
  3152. type = COMPLEX_T | CONNECTION | CLIENT;
  3153. ReissueRecv = FALSE;
  3154. ChannelsAborted = FALSE;
  3155. ConnectionHint.Initialize();
  3156. CurrentKeepAlive = 0;
  3157. HttpCredentials = NewCredentials;
  3158. InProxyConnectionTimeout = 0;
  3159. ProtocolVersion = 0;
  3160. }
  3161. inline ~HTTP2ClientVirtualConnection (
  3162. void
  3163. )
  3164. {
  3165. ConnectionHint.FreeHTTPProxy();
  3166. ConnectionHint.FreeRpcProxy();
  3167. ConnectionHint.FreeRpcServer();
  3168. }
  3169. RPC_STATUS
  3170. ClientOpen(
  3171. IN HTTPResolverHint *Hint,
  3172. IN BOOL HintWasInitialized,
  3173. IN UINT ConnTimeout,
  3174. IN ULONG CallTimeout
  3175. );
  3176. virtual RPC_STATUS SendComplete (
  3177. IN RPC_STATUS EventStatus,
  3178. IN OUT HTTP2SendContext *SendContext,
  3179. IN int ChannelId
  3180. );
  3181. virtual RPC_STATUS ReceiveComplete (
  3182. IN RPC_STATUS EventStatus,
  3183. IN BYTE *Buffer,
  3184. IN UINT BufferLength,
  3185. IN int ChannelId
  3186. );
  3187. virtual RPC_STATUS SyncRecv (
  3188. IN BYTE **Buffer,
  3189. IN ULONG *BufferLength,
  3190. IN ULONG Timeout
  3191. );
  3192. virtual void Abort (
  3193. void
  3194. );
  3195. virtual void Close (
  3196. IN BOOL DontFlush
  3197. );
  3198. virtual RPC_STATUS TurnOnOffKeepAlives (
  3199. IN BOOL TurnOn,
  3200. IN BOOL bProtectIO,
  3201. IN BOOL IsFromUpcall,
  3202. IN KEEPALIVE_TIMEOUT_UNITS Units,
  3203. IN OUT KEEPALIVE_TIMEOUT KATime,
  3204. IN ULONG KAInterval = 5000 OPTIONAL
  3205. );
  3206. virtual RPC_STATUS RecycleChannel (
  3207. IN BOOL IsFromUpcall
  3208. );
  3209. RPC_STATUS OpenReplacementOutChannel (
  3210. void
  3211. );
  3212. inline HTTP2ClientInChannel *LockDefaultInChannel (
  3213. OUT HTTP2ChannelPointer **ChannelPointer
  3214. )
  3215. {
  3216. return (HTTP2ClientInChannel *)HTTP2VirtualConnection::LockDefaultInChannel(ChannelPointer);
  3217. }
  3218. inline HTTP2ClientOutChannel *LockDefaultOutChannel (
  3219. OUT HTTP2ChannelPointer **ChannelPointer
  3220. )
  3221. {
  3222. return (HTTP2ClientOutChannel *)HTTP2VirtualConnection::LockDefaultOutChannel(ChannelPointer);
  3223. }
  3224. void AbortChannels (
  3225. IN RPC_STATUS RpcStatus
  3226. );
  3227. protected:
  3228. virtual HTTP2Channel *LockDefaultSendChannel (
  3229. OUT HTTP2ChannelPointer **ChannelPtr
  3230. );
  3231. virtual HTTP2Channel *LockDefaultReceiveChannel (
  3232. OUT HTTP2ChannelPointer **ChannelPtr
  3233. );
  3234. private:
  3235. RPC_STATUS
  3236. ClientOpenInternal(
  3237. IN HTTPResolverHint *Hint,
  3238. IN BOOL HintWasInitialized,
  3239. IN UINT ConnTimeout,
  3240. IN ULONG CallTimeout,
  3241. IN BOOL ClientOpenInChannel,
  3242. IN BOOL ClientOpenOutChannel,
  3243. IN BOOL IsReplacementChannel,
  3244. IN BOOL IsFromUpcall
  3245. );
  3246. RPC_STATUS AllocateAndInitializeInChannel (
  3247. IN HTTPResolverHint *Hint,
  3248. IN BOOL HintWasInitialized,
  3249. IN ULONG CallTimeout,
  3250. IN BOOL UseWinHttp,
  3251. OUT HTTP2ClientInChannel **ReturnInChannel
  3252. );
  3253. RPC_STATUS AllocateAndInitializeOutChannel (
  3254. IN HTTPResolverHint *Hint,
  3255. IN BOOL HintWasInitialized,
  3256. IN ULONG CallTimeout,
  3257. IN BOOL UseWinHttp,
  3258. OUT HTTP2ClientOutChannel **ReturnOutChannel
  3259. );
  3260. RPC_STATUS InitializeRawConnection (
  3261. IN OUT WS_HTTP2_CONNECTION *RawConnection,
  3262. IN HTTPResolverHint *Hint,
  3263. IN BOOL HintWasInitialized,
  3264. IN ULONG CallTimeout
  3265. );
  3266. inline void SetClientOpenInEvent (
  3267. void
  3268. )
  3269. {
  3270. InChannelState.Mutex.Request();
  3271. if (ClientOpenInEvent)
  3272. {
  3273. SetEvent(ClientOpenInEvent);
  3274. }
  3275. InChannelState.Mutex.Clear();
  3276. }
  3277. inline void SetClientOpenOutEvent (
  3278. void
  3279. )
  3280. {
  3281. InChannelState.Mutex.Request();
  3282. if (ClientOpenOutEvent)
  3283. {
  3284. SetEvent(ClientOpenOutEvent);
  3285. }
  3286. InChannelState.Mutex.Clear();
  3287. }
  3288. BOOL IsInChannelKeepAlive (
  3289. IN BOOL IsReplacementChannel
  3290. );
  3291. BOOL IsOutChannelKeepAlive (
  3292. IN BOOL IsReplacementChannel
  3293. );
  3294. ULONG GetInChannelChosenScheme (
  3295. IN BOOL IsReplacementChannel
  3296. );
  3297. ULONG GetOutChannelChosenScheme (
  3298. IN BOOL IsReplacementChannel
  3299. );
  3300. BOOL IsInChannelPositiveWithWait (
  3301. void
  3302. );
  3303. inline RPC_STATUS BlockAborts (
  3304. void
  3305. )
  3306. {
  3307. int LocalBlockAbortsCounter = BlockAbortsCounter.Increment();
  3308. LogEvent(SU_REFOBJ, EV_INC, this, IntToPtr(0x88), LocalBlockAbortsCounter, 1, 1);
  3309. // only 4 channels are subject to abort. Give it some space for multiple aborts
  3310. // in progress, and don't allow more than 10
  3311. ASSERT(BlockAbortsCounter.GetInteger() <= 10);
  3312. if (ChannelsAborted)
  3313. {
  3314. UnblockAborts();
  3315. return RPC_P_CONNECTION_SHUTDOWN;
  3316. }
  3317. return RPC_S_OK;
  3318. }
  3319. inline void UnblockAborts (
  3320. void
  3321. )
  3322. {
  3323. LogEvent(SU_REFOBJ, EV_DEC, this, IntToPtr(0x88), BlockAbortsCounter.GetInteger(), 1, 1);
  3324. BlockAbortsCounter.Decrement();
  3325. ASSERT(BlockAbortsCounter.GetInteger() >= 0);
  3326. }
  3327. inline void WaitForAbortsToUnblock (
  3328. void
  3329. )
  3330. {
  3331. #if DBG
  3332. int Retries = 0;
  3333. #endif
  3334. ASSERT(ChannelsAborted);
  3335. while (BlockAbortsCounter.GetInteger())
  3336. {
  3337. Sleep(2);
  3338. #if DBG
  3339. Retries ++;
  3340. if (Retries > 100000)
  3341. {
  3342. ASSERT(!"Cannot wait out for aborts to unblock");
  3343. Retries = 0;
  3344. }
  3345. #endif
  3346. }
  3347. }
  3348. HTTP2State InChannelState; // used as virtual connection state while
  3349. // the channels are not fully established
  3350. HTTP2State OutChannelState;
  3351. ULONG ConnectionTimeout; // connection timeout from the runtime perspective
  3352. // (but in milliseconds)
  3353. ULONG CurrentKeepAlive; // the current keep alive value for the connection
  3354. ULONG ProtocolVersion;
  3355. ULONG InProxyConnectionTimeout; // the connection timeout from IIS channel
  3356. // perspective. Used only after transport open
  3357. HANDLE ClientOpenInEvent; // valid only during open. Destruction must be
  3358. // protected by the InChannelState
  3359. HANDLE ClientOpenOutEvent; // valid only during open. Destruction must be
  3360. // protected by the InChannelState
  3361. RPC_STATUS InOpenStatus; // valid only during open
  3362. RPC_STATUS OutOpenStatus; // valid only during open
  3363. HTTPResolverHint ConnectionHint;
  3364. BOOL ReissueRecv; // valid only during channel recycling
  3365. // When set, it means the old default channel was nuked
  3366. // and a new default channel is established. In this
  3367. // case the connection must reissue the recv after
  3368. // consuming this flag
  3369. INTERLOCKED_INTEGER BlockAbortsCounter; // If set, this means abort should block until
  3370. // cleared. The open path on the client sets this to prevent a bunch
  3371. // of pesky race conditions where worker threads abort
  3372. // the connection while it is trying to get opened.
  3373. // This is a counter that may be accessed from multiple threads
  3374. BOOL ChannelsAborted; // non-zero if the channels are aborted. This flag
  3375. // goes from 0 to non-zero, but never back.
  3376. RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials; // the transport
  3377. // credentials as kept by the runtime. These are the
  3378. // encrypted version.
  3379. };
  3380. extern BOOL g_fHttpClientInitialized;
  3381. extern BOOL g_fHttpServerInitialized;
  3382. RPC_STATUS InitializeHttpClient (
  3383. void
  3384. );
  3385. RPC_STATUS InitializeHttpServer (
  3386. void
  3387. );
  3388. inline RPC_STATUS InitializeHttpClientIfNecessary (
  3389. void
  3390. )
  3391. {
  3392. if (g_fHttpClientInitialized)
  3393. return RPC_S_OK;
  3394. else
  3395. return InitializeHttpClient();
  3396. }
  3397. inline RPC_STATUS InitializeHttpServerIfNecessary (
  3398. void
  3399. )
  3400. {
  3401. if (g_fHttpServerInitialized)
  3402. return RPC_S_OK;
  3403. else
  3404. return InitializeHttpServer();
  3405. }
  3406. const ULONG HTTP2DefaultClientReceiveWindow = 64 * 1024; // 64K for client
  3407. const ULONG HTTP2DefaultInProxyReceiveWindow = 64 * 1024; // 64K for in proxy
  3408. const ULONG HTTP2DefaultOutProxyReceiveWindow = 64 * 1024; // 64K for out proxy
  3409. const ULONG HTTP2DefaultServerReceiveWindow = 64 * 1024; // 64K for server
  3410. const USHORT HTTP2ProtocolVersion = 1;
  3411. const ULONG DefaultClientKeepAliveInterval = 5 * 60 * 1000; // 5 minutes in milliseconds
  3412. const ULONG DefaultClientNoResponseKeepAliveInterval = 5 * 1000; // 5 seconds in milliseconds
  3413. const ULONG MinimumClientKeepAliveInterval = 1 * 60 * 1000; // 1 minute in milliseconds
  3414. const ULONG MinimumClientNewKeepAliveInterval = 10 * 1000; // 10 seconds in milliseconds
  3415. const ULONG MinimumClientSideKeepAliveInterval = 30 * 1000; // 30 seconds in milliseconds
  3416. const ULONG MinimumChannelLifetime = 1024 * 128; // 128K
  3417. extern ULONG DefaultChannelLifetime; // 128K for now
  3418. extern char *DefaultChannelLifetimeString;
  3419. extern ULONG DefaultChannelLifetimeStringLength; // does not include null terminator
  3420. const ULONG DefaultNoResponseTimeout = 15 * 60 * 1000; // 15 minutes in milliseconds
  3421. class HTTP2ProxyServerSideChannel : public HTTP2Channel
  3422. {
  3423. public:
  3424. HTTP2ProxyServerSideChannel (
  3425. IN HTTP2VirtualConnection *ProxyVirtualConnection,
  3426. WS_HTTP2_CONNECTION *RawConnection,
  3427. OUT RPC_STATUS *RpcStatus
  3428. ) : HTTP2Channel(HTTP2Channel::ProxyChannelType, RpcStatus)
  3429. {
  3430. SetParent(ProxyVirtualConnection);
  3431. ASSERT(RawConnection);
  3432. this->RawConnection = RawConnection;
  3433. }
  3434. RPC_STATUS InitializeRawConnection (
  3435. IN RPC_CHAR *ServerName,
  3436. IN USHORT ServerPort,
  3437. IN ULONG ConnectionTimeout,
  3438. IN I_RpcProxyIsValidMachineFn IsValidMachineFn
  3439. );
  3440. private:
  3441. WS_HTTP2_CONNECTION *RawConnection;
  3442. };
  3443. // This is a wrapper around the timer handle used
  3444. // to track the handle and the connection that owns it.
  3445. struct TimerContext
  3446. {
  3447. // Each timer points to the connection so that we know which
  3448. // connection to notify during timeout callbacks.
  3449. class HTTP2TimeoutTargetConnection *Parent;
  3450. // A handle refers to the thread pool's timer.
  3451. // When Handle != NULL, timer is active. We set it
  3452. // to NULL when timer is inactive.
  3453. HANDLE Handle;
  3454. };
  3455. class HTTP2TimeoutTargetConnection : public HTTP2VirtualConnection
  3456. {
  3457. public:
  3458. HTTP2TimeoutTargetConnection (
  3459. void
  3460. )
  3461. {
  3462. InChannelTimer.Handle = NULL;
  3463. InChannelTimer.Parent = this;
  3464. OutChannelTimer.Handle = NULL;
  3465. OutChannelTimer.Parent = this;
  3466. }
  3467. ~HTTP2TimeoutTargetConnection (
  3468. void
  3469. )
  3470. {
  3471. // make sure no one destroys the object with pending time outs
  3472. ASSERT(InChannelTimer.Handle == NULL);
  3473. ASSERT(OutChannelTimer.Handle == NULL);
  3474. // Make sure the timers point to the connection object.
  3475. ASSERT(InChannelTimer.Parent == this);
  3476. ASSERT(OutChannelTimer.Parent == this);
  3477. }
  3478. RPC_STATUS SetTimeout (
  3479. IN ULONG Timeout,
  3480. IN TimerContext *pTimer
  3481. );
  3482. void CancelTimeout (
  3483. IN TimerContext *pTimer
  3484. );
  3485. inline void CancelAllTimeouts (
  3486. void
  3487. )
  3488. {
  3489. CancelTimeout(&InChannelTimer);
  3490. CancelTimeout(&OutChannelTimer);
  3491. }
  3492. inline TimerContext* GetInChannelTimer (
  3493. void
  3494. )
  3495. {
  3496. return &InChannelTimer;
  3497. }
  3498. inline TimerContext* GetOutChannelTimer (
  3499. void
  3500. )
  3501. {
  3502. return &OutChannelTimer;
  3503. }
  3504. virtual void TimeoutExpired (
  3505. IN TimerContext *pTimer
  3506. ) = 0;
  3507. protected:
  3508. inline void TimerExpiredNotify (
  3509. IN TimerContext *pTimer
  3510. )
  3511. {
  3512. pTimer->Handle = NULL;
  3513. }
  3514. inline void VerifyValidTimer (
  3515. IN TimerContext *pTimer
  3516. )
  3517. {
  3518. ASSERT(pTimer == &InChannelTimer
  3519. || pTimer == &OutChannelTimer);
  3520. }
  3521. inline void VerifyTimerNotSet (
  3522. IN TimerContext *pTimer
  3523. )
  3524. {
  3525. VerifyValidTimer(pTimer);
  3526. ASSERT(pTimer->Handle == NULL);
  3527. }
  3528. private:
  3529. TimerContext InChannelTimer;
  3530. TimerContext OutChannelTimer;
  3531. };
  3532. class HTTP2ProxyVirtualConnection : public HTTP2TimeoutTargetConnection
  3533. {
  3534. public:
  3535. HTTP2ProxyVirtualConnection (
  3536. OUT RPC_STATUS *RpcStatus
  3537. ) : State(RpcStatus),
  3538. RundownBlock(0)
  3539. {
  3540. IsConnectionInCollection = FALSE;
  3541. ConnectionParameter = NULL;
  3542. ServerName = NULL;
  3543. ProxyConnectionCookie = NULL;
  3544. }
  3545. ~HTTP2ProxyVirtualConnection (
  3546. void
  3547. )
  3548. {
  3549. if (ServerName)
  3550. {
  3551. delete [] ServerName;
  3552. ServerName = NULL;
  3553. }
  3554. }
  3555. virtual RPC_STATUS InitializeProxyFirstLeg (
  3556. IN USHORT *ServerAddress,
  3557. IN USHORT *ServerPort,
  3558. IN void *ConnectionParameter,
  3559. IN I_RpcProxyCallbackInterface *ProxyCallbackInterface,
  3560. OUT void **IISContext
  3561. ) = 0;
  3562. virtual RPC_STATUS StartProxy (
  3563. void
  3564. ) = 0;
  3565. virtual RPC_STATUS SendComplete (
  3566. IN RPC_STATUS EventStatus,
  3567. IN OUT HTTP2SendContext *SendContext,
  3568. IN int ChannelId
  3569. );
  3570. virtual void Abort (
  3571. void
  3572. );
  3573. virtual BOOL IsInProxy (
  3574. void
  3575. ) = 0;
  3576. virtual void EnableIISSessionClose (
  3577. void
  3578. ) = 0;
  3579. virtual void DisconnectChannels (
  3580. IN BOOL ExemptChannel,
  3581. IN int ExemptChannelId
  3582. );
  3583. RPC_STATUS AddConnectionToCookieCollection (
  3584. void
  3585. );
  3586. void RemoveConnectionFromCookieCollection (
  3587. void
  3588. );
  3589. inline void BlockConnectionFromRundown (
  3590. void
  3591. )
  3592. {
  3593. RundownBlock.Increment();
  3594. }
  3595. inline void UnblockConnectionFromRundown (
  3596. void
  3597. )
  3598. {
  3599. RundownBlock.Decrement();
  3600. }
  3601. virtual void TimeoutExpired (
  3602. IN TimerContext *pTimer
  3603. );
  3604. inline HTTP2ServerCookie *GetCookie (
  3605. void
  3606. )
  3607. {
  3608. return ProxyConnectionCookie;
  3609. }
  3610. RPC_STATUS ProxyForwardDataTrafficToDefaultChannel (
  3611. IN BOOL IsInChannel,
  3612. IN BYTE *Packet,
  3613. IN ULONG PacketLength,
  3614. IN ULONG ChannelId
  3615. );
  3616. protected:
  3617. inline int ConvertChannelIdToSendContextUserData (
  3618. IN int ChannelId
  3619. )
  3620. {
  3621. return (ChannelId & 0xFFFF);
  3622. }
  3623. inline HTTP2ChannelPointer *MapSendContextUserDataToChannelPtr (
  3624. IN int SendContextUserData
  3625. )
  3626. {
  3627. // check the in channels only
  3628. if (ConvertChannelIdToSendContextUserData(InChannelIds[0]) == SendContextUserData)
  3629. return &InChannels[0];
  3630. else if (ConvertChannelIdToSendContextUserData(InChannelIds[1]) == SendContextUserData)
  3631. return &InChannels[1];
  3632. else
  3633. return NULL;
  3634. }
  3635. HTTP2State State;
  3636. ULONG ConnectionTimeout;
  3637. ULONG ProtocolVersion;
  3638. I_RpcProxyCallbackInterface *ProxyCallbackInterface; // callback interface for proxy specific
  3639. // functions
  3640. RPC_CHAR *ServerName; // the server name. Valid until the out channel is opened.
  3641. USHORT ServerPort; // the server port. Valid for the lifetime of the connection
  3642. ULONG IISConnectionTimeout;
  3643. BOOL IsConnectionInCollection;
  3644. void *ConnectionParameter; // valid only between establishment header and first
  3645. // RTS packet
  3646. INTERLOCKED_INTEGER RundownBlock;
  3647. HTTP2ServerCookie *ProxyConnectionCookie; // proxies don't use the embedded connection
  3648. // cookie - they use this pointer. The reason is that multiple connections
  3649. // can use the same cookie when we act as web farm and we can't have
  3650. // the cookie embedded in any individual connection as this opens life
  3651. // time issues.
  3652. };
  3653. class HTTP2InProxyVirtualConnection;
  3654. class HTTP2InProxyInChannel : public HTTP2Channel
  3655. {
  3656. public:
  3657. HTTP2InProxyInChannel (
  3658. IN HTTP2InProxyVirtualConnection *InProxyVirtualConnection,
  3659. OUT RPC_STATUS *RpcStatus
  3660. ) : HTTP2Channel(HTTP2Channel::ProxyChannelType, RpcStatus)
  3661. {
  3662. SetParent((HTTP2VirtualConnection *)InProxyVirtualConnection);
  3663. }
  3664. inline void TransferReceiveStateToNewChannel (
  3665. OUT HTTP2InProxyInChannel *NewChannel
  3666. )
  3667. {
  3668. GetProxyReceiver()->TransferStateToNewReceiver (
  3669. NewChannel->GetProxyReceiver()
  3670. );
  3671. }
  3672. virtual RPC_STATUS ForwardFlowControlAck (
  3673. IN ULONG BytesReceivedForAck,
  3674. IN ULONG WindowForAck
  3675. );
  3676. inline void BytesConsumedNotification (
  3677. IN ULONG Bytes,
  3678. IN BOOL OwnsMutex,
  3679. OUT BOOL *IssueAck,
  3680. OUT ULONG *BytesReceivedForAck,
  3681. OUT ULONG *WindowForAck
  3682. )
  3683. {
  3684. GetProxyReceiver()->BytesConsumedNotification (Bytes,
  3685. OwnsMutex,
  3686. IssueAck,
  3687. BytesReceivedForAck,
  3688. WindowForAck
  3689. );
  3690. }
  3691. inline void EnableIISSessionClose (
  3692. void
  3693. )
  3694. {
  3695. GetIISTransportChannel()->EnableIISSessionClose();
  3696. }
  3697. protected:
  3698. inline HTTP2ProxyReceiver *GetProxyReceiver (
  3699. void
  3700. )
  3701. {
  3702. BYTE *ThisChannelPtr = (BYTE *)this;
  3703. ThisChannelPtr += SIZE_OF_OBJECT_AND_PADDING(HTTP2InProxyInChannel);
  3704. return (HTTP2ProxyReceiver *)ThisChannelPtr;
  3705. }
  3706. inline HTTP2IISTransportChannel *GetIISTransportChannel (
  3707. void
  3708. )
  3709. {
  3710. BYTE *ThisChannelPtr = (BYTE *)this;
  3711. ThisChannelPtr += SIZE_OF_OBJECT_AND_PADDING(HTTP2InProxyInChannel)
  3712. + SIZE_OF_OBJECT_AND_PADDING(HTTP2ProxyReceiver)
  3713. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PingReceiver)
  3714. ;
  3715. return (HTTP2IISTransportChannel *)ThisChannelPtr;
  3716. }
  3717. };
  3718. class HTTP2InProxyOutChannel : public HTTP2ProxyServerSideChannel
  3719. {
  3720. public:
  3721. HTTP2InProxyOutChannel (
  3722. IN HTTP2InProxyVirtualConnection *InProxyVirtualConnection,
  3723. IN WS_HTTP2_CONNECTION *RawConnection,
  3724. OUT RPC_STATUS *RpcStatus
  3725. ) : HTTP2ProxyServerSideChannel((HTTP2VirtualConnection *)InProxyVirtualConnection,
  3726. RawConnection,
  3727. RpcStatus)
  3728. {
  3729. }
  3730. virtual RPC_STATUS LastPacketSentNotification (
  3731. IN HTTP2SendContext *LastSendContext
  3732. );
  3733. inline RPC_STATUS Unplug (
  3734. void
  3735. )
  3736. {
  3737. return GetPlugChannel()->Unplug();
  3738. }
  3739. RPC_STATUS SetRawConnectionKeepAlive (
  3740. IN ULONG KeepAliveInterval // in milliseconds
  3741. );
  3742. inline RPC_STATUS FlowControlAckNotify (
  3743. IN ULONG BytesReceivedForAck,
  3744. IN ULONG WindowForAck
  3745. )
  3746. {
  3747. RPC_STATUS RpcStatus;
  3748. // Need to synchronize with aborts (rule 9).
  3749. RpcStatus = BeginSimpleSubmitAsync();
  3750. if (RpcStatus == RPC_S_OK)
  3751. {
  3752. RpcStatus = GetFlowControlSenderChannel()->FlowControlAckNotify(BytesReceivedForAck,
  3753. WindowForAck
  3754. );
  3755. FinishSubmitAsync();
  3756. }
  3757. return RpcStatus;
  3758. }
  3759. inline void SetPeerReceiveWindow (
  3760. IN ULONG PeerReceiveWindow
  3761. )
  3762. {
  3763. GetFlowControlSenderChannel()->SetPeerReceiveWindow (
  3764. PeerReceiveWindow
  3765. );
  3766. }
  3767. inline ULONG GetPeerReceiveWindow (
  3768. void
  3769. )
  3770. {
  3771. return GetFlowControlSenderChannel()->GetPeerReceiveWindow ();
  3772. }
  3773. protected:
  3774. inline WS_HTTP2_CONNECTION *GetRawConnection (
  3775. void
  3776. )
  3777. {
  3778. BYTE *ThisChannelPtr = (BYTE *)this;
  3779. ThisChannelPtr += SIZE_OF_OBJECT_AND_PADDING(HTTP2InProxyOutChannel)
  3780. + SIZE_OF_OBJECT_AND_PADDING(HTTP2ProxyPlugChannel)
  3781. + SIZE_OF_OBJECT_AND_PADDING(HTTP2FlowControlSender)
  3782. + SIZE_OF_OBJECT_AND_PADDING(HTTP2ProxySocketTransportChannel)
  3783. ;
  3784. return (WS_HTTP2_CONNECTION *)ThisChannelPtr;
  3785. }
  3786. inline HTTP2FlowControlSender *GetFlowControlSenderChannel (
  3787. void
  3788. )
  3789. {
  3790. BYTE *ThisChannelPtr = (BYTE *)this;
  3791. ThisChannelPtr += SIZE_OF_OBJECT_AND_PADDING(HTTP2InProxyOutChannel)
  3792. + SIZE_OF_OBJECT_AND_PADDING(HTTP2ProxyPlugChannel)
  3793. ;
  3794. return (HTTP2FlowControlSender *)ThisChannelPtr;
  3795. }
  3796. inline HTTP2PlugChannel *GetPlugChannel (
  3797. void
  3798. )
  3799. {
  3800. BYTE *ThisChannelPtr = (BYTE *)this;
  3801. ThisChannelPtr += SIZE_OF_OBJECT_AND_PADDING(HTTP2InProxyOutChannel);
  3802. return (HTTP2PlugChannel *)ThisChannelPtr;
  3803. }
  3804. };
  3805. class HTTP2InProxyVirtualConnection : public HTTP2ProxyVirtualConnection
  3806. {
  3807. public:
  3808. HTTP2InProxyVirtualConnection (
  3809. OUT RPC_STATUS *RpcStatus
  3810. ) : HTTP2ProxyVirtualConnection(RpcStatus)
  3811. {
  3812. ConnectionTimeout = 0;
  3813. RpcpMemorySet(&ClientAddress, 0, sizeof(ClientAddress));
  3814. }
  3815. virtual RPC_STATUS InitializeProxyFirstLeg (
  3816. IN USHORT *ServerAddress,
  3817. IN USHORT *ServerPort,
  3818. IN void *ConnectionParameter,
  3819. IN I_RpcProxyCallbackInterface *ProxyCallbackInterface,
  3820. OUT void **IISContext
  3821. );
  3822. virtual RPC_STATUS StartProxy (
  3823. void
  3824. );
  3825. RPC_STATUS InitializeProxySecondLeg (
  3826. void
  3827. );
  3828. virtual RPC_STATUS ReceiveComplete (
  3829. IN RPC_STATUS EventStatus,
  3830. IN BYTE *Buffer,
  3831. IN UINT BufferLength,
  3832. IN int ChannelId
  3833. );
  3834. virtual BOOL IsInProxy (
  3835. void
  3836. )
  3837. {
  3838. return TRUE;
  3839. }
  3840. virtual void EnableIISSessionClose (
  3841. void
  3842. );
  3843. virtual void DisconnectChannels (
  3844. IN BOOL ExemptChannel,
  3845. IN int ExemptChannelId
  3846. );
  3847. inline HTTP2InProxyInChannel *LockDefaultInChannel (
  3848. OUT HTTP2ChannelPointer **ChannelPointer
  3849. )
  3850. {
  3851. return (HTTP2InProxyInChannel *)HTTP2VirtualConnection::LockDefaultInChannel(ChannelPointer);
  3852. }
  3853. inline HTTP2InProxyOutChannel *LockDefaultOutChannel (
  3854. OUT HTTP2ChannelPointer **ChannelPointer
  3855. )
  3856. {
  3857. return (HTTP2InProxyOutChannel *)HTTP2VirtualConnection::LockDefaultOutChannel(ChannelPointer);
  3858. }
  3859. private:
  3860. RPC_STATUS AllocateAndInitializeInChannel (
  3861. IN void *ConnectionParameter,
  3862. OUT HTTP2InProxyInChannel **ReturnInChannel,
  3863. OUT void **IISContext
  3864. );
  3865. RPC_STATUS AllocateAndInitializeOutChannel (
  3866. OUT HTTP2InProxyOutChannel **ReturnOutChannel
  3867. );
  3868. RPC_STATUS ConnectToServer (
  3869. void
  3870. );
  3871. RPC_STATUS SendD1_B2ToServer (
  3872. void
  3873. );
  3874. RPC_STATUS SendD2_A2ToServer (
  3875. void
  3876. );
  3877. ULONG ChannelLifetime;
  3878. ULONG CurrentClientKeepAliveInterval;
  3879. ULONG DefaultClientKeepAliveInterval;
  3880. ChannelSettingClientAddress ClientAddress; // needed only while processing D1/B1
  3881. HTTP2Cookie AssociationGroupId; // needed only while processing D1/B1
  3882. QUEUE NonDefaultChannelBufferQueue; // used only in Opened_A5W state
  3883. };
  3884. class HTTP2OutProxyVirtualConnection;
  3885. class HTTP2OutProxyInChannel : public HTTP2ProxyServerSideChannel
  3886. {
  3887. public:
  3888. HTTP2OutProxyInChannel (
  3889. IN HTTP2OutProxyVirtualConnection *OutProxyVirtualConnection,
  3890. WS_HTTP2_CONNECTION *RawConnection,
  3891. OUT RPC_STATUS *RpcStatus
  3892. ) : HTTP2ProxyServerSideChannel((HTTP2VirtualConnection *)OutProxyVirtualConnection,
  3893. RawConnection,
  3894. RpcStatus)
  3895. {
  3896. }
  3897. virtual RPC_STATUS ForwardFlowControlAck (
  3898. IN ULONG BytesReceivedForAck,
  3899. IN ULONG WindowForAck
  3900. );
  3901. inline void BytesConsumedNotification (
  3902. IN ULONG Bytes,
  3903. IN BOOL OwnsMutex,
  3904. OUT BOOL *IssueAck,
  3905. OUT ULONG *BytesReceivedForAck,
  3906. OUT ULONG *WindowForAck
  3907. )
  3908. {
  3909. GetProxyReceiver()->BytesConsumedNotification (Bytes,
  3910. OwnsMutex,
  3911. IssueAck,
  3912. BytesReceivedForAck,
  3913. WindowForAck
  3914. );
  3915. }
  3916. protected:
  3917. inline HTTP2ProxyReceiver *GetProxyReceiver (
  3918. void
  3919. )
  3920. {
  3921. BYTE *ThisChannelPtr = (BYTE *)this;
  3922. ThisChannelPtr += SIZE_OF_OBJECT_AND_PADDING(HTTP2OutProxyInChannel);
  3923. return (HTTP2ProxyReceiver *)ThisChannelPtr;
  3924. }
  3925. };
  3926. // at the current size of the ping packet, this is 43 ping packets
  3927. const ULONG AccumulatedPingTrafficNotifyThreshold = 1032;
  3928. class HTTP2OutProxyOutChannel : public HTTP2Channel
  3929. {
  3930. public:
  3931. HTTP2OutProxyOutChannel (
  3932. IN HTTP2OutProxyVirtualConnection *OutProxyVirtualConnection,
  3933. OUT RPC_STATUS *RpcStatus
  3934. ) : HTTP2Channel(HTTP2Channel::ProxyChannelType, RpcStatus)
  3935. {
  3936. SetParent((HTTP2VirtualConnection *)OutProxyVirtualConnection);
  3937. AccumulatedPingTraffic = 0;
  3938. }
  3939. virtual RPC_STATUS LastPacketSentNotification (
  3940. IN HTTP2SendContext *LastSendContext
  3941. );
  3942. inline RPC_STATUS Unplug (
  3943. void
  3944. )
  3945. {
  3946. HTTP2PlugChannel *PlugChannel;
  3947. PlugChannel = GetPlugChannel();
  3948. return PlugChannel->Unplug();
  3949. }
  3950. inline void SetStrongPlug (
  3951. void
  3952. )
  3953. {
  3954. HTTP2PlugChannel *PlugChannel;
  3955. PlugChannel = GetPlugChannel();
  3956. return PlugChannel->SetStrongPlug();
  3957. }
  3958. virtual void PingTrafficSentNotify (
  3959. IN ULONG PingTrafficSize
  3960. );
  3961. BOOL PingTrafficSentNotifyServer (
  3962. IN ULONG PingTrafficSize
  3963. );
  3964. inline RPC_STATUS SetConnectionTimeout (
  3965. IN ULONG ConnectionTimeout
  3966. )
  3967. {
  3968. return GetPingOriginatorChannel()->SetConnectionTimeout(ConnectionTimeout);
  3969. }
  3970. inline RPC_STATUS FlowControlAckNotify (
  3971. IN ULONG BytesReceivedForAck,
  3972. IN ULONG WindowForAck
  3973. )
  3974. {
  3975. return GetFlowControlSenderChannel()->FlowControlAckNotify(BytesReceivedForAck,
  3976. WindowForAck
  3977. );
  3978. }
  3979. inline void SetPeerReceiveWindow (
  3980. IN ULONG PeerReceiveWindow
  3981. )
  3982. {
  3983. GetFlowControlSenderChannel()->SetPeerReceiveWindow (
  3984. PeerReceiveWindow
  3985. );
  3986. }
  3987. inline ULONG GetPeerReceiveWindow (
  3988. void
  3989. )
  3990. {
  3991. return GetFlowControlSenderChannel()->GetPeerReceiveWindow ();
  3992. }
  3993. inline void GetFlowControlSenderBufferQueue (
  3994. OUT LIST_ENTRY *NewBufferHead
  3995. )
  3996. {
  3997. GetFlowControlSenderChannel()->GetBufferQueue(NewBufferHead);
  3998. }
  3999. inline void EnableIISSessionClose (
  4000. void
  4001. )
  4002. {
  4003. GetIISTransportChannel()->EnableIISSessionClose();
  4004. }
  4005. private:
  4006. inline HTTP2PlugChannel *GetPlugChannel (
  4007. void
  4008. )
  4009. {
  4010. BYTE *Channel = (BYTE *)this;
  4011. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2OutProxyOutChannel);
  4012. return (HTTP2PlugChannel *)Channel;
  4013. }
  4014. inline HTTP2PingOriginator *GetPingOriginatorChannel (
  4015. void
  4016. )
  4017. {
  4018. BYTE *Channel = (BYTE *)this;
  4019. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2OutProxyOutChannel)
  4020. + SIZE_OF_OBJECT_AND_PADDING(HTTP2ProxyPlugChannel)
  4021. + SIZE_OF_OBJECT_AND_PADDING(HTTP2FlowControlSender)
  4022. ;
  4023. return (HTTP2PingOriginator *)Channel;
  4024. }
  4025. inline HTTP2FlowControlSender *GetFlowControlSenderChannel (
  4026. void
  4027. )
  4028. {
  4029. BYTE *Channel = (BYTE *)this;
  4030. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2OutProxyOutChannel)
  4031. + SIZE_OF_OBJECT_AND_PADDING(HTTP2ProxyPlugChannel)
  4032. ;
  4033. return (HTTP2FlowControlSender *)Channel;
  4034. }
  4035. inline HTTP2IISTransportChannel *GetIISTransportChannel (
  4036. void
  4037. )
  4038. {
  4039. BYTE *ThisChannelPtr = (BYTE *)this;
  4040. ThisChannelPtr += SIZE_OF_OBJECT_AND_PADDING(HTTP2OutProxyOutChannel)
  4041. + SIZE_OF_OBJECT_AND_PADDING(HTTP2ProxyPlugChannel)
  4042. + SIZE_OF_OBJECT_AND_PADDING(HTTP2FlowControlSender)
  4043. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PingOriginator)
  4044. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PingReceiver)
  4045. ;
  4046. return (HTTP2IISTransportChannel *)ThisChannelPtr;
  4047. }
  4048. ULONG AccumulatedPingTraffic;
  4049. };
  4050. extern ULONG HTTP2OutProxyReceiveWindow;
  4051. typedef enum tagOutProxyLastPacketType
  4052. {
  4053. oplptInvalid = 0,
  4054. oplptD4_A10,
  4055. oplptD5_B3
  4056. } OutProxyLastPacketType;
  4057. class HTTP2OutProxyVirtualConnection : public HTTP2ProxyVirtualConnection
  4058. {
  4059. public:
  4060. HTTP2OutProxyVirtualConnection (
  4061. OUT RPC_STATUS *RpcStatus
  4062. ) : HTTP2ProxyVirtualConnection(RpcStatus)
  4063. {
  4064. ConnectionTimeout = 0;
  4065. ProxyReceiveWindowSize = HTTP2OutProxyReceiveWindow;
  4066. }
  4067. virtual RPC_STATUS InitializeProxyFirstLeg (
  4068. IN USHORT *ServerAddress,
  4069. IN USHORT *ServerPort,
  4070. IN void *ConnectionParameter,
  4071. IN I_RpcProxyCallbackInterface *ProxyCallbackInterface,
  4072. OUT void **IISContext
  4073. );
  4074. virtual RPC_STATUS StartProxy (
  4075. void
  4076. );
  4077. RPC_STATUS InitializeProxySecondLeg (
  4078. void
  4079. );
  4080. virtual RPC_STATUS ReceiveComplete (
  4081. IN RPC_STATUS EventStatus,
  4082. IN BYTE *Buffer,
  4083. IN UINT BufferLength,
  4084. IN int ChannelId
  4085. );
  4086. virtual BOOL IsInProxy (
  4087. void
  4088. )
  4089. {
  4090. return FALSE;
  4091. }
  4092. virtual void EnableIISSessionClose (
  4093. void
  4094. );
  4095. BOOL PingTrafficSentNotifyServer (
  4096. IN ULONG PingTrafficSize
  4097. );
  4098. inline HTTP2OutProxyInChannel *LockDefaultInChannel (
  4099. OUT HTTP2ChannelPointer **ChannelPointer
  4100. )
  4101. {
  4102. return (HTTP2OutProxyInChannel *)HTTP2VirtualConnection::LockDefaultInChannel(ChannelPointer);
  4103. }
  4104. inline HTTP2OutProxyOutChannel *LockDefaultOutChannel (
  4105. OUT HTTP2ChannelPointer **ChannelPointer
  4106. )
  4107. {
  4108. return (HTTP2OutProxyOutChannel *)HTTP2VirtualConnection::LockDefaultOutChannel(ChannelPointer);
  4109. }
  4110. virtual void LastPacketSentNotification (
  4111. IN int ChannelId,
  4112. IN HTTP2SendContext *LastSendContext
  4113. );
  4114. private:
  4115. RPC_STATUS ConnectToServer (
  4116. );
  4117. RPC_STATUS SendHeaderToClient (
  4118. void
  4119. );
  4120. RPC_STATUS SendD1_A3ToClient (
  4121. void
  4122. );
  4123. RPC_STATUS SendD1_A2ToServer (
  4124. IN ULONG ChannelLifetime
  4125. );
  4126. RPC_STATUS SendD4_A4ToServer (
  4127. IN ULONG ChannelLifetime
  4128. );
  4129. RPC_STATUS AllocateAndInitializeInChannel (
  4130. OUT HTTP2OutProxyInChannel **ReturnOutChannel
  4131. );
  4132. RPC_STATUS AllocateAndInitializeOutChannel (
  4133. IN void *ConnectionParameter,
  4134. OUT HTTP2OutProxyOutChannel **ReturnInChannel,
  4135. OUT void **IISContext
  4136. );
  4137. ULONG ProxyReceiveWindowSize;
  4138. };
  4139. class HTTP2ServerVirtualConnection; // forward
  4140. class HTTP2ServerChannel : public HTTP2Channel
  4141. {
  4142. public:
  4143. HTTP2ServerChannel (
  4144. OUT RPC_STATUS *Status
  4145. ) : HTTP2Channel (0, // InitialFlag
  4146. Status)
  4147. {
  4148. }
  4149. HTTP2ServerVirtualConnection *LockParentPointer (
  4150. void
  4151. )
  4152. {
  4153. return (HTTP2ServerVirtualConnection *)HTTP2Channel::LockParentPointer();
  4154. }
  4155. virtual void AbortConnection (
  4156. IN RPC_STATUS AbortReason
  4157. );
  4158. };
  4159. class HTTP2ServerInChannel : public HTTP2ServerChannel
  4160. {
  4161. public:
  4162. HTTP2ServerInChannel (
  4163. OUT RPC_STATUS *RpcStatus
  4164. ) : HTTP2ServerChannel (RpcStatus)
  4165. {
  4166. }
  4167. RPC_STATUS QueryLocalAddress (
  4168. IN OUT void *Buffer,
  4169. IN OUT unsigned long *BufferSize,
  4170. OUT unsigned long *AddressFormat
  4171. );
  4172. virtual RPC_STATUS ForwardFlowControlAck (
  4173. IN ULONG BytesReceivedForAck,
  4174. IN ULONG WindowForAck
  4175. );
  4176. inline BOOL IsDataReceivePosted (
  4177. void
  4178. )
  4179. {
  4180. return GetEndpointReceiver()->IsDataReceivePosted();
  4181. }
  4182. inline RPC_STATUS TransferReceiveStateToNewChannel (
  4183. OUT HTTP2ServerInChannel *NewChannel
  4184. )
  4185. {
  4186. return GetEndpointReceiver()->TransferStateToNewReceiver (
  4187. NewChannel->GetEndpointReceiver()
  4188. );
  4189. }
  4190. protected:
  4191. inline WS_HTTP2_CONNECTION *GetRawConnection (
  4192. void
  4193. )
  4194. {
  4195. BYTE *ThisChannelPtr = (BYTE *)this;
  4196. ThisChannelPtr += SIZE_OF_OBJECT_AND_PADDING(HTTP2ServerInChannel)
  4197. + SIZE_OF_OBJECT_AND_PADDING(HTTP2EndpointReceiver)
  4198. + SIZE_OF_OBJECT_AND_PADDING(HTTP2SocketTransportChannel);
  4199. return (WS_HTTP2_CONNECTION *)ThisChannelPtr;
  4200. }
  4201. inline HTTP2EndpointReceiver *GetEndpointReceiver (
  4202. void
  4203. )
  4204. {
  4205. BYTE *ThisChannelPtr = (BYTE *)this;
  4206. ThisChannelPtr += SIZE_OF_OBJECT_AND_PADDING(HTTP2ServerInChannel);
  4207. return (HTTP2EndpointReceiver *)ThisChannelPtr;
  4208. }
  4209. };
  4210. class HTTP2ServerOutChannel : public HTTP2ServerChannel
  4211. {
  4212. public:
  4213. HTTP2ServerOutChannel (
  4214. OUT RPC_STATUS *RpcStatus
  4215. ) : HTTP2ServerChannel (RpcStatus),
  4216. DataSendsPending (0)
  4217. {
  4218. PingOriginator = NULL;
  4219. CachedLastSendContextUsed = FALSE;
  4220. }
  4221. virtual RPC_STATUS Send (
  4222. IN OUT HTTP2SendContext *SendContext
  4223. );
  4224. virtual RPC_STATUS SendComplete (
  4225. IN RPC_STATUS EventStatus,
  4226. IN OUT HTTP2SendContext *SendContext
  4227. );
  4228. void HTTP2ServerOutChannel::SendCancelled (
  4229. IN HTTP2SendContext *SendContext
  4230. );
  4231. virtual RPC_STATUS SyncSend (
  4232. IN HTTP2TrafficType TrafficType,
  4233. IN ULONG BufferLength,
  4234. IN BYTE *Buffer,
  4235. IN BOOL fDisableCancelCheck,
  4236. IN ULONG Timeout,
  4237. IN BASE_ASYNC_OBJECT *Connection,
  4238. IN HTTP2SendContext *SendContext
  4239. );
  4240. virtual RPC_STATUS SetKeepAliveTimeout (
  4241. IN BOOL TurnOn,
  4242. IN BOOL bProtectIO,
  4243. IN KEEPALIVE_TIMEOUT_UNITS Units,
  4244. IN OUT KEEPALIVE_TIMEOUT KATime,
  4245. IN ULONG KAInterval = 5000 OPTIONAL
  4246. );
  4247. virtual RPC_STATUS LastPacketSentNotification (
  4248. IN HTTP2SendContext *LastSendContext
  4249. );
  4250. inline RPC_STATUS Unplug (
  4251. void
  4252. )
  4253. {
  4254. HTTP2PlugChannel *PlugChannel;
  4255. PlugChannel = GetPlugChannel();
  4256. return PlugChannel->Unplug();
  4257. }
  4258. RPC_STATUS GetChannelOriginatorBufferQueue (
  4259. OUT LIST_ENTRY *NewBufferHead
  4260. );
  4261. inline void PlugDataOriginatorChannel (
  4262. void
  4263. )
  4264. {
  4265. GetDataOriginatorChannel()->PlugChannel();
  4266. }
  4267. inline RPC_STATUS RestartDataOriginatorChannel (
  4268. void
  4269. )
  4270. {
  4271. return GetDataOriginatorChannel()->RestartChannel();
  4272. }
  4273. inline RPC_STATUS NotifyDataOriginatorForTrafficSent (
  4274. IN ULONG TrafficSentSize
  4275. )
  4276. {
  4277. return GetDataOriginatorChannel()->NotifyTrafficSent(TrafficSentSize);
  4278. }
  4279. inline RPC_STATUS FlowControlAckNotify (
  4280. IN ULONG BytesReceivedForAck,
  4281. IN ULONG WindowForAck
  4282. )
  4283. {
  4284. return GetFlowControlSenderChannel()->FlowControlAckNotify(BytesReceivedForAck,
  4285. WindowForAck
  4286. );
  4287. }
  4288. inline void SetPeerReceiveWindow (
  4289. IN ULONG PeerReceiveWindow
  4290. )
  4291. {
  4292. GetFlowControlSenderChannel()->SetPeerReceiveWindow (
  4293. PeerReceiveWindow
  4294. );
  4295. }
  4296. inline ULONG GetPeerReceiveWindow (
  4297. void
  4298. )
  4299. {
  4300. return GetFlowControlSenderChannel()->GetPeerReceiveWindow ();
  4301. }
  4302. RPC_STATUS GetFlowControlSenderBufferQueue (
  4303. OUT LIST_ENTRY *NewBufferHead
  4304. );
  4305. HTTP2SendContext *GetLastSendContext (
  4306. void
  4307. );
  4308. inline void FreeLastSendContext (
  4309. IN HTTP2SendContext *SendContext
  4310. )
  4311. {
  4312. if (SendContext == GetCachedLastSendContext())
  4313. CachedLastSendContextUsed = FALSE;
  4314. else
  4315. delete SendContext;
  4316. }
  4317. inline void DrainPendingSends (
  4318. void
  4319. )
  4320. {
  4321. #if DBG
  4322. int Retries = 0;
  4323. #endif
  4324. while (DataSendsPending.GetInteger() > 0)
  4325. {
  4326. #if DBG
  4327. Retries ++;
  4328. if (Retries > 100000)
  4329. {
  4330. ASSERT(!"Cannot drain pending sends on channel");
  4331. Retries = 0;
  4332. }
  4333. #endif
  4334. Sleep(2);
  4335. }
  4336. }
  4337. private:
  4338. inline HTTP2PlugChannel *GetPlugChannel (
  4339. void
  4340. )
  4341. {
  4342. BYTE *Channel = (BYTE *)this;
  4343. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2ServerOutChannel);
  4344. return (HTTP2PlugChannel *)Channel;
  4345. }
  4346. inline HTTP2ChannelDataOriginator *GetDataOriginatorChannel (
  4347. void
  4348. )
  4349. {
  4350. BYTE *Channel = (BYTE *)this;
  4351. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2ServerOutChannel)
  4352. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PlugChannel)
  4353. + SIZE_OF_OBJECT_AND_PADDING(HTTP2FlowControlSender)
  4354. ;
  4355. return (HTTP2ChannelDataOriginator *)Channel;
  4356. }
  4357. inline HTTP2FlowControlSender *GetFlowControlSenderChannel (
  4358. void
  4359. )
  4360. {
  4361. BYTE *Channel = (BYTE *)this;
  4362. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2ServerOutChannel)
  4363. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PlugChannel)
  4364. ;
  4365. return (HTTP2FlowControlSender *)Channel;
  4366. }
  4367. inline HTTP2SendContext *GetCachedLastSendContext (
  4368. void
  4369. )
  4370. {
  4371. BYTE *Channel = (BYTE *)this;
  4372. Channel += SIZE_OF_OBJECT_AND_PADDING(HTTP2ServerOutChannel)
  4373. + SIZE_OF_OBJECT_AND_PADDING(HTTP2PlugChannel)
  4374. + SIZE_OF_OBJECT_AND_PADDING(HTTP2FlowControlSender)
  4375. + SIZE_OF_OBJECT_AND_PADDING(HTTP2ChannelDataOriginator)
  4376. + SIZE_OF_OBJECT_AND_PADDING(HTTP2SocketTransportChannel)
  4377. + SIZE_OF_OBJECT_AND_PADDING(WS_HTTP2_CONNECTION)
  4378. ;
  4379. return (HTTP2SendContext *)Channel;
  4380. }
  4381. RPC_STATUS UnaffinitizeSendContextList (
  4382. IN LIST_ENTRY *ListHead
  4383. );
  4384. HTTP2PingOriginator *PingOriginator;
  4385. BOOL CachedLastSendContextUsed; // non-zero if the cached last send context is
  4386. // currently used.
  4387. INTERLOCKED_INTEGER DataSendsPending;
  4388. };
  4389. const ULONG BytesSentByProxyTimeInterval = 4 * 60 * 1000; // 4 minutes in millisecons
  4390. const ULONG MaxBytesSentByProxy = 8 * 1024; // 8K is the maximum we allow the proxy per unit of time
  4391. typedef struct tagHTTP2OutProxyTransportSettings
  4392. {
  4393. ULONG ReceiveWindow;
  4394. ULONG ChannelLifetime;
  4395. } HTTP2OutProxyTransportSettings;
  4396. class HTTP2ServerVirtualConnection : public HTTP2TimeoutTargetConnection
  4397. {
  4398. public:
  4399. HTTP2ServerVirtualConnection (
  4400. IN HTTP2ServerCookie *NewCookie,
  4401. IN ULONG ProtocolVersion,
  4402. OUT RPC_STATUS *RpcStatus
  4403. ) : InChannelState(RpcStatus),
  4404. OutChannelState(RpcStatus)
  4405. {
  4406. InProxyReceiveWindows[0] = 0;
  4407. InProxyReceiveWindows[1] = 0;
  4408. OutProxySettings[0].ReceiveWindow = 0;
  4409. OutProxySettings[0].ChannelLifetime = 0;
  4410. OutProxySettings[1].ReceiveWindow = 0;
  4411. OutProxySettings[1].ChannelLifetime = 0;
  4412. InProxyConnectionTimeout = 0;
  4413. this->ProtocolVersion = ProtocolVersion;
  4414. InChannelState.State = http2svClosed;
  4415. RpcpMemorySet(&ClientAddress, 0, sizeof(ClientAddress));
  4416. EmbeddedConnectionCookie.SetConnection(this);
  4417. EmbeddedConnectionCookie.SetCookie(NewCookie->GetCookie());
  4418. BytesSentByProxyForInterval = 0;
  4419. BytesSentByProxyTimeIntervalStart = 0;
  4420. LastBufferToFree = NULL;
  4421. }
  4422. virtual RPC_STATUS SendComplete (
  4423. IN RPC_STATUS EventStatus,
  4424. IN OUT HTTP2SendContext *SendContext,
  4425. IN int ChannelId
  4426. );
  4427. virtual RPC_STATUS ReceiveComplete (
  4428. IN RPC_STATUS EventStatus,
  4429. IN BYTE *Buffer,
  4430. IN UINT BufferLength,
  4431. IN int ChannelId
  4432. );
  4433. virtual RPC_STATUS SyncSend (
  4434. IN ULONG BufferLength,
  4435. IN BYTE *Buffer,
  4436. IN BOOL fDisableShutdownCheck,
  4437. IN BOOL fDisableCancelCheck,
  4438. IN ULONG Timeout
  4439. );
  4440. virtual void Abort (
  4441. void
  4442. );
  4443. virtual void Close (
  4444. IN BOOL DontFlush
  4445. );
  4446. virtual RPC_STATUS QueryClientAddress (
  4447. OUT RPC_CHAR **pNetworkAddress
  4448. );
  4449. virtual RPC_STATUS QueryLocalAddress (
  4450. IN OUT void *Buffer,
  4451. IN OUT unsigned long *BufferSize,
  4452. OUT unsigned long *AddressFormat
  4453. );
  4454. virtual RPC_STATUS QueryClientId(
  4455. OUT RPC_CLIENT_PROCESS_IDENTIFIER *ClientProcess
  4456. );
  4457. virtual RPC_STATUS QueryClientIpAddress (
  4458. IN OUT RPC_CLIENT_IP_ADDRESS *ClientIpAddress
  4459. );
  4460. virtual void LastPacketSentNotification (
  4461. IN int ChannelId,
  4462. IN HTTP2SendContext *LastSendContext
  4463. );
  4464. virtual RPC_STATUS RecycleChannel (
  4465. IN BOOL IsFromUpcall
  4466. );
  4467. // must initialize the type member and migrate the
  4468. // WS_HTTP2_INITIAL_CONNECTION after morphing it into
  4469. // WS_HTTP2_CONNECTION
  4470. static RPC_STATUS InitializeServerConnection (
  4471. IN BYTE *Packet,
  4472. IN ULONG PacketLength,
  4473. IN WS_HTTP2_INITIAL_CONNECTION *Connection,
  4474. OUT HTTP2ServerVirtualConnection **ServerVirtualConnection,
  4475. OUT BOOL *VirtualConnectionCreated
  4476. );
  4477. static RPC_STATUS AllocateAndInitializeInChannel (
  4478. IN OUT WS_HTTP2_INITIAL_CONNECTION **Connection,
  4479. OUT HTTP2ServerInChannel **ReturnInChannel
  4480. );
  4481. static RPC_STATUS AllocateAndInitializeOutChannel (
  4482. IN OUT WS_HTTP2_INITIAL_CONNECTION **Connection,
  4483. IN ULONG OutChannelLifetime,
  4484. OUT HTTP2ServerOutChannel **ReturnOutChannel
  4485. );
  4486. inline HTTP2ServerInChannel *LockDefaultInChannel (
  4487. OUT HTTP2ChannelPointer **ChannelPointer
  4488. )
  4489. {
  4490. return (HTTP2ServerInChannel *)HTTP2VirtualConnection::LockDefaultInChannel(ChannelPointer);
  4491. }
  4492. inline HTTP2ServerOutChannel *LockDefaultOutChannel (
  4493. OUT HTTP2ChannelPointer **ChannelPointer
  4494. )
  4495. {
  4496. return (HTTP2ServerOutChannel *)HTTP2VirtualConnection::LockDefaultOutChannel(ChannelPointer);
  4497. }
  4498. virtual void TimeoutExpired (
  4499. IN TimerContext *pTimer
  4500. );
  4501. inline void SetLastBufferToFree (
  4502. IN void *NewLastBufferToFree
  4503. )
  4504. {
  4505. ASSERT(LastBufferToFree == NULL);
  4506. LastBufferToFree = NewLastBufferToFree;
  4507. }
  4508. inline BOOL IsLastBufferToFreeSet (
  4509. void
  4510. )
  4511. {
  4512. return (LastBufferToFree != NULL);
  4513. }
  4514. inline void *GetAndResetLastBufferToFree (
  4515. void
  4516. )
  4517. {
  4518. void *LocalLastBufferToFree;
  4519. ASSERT(LastBufferToFree != NULL);
  4520. LocalLastBufferToFree = LastBufferToFree;
  4521. LastBufferToFree = NULL;
  4522. return LocalLastBufferToFree;
  4523. }
  4524. private:
  4525. void DrainOutChannelPendingSends (
  4526. void
  4527. );
  4528. HTTP2State InChannelState; // used as virtual connection state while
  4529. // the channels are not fully established
  4530. HTTP2State OutChannelState;
  4531. ULONG ProtocolVersion;
  4532. // accessed through the default out channel selector
  4533. HTTP2OutProxyTransportSettings OutProxySettings[2];
  4534. ChannelSettingClientAddress ClientAddress;
  4535. ULONG InProxyConnectionTimeout; // valid b/n D1_B2 and D1_C1
  4536. // accessed through the default in channel selector
  4537. ULONG InProxyReceiveWindows[2];
  4538. HTTP2Cookie AssociationGroupId;
  4539. ULONG BytesSentByProxyForInterval; // the number of bytes sent by the proxy independently
  4540. // for the current time interval
  4541. ULONG BytesSentByProxyTimeIntervalStart; // the start of the current time interval
  4542. void *LastBufferToFree; // temporary storage for the last buffer to free
  4543. // Used b/n SetLastBufferToFree and the last send only.
  4544. // Must be freed using RpcFreeBuffer/I_RpcTransConnectionFreePacket
  4545. };
  4546. #endif // __HTTP2_HXX__