1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #pragma once
10 
11 #include <fizz/record/Types.h>
12 #include <folly/io/IOBuf.h>
13 #include <folly/io/async/AsyncUDPSocket.h>
14 #include <folly/io/async/SSLContext.h>
15 #include <proxygen/lib/http/codec/HTTPCodecFilter.h>
16 #include <proxygen/lib/http/session/HTTPSessionActivityTracker.h>
17 #include <proxygen/lib/http/session/HTTPTransaction.h>
18 #include <proxygen/lib/utils/Time.h>
19 #include <wangle/acceptor/ManagedConnection.h>
20 #include <wangle/acceptor/TransportInfo.h>
21 
22 namespace proxygen {
23 class HTTPSessionController;
24 class HTTPSessionStats;
25 class HTTPTransaction;
26 class ByteEventTracker;
27 
28 constexpr uint32_t kDefaultMaxConcurrentOutgoingStreams = 100;
29 
30 class HTTPPriorityMapFactoryProvider {
31  public:
32   virtual ~HTTPPriorityMapFactoryProvider() = default;
33   virtual HTTPCodec::StreamID sendPriority(http2::PriorityUpdate pri) = 0;
34 };
35 
36 class HTTPSessionBase : public wangle::ManagedConnection {
37  public:
38   /**
39    * Optional callback interface that the HTTPSessionBase
40    * notifies of connection lifecycle events.
41    */
42   class InfoCallback {
43    public:
~InfoCallback()44     virtual ~InfoCallback() {
45     }
46 
47     // Note: you must not start any asynchronous work from onCreate()
onCreate(const HTTPSessionBase &)48     virtual void onCreate(const HTTPSessionBase&) {
49     }
onTransportReady(const HTTPSessionBase &)50     virtual void onTransportReady(const HTTPSessionBase&) {
51     }
onConnectionError(const HTTPSessionBase &)52     virtual void onConnectionError(const HTTPSessionBase&) {
53     }
onFullHandshakeCompletion(const HTTPSessionBase &)54     virtual void onFullHandshakeCompletion(const HTTPSessionBase&) {
55     }
onIngressError(const HTTPSessionBase &,ProxygenError)56     virtual void onIngressError(const HTTPSessionBase&, ProxygenError) {
57     }
onIngressEOF()58     virtual void onIngressEOF() {
59     }
onRead(const HTTPSessionBase &,size_t)60     virtual void onRead(const HTTPSessionBase&, size_t /*bytesRead*/) {
61     }
62     /**
63      * New version of the API.  Includes the stream these bytes belong to,
64      * or HTTPCodec::NoStream if unknown.  bytesRead can be 0 if the stream
65      * ended.
66      *
67      * If onRead is currently implemented with the old signature (without stream
68      * ID), safest path is to keep it and change it to call onRead with the new
69      * signature that includes the stream ID with folly::none as the Stream ID.
70      */
onRead(const HTTPSessionBase & sess,size_t bytesRead,folly::Optional<HTTPCodec::StreamID>)71     virtual void onRead(const HTTPSessionBase& sess,
72                         size_t bytesRead,
73                         folly::Optional<HTTPCodec::StreamID> /*stream id*/) {
74       onRead(sess, bytesRead);
75     }
onWrite(const HTTPSessionBase &,size_t)76     virtual void onWrite(const HTTPSessionBase&, size_t /*bytesWritten*/) {
77     }
onRequestBegin(const HTTPSessionBase &)78     virtual void onRequestBegin(const HTTPSessionBase&) {
79     }
onRequestEnd(const HTTPSessionBase &,uint32_t)80     virtual void onRequestEnd(const HTTPSessionBase&,
81                               uint32_t /*maxIngressQueueSize*/) {
82     }
onActivateConnection(const HTTPSessionBase &)83     virtual void onActivateConnection(const HTTPSessionBase&) {
84     }
onDeactivateConnection(const HTTPSessionBase &)85     virtual void onDeactivateConnection(const HTTPSessionBase&) {
86     }
87     // Note: you must not start any asynchronous work from onDestroy()
onDestroy(const HTTPSessionBase &)88     virtual void onDestroy(const HTTPSessionBase&) {
89     }
onIngressMessage(const HTTPSessionBase &,const HTTPMessage &)90     virtual void onIngressMessage(const HTTPSessionBase&, const HTTPMessage&) {
91     }
onIngressLimitExceeded(const HTTPSessionBase &)92     virtual void onIngressLimitExceeded(const HTTPSessionBase&) {
93     }
onIngressPaused(const HTTPSessionBase &)94     virtual void onIngressPaused(const HTTPSessionBase&) {
95     }
onTransactionDetached(const HTTPSessionBase &)96     virtual void onTransactionDetached(const HTTPSessionBase&) {
97     }
onPingReplySent(int64_t)98     virtual void onPingReplySent(int64_t /*latency*/) {
99     }
onPingReplyReceived()100     virtual void onPingReplyReceived() {
101     }
onSettingsOutgoingStreamsFull(const HTTPSessionBase &)102     virtual void onSettingsOutgoingStreamsFull(const HTTPSessionBase&) {
103     }
onSettingsOutgoingStreamsNotFull(const HTTPSessionBase &)104     virtual void onSettingsOutgoingStreamsNotFull(const HTTPSessionBase&) {
105     }
onFlowControlWindowClosed(const HTTPSessionBase &)106     virtual void onFlowControlWindowClosed(const HTTPSessionBase&) {
107     }
onEgressBuffered(const HTTPSessionBase &)108     virtual void onEgressBuffered(const HTTPSessionBase&) {
109     }
onEgressBufferCleared(const HTTPSessionBase &)110     virtual void onEgressBufferCleared(const HTTPSessionBase&) {
111     }
onSettings(const HTTPSessionBase &,const SettingsList &)112     virtual void onSettings(const HTTPSessionBase&, const SettingsList&) {
113     }
onSettingsAck(const HTTPSessionBase &)114     virtual void onSettingsAck(const HTTPSessionBase&) {
115     }
116   };
117 
118   HTTPSessionBase(const folly::SocketAddress& localAddr,
119                   const folly::SocketAddress& peerAddr,
120                   HTTPSessionController* controller,
121                   const wangle::TransportInfo& tinfo,
122                   InfoCallback* infoCallback,
123                   std::unique_ptr<HTTPCodec> codec,
124                   const WheelTimerInstance& wheelTimer,
125                   HTTPCodec::StreamID rootNodeId);
126 
127   virtual ~HTTPSessionBase() override;
128 
setHTTPSessionActivityTracker(std::unique_ptr<HTTPSessionActivityTracker> httpSessionActivityTracker)129   virtual void setHTTPSessionActivityTracker(
130       std::unique_ptr<HTTPSessionActivityTracker> httpSessionActivityTracker) {
131     httpSessionActivityTracker_ = std::move(httpSessionActivityTracker);
132   }
133 
getHTTPSessionActivityTracker()134   [[nodiscard]] HTTPSessionActivityTracker* getHTTPSessionActivityTracker()
135       const {
136     return httpSessionActivityTracker_.get();
137   }
138   /**
139    * Set the read buffer limit to be used for all new HTTPSessionBase objects.
140    */
setDefaultReadBufferLimit(uint32_t limit)141   static void setDefaultReadBufferLimit(uint32_t limit) {
142     kDefaultReadBufLimit = limit;
143     VLOG(3) << "read buffer limit: " << int(limit / 1000) << "KB";
144   }
145 
setMaxReadBufferSize(uint32_t bytes)146   static void setMaxReadBufferSize(uint32_t bytes) {
147     maxReadBufferSize_ = bytes;
148   }
149 
150   /**
151    * Set the maximum egress body size for any outbound body bytes per loop,
152    * when there are > 1 transactions.
153    */
setFlowControlledBodySizeLimit(uint32_t limit)154   static void setFlowControlledBodySizeLimit(uint32_t limit) {
155     egressBodySizeLimit_ = limit;
156   }
157 
158   /**
159    * Set the default number of egress bytes this session will buffer before
160    * pausing all transactions' egress.
161    */
setDefaultWriteBufferLimit(uint32_t max)162   static void setDefaultWriteBufferLimit(uint32_t max) {
163     kDefaultWriteBufLimit = max;
164   }
165 
setInfoCallback(InfoCallback * callback)166   void setInfoCallback(InfoCallback* callback) {
167     infoCallback_ = callback;
168   }
169 
getInfoCallback()170   InfoCallback* getInfoCallback() const {
171     return infoCallback_;
172   }
173 
174   virtual void setSessionStats(HTTPSessionStats* stats);
175 
176   virtual HTTPTransaction::Transport::Type getType() const noexcept = 0;
177 
178   virtual folly::AsyncTransport* getTransport() = 0;
179 
180   virtual const folly::AsyncTransport* getTransport() const = 0;
181 
182   virtual folly::EventBase* getEventBase() const = 0;
183 
184   /**
185    * Called by handleErrorDirectly (when handling parse errors) if the
186    * transaction has no handler.
187    */
188   HTTPTransaction::Handler* getParseErrorHandler(HTTPTransaction* txn,
189                                                  const HTTPException& error);
190 
191   virtual bool hasActiveTransactions() const = 0;
192 
193   /**
194    * Returns true iff a new outgoing transaction can be made on this session
195    */
supportsMoreTransactions()196   bool supportsMoreTransactions() const {
197     return (getNumOutgoingStreams() < getMaxConcurrentOutgoingStreams());
198   }
199 
200   virtual uint32_t getNumStreams() const = 0;
201 
202   virtual uint32_t getNumOutgoingStreams() const = 0;
203 
204   // SimpleSessionPool
getHistoricalMaxOutgoingStreams()205   uint32_t getHistoricalMaxOutgoingStreams() const {
206     return historicalMaxOutgoingStreams_;
207   }
208 
209   virtual uint32_t getNumIncomingStreams() const = 0;
210 
211   virtual uint32_t getMaxConcurrentOutgoingStreamsRemote() const = 0;
212 
getMaxConcurrentOutgoingStreams()213   uint32_t getMaxConcurrentOutgoingStreams() const {
214     return std::min(maxConcurrentOutgoingStreamsConfig_,
215                     getMaxConcurrentOutgoingStreamsRemote());
216   }
217 
getController()218   HTTPSessionController* getController() const {
219     return controller_;
220   }
221 
setController(HTTPSessionController * controller)222   void setController(HTTPSessionController* controller) {
223     controller_ = controller;
224 
225     // Controller controlled settings
226     initCodecHeaderIndexingStrategy();
227   }
228 
getConnectionCloseReason()229   ConnectionCloseReason getConnectionCloseReason() const {
230     return closeReason_;
231   }
232 
233   template <typename Filter, typename... Args>
addCodecFilter(Args &&...args)234   void addCodecFilter(Args&&... args) {
235     codec_.add<Filter>(std::forward<Args>(args)...);
236   }
237 
getCodecProtocol()238   virtual CodecProtocol getCodecProtocol() const {
239     return codec_->getProtocol();
240   }
241 
242   /**
243    * Set flow control properties on the session.
244    *
245    * @param initialReceiveWindow      size of initial receive window
246    *                                  for all ingress streams; set via
247    *                                  the initial SETTINGS frame
248    * @param receiveStreamWindowSize   per-stream receive window for NEW streams;
249    *                                  sent via a WINDOW_UPDATE frame
250    * @param receiveSessionWindowSize  per-session receive window; sent
251    *                                  via a WINDOW_UPDATE frame
252    */
253   virtual void setFlowControl(size_t initialReceiveWindow,
254                               size_t receiveStreamWindowSize,
255                               size_t receiveSessionWindowSize) = 0;
256 
257   /**
258    * Set outgoing settings for this session
259    */
260   virtual void setEgressSettings(const SettingsList& inSettings) = 0;
261 
262   /**
263    * Global flag for turning HTTP2 priorities off
264    **/
setHTTP2PrioritiesEnabled(bool enabled)265   void setHTTP2PrioritiesEnabled(bool enabled) /*override*/ {
266     h2PrioritiesEnabled_ = enabled;
267   }
268 
getHTTP2PrioritiesEnabled()269   virtual bool getHTTP2PrioritiesEnabled() const {
270     return h2PrioritiesEnabled_;
271   }
272 
273   /**
274    * Set the maximum number of outgoing transactions this session can open
275    * at once. Note: you can only call function before startNow() is called
276    * since the remote side can change this value.
277    */
setMaxConcurrentOutgoingStreams(uint32_t num)278   void setMaxConcurrentOutgoingStreams(uint32_t num) {
279     // TODO: CHECK(started_);
280     maxConcurrentOutgoingStreamsConfig_ = num;
281   }
282 
283   /**
284    * Set the maximum number of transactions the remote can open at once.
285    */
286   virtual void setMaxConcurrentIncomingStreams(uint32_t num) = 0;
287 
288   /**
289    * Get/Set the number of egress bytes this session will buffer before
290    * pausing all transactions' egress.
291    */
getWriteBufferLimit()292   uint32_t getWriteBufferLimit() const {
293     return writeBufLimit_;
294   }
295 
setWriteBufferLimit(uint32_t limit)296   void setWriteBufferLimit(uint32_t limit) {
297     writeBufLimit_ = limit;
298     VLOG(4) << "write buffer limit: " << int(limit / 1000) << "KB";
299   }
300 
setReadBufferLimit(uint32_t limit)301   void setReadBufferLimit(uint32_t limit) {
302     readBufLimit_ = limit;
303   }
304 
305   /**
306    * Start reading from the transport and send any introductory messages
307    * to the remote side. This function must be called once per session to
308    * begin reads.
309    */
310   virtual void startNow() = 0;
311 
312   /**
313    * Send a settings frame
314    */
315   virtual size_t sendSettings() = 0;
316 
317   /**
318    * Causes a ping to be sent on the session. If the underlying protocol
319    * doesn't support pings, this will return 0. Otherwise, it will return
320    * the number of bytes written on the transport to send the ping.
321    */
322   virtual size_t sendPing() = 0;
323 
324   /**
325    * Sends a priority message on this session.  If the underlying protocol
326    * doesn't support priority, this is a no-op.  A new stream identifier will
327    * be selected and returned.
328    */
329   virtual HTTPCodec::StreamID sendPriority(http2::PriorityUpdate pri)
330       /*override*/
331       = 0;
332 
333   /**
334    * As above, but updates an existing priority node.  Do not use for
335    * real nodes, prefer HTTPTransaction::changePriority.
336    */
337   virtual size_t sendPriority(HTTPCodec::StreamID id,
338                               http2::PriorityUpdate pri) = 0;
339 
340   /**
341    * Send a CERTIFICATE_REQUEST frame. If the underlying protocol doesn't
342    * support secondary authentication, this is a no-op and 0 is returned.
343    */
sendCertificateRequest(std::unique_ptr<folly::IOBuf>,std::vector<fizz::Extension>)344   virtual size_t sendCertificateRequest(
345       std::unique_ptr<folly::IOBuf> /* certificateRequestContext */,
346       std::vector<fizz::Extension> /* extensions */) {
347     return 0;
348   }
349 
getNumTxnServed()350   uint64_t getNumTxnServed() const {
351     return transactionSeqNo_;
352   }
353 
getLatestIdleTime()354   std::chrono::seconds getLatestIdleTime() const {
355     DCHECK_GT(transactionSeqNo_, 0) << "No idle time for the first transaction";
356     DCHECK(latestActive_ > TimePoint::min());
357     return latestIdleDuration_;
358   }
359 
setPrioritySampled(bool sampled)360   void setPrioritySampled(bool sampled) {
361     prioritySample_ = sampled;
362   }
363 
364   // public HTTPTransaction::Transport overrides
getLocalAddress()365   virtual const folly::SocketAddress& getLocalAddress() const noexcept {
366     return localAddr_;
367   }
getPeerAddress()368   virtual const folly::SocketAddress& getPeerAddress() const noexcept {
369     return peerAddr_;
370   }
getSetupTransportInfo()371   const wangle::TransportInfo& getSetupTransportInfo() const noexcept
372   /*override*/ {
373     return transportInfo_;
374   }
375   virtual bool getCurrentTransportInfo(
376       wangle::TransportInfo* tinfo) /*override*/
377       = 0;
378 
379   virtual bool getCurrentTransportInfoWithoutUpdate(
380       wangle::TransportInfo* tinfo) const = 0;
381 
382   virtual void setHeaderCodecStats(HeaderCodec::Stats* stats) = 0;
383 
384   virtual void enableDoubleGoawayDrain() = 0;
385 
getSetupTransportInfo()386   wangle::TransportInfo& getSetupTransportInfo() noexcept {
387     return transportInfo_;
388   }
389 
onNetworkSwitch(std::unique_ptr<folly::AsyncUDPSocket>)390   virtual void onNetworkSwitch(
391       std::unique_ptr<folly::AsyncUDPSocket>) noexcept {
392   }
393 
394   /**
395    * If the connection is closed by remote end
396    */
397   virtual bool connCloseByRemote() = 0;
398 
399   // Upstream API
400 
401   // The interfaces defined below update the virtual stream based priority
402   // scheme from the current system which allows only strict priorities to a
403   // flexible system allowing an arbitrary tree of virtual streams, subject only
404   // to the limitations in the HTTP/2 specification. An arbitrary prioritization
405   // scheme can be implemented by constructing virtual streams corresponding to
406   // the desired prioritization and attaching new streams as dependencies of the
407   // appropriate virtual stream.
408   //
409   // The user must define a map from an opaque integer priority level to an
410   // HTTP/2 priority corresponding to the virtual stream. This map is
411   // implemented by the user in a class that extends
412   // HTTPUpstreamSession::PriorityMapFactory. A shared pointer to this class is
413   // passed into the constructor of HTTPUpstreamSession. This method will send
414   // the virtual streams and return a unique pointer to a class that extends
415   // HTTPUpstreamSession::PriorityAdapter. This class implements the map between
416   // the user defined priority level and the HTTP/2 priority level.
417   //
418   // When the session is started, the createVirtualStreams method of
419   // PriorityMapFactory is called by HTTPUpstreamSession::startNow. The returned
420   // pointer to the PriorityAdapter map is cached in HTTPUpstreamSession. The
421   // HTTP/2 priority that should be used for a new stream dependent on a virtual
422   // stream corresponding to a given priority level is then retrieved by calling
423   // the HTTPUpstreamSession::getHTTPPriority(uint8_t level) method.
424   //
425   // The prior strict priority system has been left in place for now, but if
426   // both maxLevels and PriorityMapFactory are passed into the
427   // HTTPUpstreamSession constructor, the maxLevels parameter will be ignored.
428 
429   // Implments a map from generic priority level to HTTP/2 priority.
430   class PriorityAdapter {
431    public:
432     virtual folly::Optional<const HTTPMessage::HTTP2Priority> getHTTPPriority(
433         uint8_t level) = 0;
434     virtual ~PriorityAdapter() = default;
435   };
436 
437   class PriorityMapFactory {
438    public:
439     // Creates the map implemented by PriorityAdapter, sends the corresponding
440     // virtual stream on the given session, and retuns the map.
441     virtual std::unique_ptr<PriorityAdapter> createVirtualStreams(
442         HTTPPriorityMapFactoryProvider* session) const = 0;
443     virtual ~PriorityMapFactory() = default;
444   };
445 
446   using FilterIteratorFn = std::function<void(HTTPCodecFilter*)>;
447 
448   virtual bool isDetachable(bool checkSocket) const = 0;
449 
450   virtual void attachThreadLocals(folly::EventBase* eventBase,
451                                   folly::SSLContextPtr sslContext,
452                                   const WheelTimerInstance& wheelTimer,
453                                   HTTPSessionStats* stats,
454                                   FilterIteratorFn fn,
455                                   HeaderCodec::Stats* headerCodecStats,
456                                   HTTPSessionController* controller) = 0;
457 
458   virtual void detachThreadLocals(bool detachSSLContext = false) = 0;
459 
460   /**
461    * Creates a new transaction on this upstream session. Invoking this function
462    * also has the side-affect of starting reads after this event loop completes.
463    *
464    * @param handler The request handler to attach to this transaction. It must
465    *                not be null.
466    */
467   virtual HTTPTransaction* newTransaction(
468       HTTPTransaction::Handler* handler) = 0;
469 
470   virtual bool isReplaySafe() const = 0;
471 
472   /**
473    * Returns true if the underlying transport can be used again in a new
474    * request.
475    */
476   virtual bool isReusable() const = 0;
477 
478   /**
479    * Returns true if the session is shutting down
480    */
481   virtual bool isClosing() const = 0;
482 
483   /**
484    * Drains the current transactions and prevents new transactions from being
485    * created on this session. When the number of transactions reaches zero, this
486    * session will shutdown the transport and delete itself.
487    */
488   virtual void drain() = 0;
489 
490   virtual folly::Optional<const HTTPMessage::HTTP2Priority> getHTTPPriority(
491       uint8_t level) = 0;
492 
493   /**
494    * Enable to use Ex Headers in HTTPSession
495    */
496   void enableExHeadersSettings() noexcept;
497 
isExHeadersEnabled()498   bool isExHeadersEnabled() noexcept {
499     return exHeadersEnabled_;
500   }
501 
502   virtual void injectTraceEventIntoAllTransactions(TraceEvent&) = 0;
503 
setConnectionToken(const HTTPTransaction::ConnectionToken & token)504   void setConnectionToken(
505       const HTTPTransaction::ConnectionToken& token) noexcept {
506     connectionToken_ = token;
507   }
508 
509   // Use the protocol's ping feature to test liveness of the peer.  Send a ping
510   // every interval seconds.  If the ping is not returned by timeout, drop the
511   // connection.
512   // If extendIntervalOnIngress is true, then any ingress data will reset the
513   // timer until the next PING.
514   // If immediate is true, send a ping immediately.  Otherwise, wait one
515   // interval.
516   virtual void enablePingProbes(std::chrono::seconds interval,
517                                 std::chrono::seconds timeout,
518                                 bool extendIntervalOnIngress,
519                                 bool immediate = false) = 0;
520 
setIngressTimeoutAfterEom(bool setIngressTimeoutAfterEom)521   void setIngressTimeoutAfterEom(bool setIngressTimeoutAfterEom) noexcept {
522     setIngressTimeoutAfterEom_ = setIngressTimeoutAfterEom;
523   }
524 
525  protected:
526   bool notifyEgressBodyBuffered(int64_t bytes, bool update);
527 
528   void updateWriteBufSize(int64_t delta);
529 
530   void updatePendingWrites();
531 
532   /**
533    * Install a direct response handler for the transaction based on the
534    * error.
535    */
536   void handleErrorDirectly(HTTPTransaction* txn, const HTTPException& error);
537 
538   bool onBodyImpl(std::unique_ptr<folly::IOBuf> chain,
539                   size_t length,
540                   uint16_t padding,
541                   HTTPTransaction* txn);
542 
543   bool notifyBodyProcessed(uint32_t bytes);
544 
setLatestActive()545   void setLatestActive() {
546     latestActive_ = getCurrentTime();
547   }
548 
ingressLimitExceeded()549   bool ingressLimitExceeded() const {
550     return pendingReadSize_ > readBufLimit_;
551   }
onCreateTransaction()552   void onCreateTransaction() {
553     if (transactionSeqNo_ >= 1) {
554       // idle duration only exists since the 2nd transaction in the session
555       latestIdleDuration_ = secondsSince(latestActive_);
556     }
557   }
558 
incrementSeqNo()559   void incrementSeqNo() {
560     ++transactionSeqNo_;
561   }
562 
isPrioritySampled()563   bool isPrioritySampled() const {
564     return prioritySample_;
565   }
566 
onNewOutgoingStream(uint32_t outgoingStreams)567   void onNewOutgoingStream(uint32_t outgoingStreams) {
568     if (outgoingStreams > historicalMaxOutgoingStreams_) {
569       historicalMaxOutgoingStreams_ = outgoingStreams;
570     }
571   }
572 
setCloseReason(ConnectionCloseReason reason)573   void setCloseReason(ConnectionCloseReason reason) {
574     if (closeReason_ == ConnectionCloseReason::kMAX_REASON) {
575       closeReason_ = reason;
576     }
577   }
578 
579   static void handleLastByteEvents(ByteEventTracker* byteEventTracker,
580                                    HTTPTransaction* txn,
581                                    size_t encodedSize,
582                                    size_t byteOffset,
583                                    bool piggybacked);
584 
585   void runDestroyCallbacks();
586 
587   /*
588    * Invoked by children upon updating the actual codec wrapped by the filter
589    * chain.
590    */
591   void onCodecChanged();
592 
593   /**
594    * Initializes the underlying codec's header indexing strategy, if applicable,
595    * by retrieving the requisite strategy from the bound controller.
596    * This methods exists as some sessions, notably HTTPUpstreamSessions, have
597    # their parent controller set after instantiation
598    */
599   void initCodecHeaderIndexingStrategy();
600 
601   /**
602    * Attaches session to HTTPSessionController.
603    */
604   void attachToSessionController();
605 
606   /**
607    * Informs HTTPSessionController that transport is ready.
608    */
609   void informSessionControllerTransportReady();
610 
611   HTTPSessionStats* sessionStats_{nullptr};
612 
613   InfoCallback* infoCallback_{nullptr}; // maybe can move to protected
614 
615   wangle::TransportInfo transportInfo_;
616 
617   HTTPCodecFilterChain codec_;
618 
619   HTTP2PriorityQueue txnEgressQueue_;
620 
621   /**
622    * Maximum number of ingress body bytes that can be buffered across all
623    * transactions for this single session/connection.
624    * While changing this value from multiple threads is supported,
625    * it is not correct since a thread can use a value changed by another thread
626    * We should change the code to avoid this
627    */
628   static std::atomic<uint32_t> kDefaultReadBufLimit;
629 
630   /**
631    * The maximum size of the read buffer from the socket.
632    */
633   static uint32_t maxReadBufferSize_;
634 
635   /**
636    * Maximum number of bytes that can be buffered across all transactions before
637    * this session will start applying backpressure to its transactions.
638    */
639   static uint32_t kDefaultWriteBufLimit;
640   /**
641    * Maximum number of bytes to egress per loop when there are > 1
642    * transactions.  Otherwise defaults to kDefaultWriteBufLimit.
643    */
644   static uint32_t egressBodySizeLimit_;
645 
646   /** Address of this end of the connection */
647   folly::SocketAddress localAddr_;
648 
649   /** Address of the remote end of the connection */
650   folly::SocketAddress peerAddr_;
651 
652   /**
653    * Optional connection token associated with this session.
654    */
655   folly::Optional<HTTPTransaction::ConnectionToken> connectionToken_;
656 
657   /**
658    * Indicates whether ingress timeout has to be scheduled after EOM is sent.
659    */
660   bool setIngressTimeoutAfterEom_{false};
661 
662   std::unique_ptr<HTTPSessionActivityTracker> httpSessionActivityTracker_;
663 
664  private:
665   // Underlying controller_ is marked as private so that callers must utilize
666   // getController/setController protected methods.  This ensures we have a
667   // single path to update controller_
668   HTTPSessionController* controller_{nullptr};
669 
670   // private ManagedConnection methods
getIdleTime()671   std::chrono::milliseconds getIdleTime() const override {
672     if (timePointInitialized(latestActive_)) {
673       return millisecondsSince(latestActive_);
674     } else {
675       return std::chrono::milliseconds(0);
676     }
677   }
678 
679   /**
680    * The latest time when this session became idle status
681    */
682   TimePoint latestActive_{};
683 
684   /**
685    * The idle duration between latest two consecutive active status
686    */
687   std::chrono::seconds latestIdleDuration_{};
688 
689   /** Transaction sequence number */
690   uint32_t transactionSeqNo_{0};
691 
692   /**
693    * The root cause reason this connection was closed.
694    */
695   ConnectionCloseReason closeReason_{ConnectionCloseReason::kMAX_REASON};
696 
697   /**
698    * The maximum number concurrent transactions in the history of this session
699    */
700   uint32_t historicalMaxOutgoingStreams_{0};
701 
702   /**
703    * The maximum number of concurrent transactions that this session may
704    * create, as configured locally.
705    */
706   uint32_t maxConcurrentOutgoingStreamsConfig_{
707       kDefaultMaxConcurrentOutgoingStreams};
708 
709   /**
710    * Maximum number of cumulative bytes that can be buffered by the
711    * transactions in this session before applying backpressure.
712    *
713    * Note readBufLimit_ is settable via setFlowControl
714    */
715   uint32_t readBufLimit_{kDefaultReadBufLimit};
716   uint32_t writeBufLimit_{kDefaultWriteBufLimit};
717 
718   /**
719    * Bytes of egress data sent to the socket but not yet written
720    * to the network.
721    */
722   uint64_t pendingWriteSize_{0};
723 
724   /**
725    * The net change this event loop in the amount of buffered bytes
726    * for all this session's txns and socket write buffer.
727    */
728   int64_t pendingWriteSizeDelta_{0};
729 
730   /**
731    * Bytes of ingress data read from the socket, but not yet sent to a
732    * transaction.
733    */
734   uint32_t pendingReadSize_{0};
735 
736   bool prioritySample_ : 1;
737   bool h2PrioritiesEnabled_ : 1;
738 
739   /**
740    * Indicates whether Ex Headers is supported in HTTPSession
741    */
742   bool exHeadersEnabled_ : 1;
743 };
744 
745 } // namespace proxygen
746