Source code of Windows XP (NT5)
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.

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