proxygen
HTTPSessionBase.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-present, Facebook, Inc.
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. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
11 
16 
19 
20 namespace proxygen {
25 
26 
28  const SocketAddress& localAddr,
29  const SocketAddress& peerAddr,
30  HTTPSessionController* controller,
31  const TransportInfo& tinfo,
32  InfoCallback* infoCallback,
33  std::unique_ptr<HTTPCodec> codec) :
34  infoCallback_(infoCallback),
35  transportInfo_(tinfo),
36  codec_(std::move(codec)),
37  localAddr_(localAddr),
38  peerAddr_(peerAddr),
39  prioritySample_(false),
40  h2PrioritiesEnabled_(true),
41  exHeadersEnabled_(false) {
42 
43  // If we receive IPv4-mapped IPv6 addresses, convert them to IPv4.
46 
47  setController(controller);
48 }
49 
51  if (infoCallback_) {
52  infoCallback_->onDestroy(*this);
53  }
54  if (controller_) {
56  controller_ = nullptr;
57  }
58 }
59 
61  if (controller_) {
63  }
64 
66 }
67 
69  // Set the header indexing strategy to be employed by the codec if H2
70  // This is done here so that the strategy could be dynamic depending on the
71  // session
73  HTTP2Codec* h2Codec = static_cast<HTTP2Codec*>(codec_.getChainEndPtr());
76  }
77 }
78 
79 bool HTTPSessionBase::onBodyImpl(std::unique_ptr<folly::IOBuf> chain, size_t length,
80  uint16_t padding, HTTPTransaction* txn) {
81  DestructorGuard dg(this);
82  auto oldSize = pendingReadSize_;
83  pendingReadSize_ += length + padding;
84  txn->onIngressBody(std::move(chain), padding);
85  if (oldSize < pendingReadSize_) {
86  // Transaction must have buffered something and not called
87  // notifyBodyProcessed() on it.
88  VLOG(4) << *this << " Enqueued ingress. Ingress buffer uses "
89  << pendingReadSize_ << " of " << readBufLimit_
90  << " bytes.";
91  if (pendingReadSize_ > readBufLimit_ &&
92  oldSize <= readBufLimit_) {
93  if (infoCallback_) {
95  }
96  return true;
97  }
98  }
99  return false;
100 }
101 
103  CHECK_GE(pendingReadSize_, bytes);
104  auto oldSize = pendingReadSize_;
105  pendingReadSize_ -= bytes;
106  VLOG(4) << *this << " Dequeued " << bytes << " bytes of ingress. "
107  << "Ingress buffer uses " << pendingReadSize_ << " of "
108  << readBufLimit_ << " bytes.";
109  if (oldSize > readBufLimit_ &&
110  pendingReadSize_ <= readBufLimit_) {
111  return true;
112  }
113  return false;
114 }
115 
116 void
118  const HTTPException& error) {
119  VLOG(4) << *this << " creating direct error handler";
120  DCHECK(txn);
121  auto handler = getParseErrorHandler(txn, error);
122  if (!handler) {
123  txn->sendAbort();
124  return;
125  }
126  txn->setHandler(handler);
127  if (infoCallback_) {
129  }
130  txn->onError(error);
131 }
132 
135  const HTTPException& error) {
136  // we encounter an error before we finish reading the ingress headers.
138  // do not return the parse error handler for upstreams, since all we
139  // can do in that direction is abort.
140  return nullptr;
141  }
142  return controller_->getParseErrorHandler(txn, error, getLocalAddress());
143 }
144 
147  if (settings) {
149  exHeadersEnabled_ = true;
150  }
151 }
152 
154  auto controllerPtr = getController();
155  if (controllerPtr) {
156  controllerPtr->attachSession(this);
157  }
158 }
159 
161  ByteEventTracker* byteEventTracker,
162  HTTPTransaction* txn,
163  size_t encodedSize,
164  size_t byteOffset,
165  bool piggybacked) {
166  // TODO: sort out the TransportCallback for all the EOM handling cases.
167  // Current code has the same behavior as before when there wasn't commonEom.
168  // The issue here is onEgressBodyLastByte can be called twice, depending on
169  // the encodedSize. E.g., when codec actually write to buffer in sendEOM.
170  if (!txn->testAndSetFirstByteSent()) {
171  txn->onEgressBodyFirstByte();
172  }
173  if (!piggybacked) {
174  txn->onEgressBodyLastByte();
175  }
176  // in case encodedSize == 0 we won't get TTLBA which is acceptable
177  // noting the fact that we don't have a response body
178  if (byteEventTracker && (encodedSize > 0)) {
179  byteEventTracker->addLastByteEvent(txn, byteOffset);
180  }
181 }
182 
183 }
virtual void setHandler(Handler *handler)
void onError(const HTTPException &error)
static uint32_t kDefaultReadBufLimit
void enableExHeadersSettings() noexcept
folly::SocketAddress localAddr_
virtual HTTPSettings * getEgressSettings()
Definition: HTTPCodec.h:653
virtual void onIngressLimitExceeded(const HTTPSessionBase &)
HTTPCodecFilterChain codec_
ProxygenError getProxygenError() const
Definition: Exception.h:50
const SocketAddress peerAddr
Definition: TestUtils.cpp:20
static uint32_t maxReadBufferSize_
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
virtual void onIngressError(const HTTPSessionBase &, ProxygenError)
CodecFactory codec
STL namespace.
virtual CodecProtocol getProtocol() const =0
void onIngressBody(std::unique_ptr< folly::IOBuf > chain, uint16_t padding)
static http_parser_settings settings
Definition: test.c:1529
std::unique_ptr< Codec > codec_
virtual void addLastByteEvent(HTTPTransaction *txn, uint64_t byteNo) noexcept
requires E e noexcept(noexcept(s.error(std::move(e))))
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
Definition: error.h:48
HTTPSessionBase(const folly::SocketAddress &localAddr, const folly::SocketAddress &peerAddr, HTTPSessionController *controller, const wangle::TransportInfo &tinfo, InfoCallback *infoCallback, std::unique_ptr< HTTPCodec > codec)
void handler(int, siginfo_t *, void *)
virtual void onSessionCodecChange(HTTPSessionBase *)
static void handleLastByteEvents(ByteEventTracker *byteEventTracker, HTTPTransaction *txn, size_t encodedSize, size_t byteOffset, bool piggybacked)
bool onBodyImpl(std::unique_ptr< folly::IOBuf > chain, size_t length, uint16_t padding, HTTPTransaction *txn)
void setHeaderIndexingStrategy(const HeaderIndexingStrategy *indexingStrat)
Definition: HTTP2Codec.h:171
HTTPSessionController * getController()
void handleErrorDirectly(HTTPTransaction *txn, const HTTPException &error)
virtual HTTPTransactionHandler * getParseErrorHandler(HTTPTransaction *txn, const HTTPException &error, const folly::SocketAddress &localAddress)=0
virtual const HeaderIndexingStrategy * getHeaderIndexingStrategy() const
void setController(HTTPSessionController *controller)
virtual void detachSession(const HTTPSessionBase *session)=0
const SocketAddress localAddr
Definition: TestUtils.cpp:19
bool notifyBodyProcessed(uint32_t bytes)
bool isHTTP2CodecProtocol(CodecProtocol protocol)
folly::SocketAddress peerAddr_
static uint32_t kDefaultWriteBufLimit
virtual void onDestroy(const HTTPSessionBase &)
const folly::SocketAddress & getLocalAddress() const noexcept
HTTPSessionController * controller_
static uint32_t egressBodySizeLimit_
HTTPTransaction::Handler * getParseErrorHandler(HTTPTransaction *txn, const HTTPException &error)
virtual TransportDirection getTransportDirection() const =0
void setSetting(SettingsId id, SettingsValue val)