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