proxygen
proxygen::SPDYCodec Class Reference

#include <SPDYCodec.h>

Inheritance diagram for proxygen::SPDYCodec:
proxygen::HTTPParallelCodec proxygen::HTTPCodec

Classes

struct  SettingData
 

Public Types

using SettingList = std::vector< SettingData >
 
- Public Types inherited from proxygen::HTTPCodec
using StreamID = uint64_t
 

Public Member Functions

 SPDYCodec (TransportDirection direction, SPDYVersion version, int spdyCompressionLevel=Z_NO_COMPRESSION)
 
 ~SPDYCodec () override
 
CodecProtocol getProtocol () const override
 
const std::stringgetUserAgent () const override
 
bool supportsStreamFlowControl () const override
 
bool supportsSessionFlowControl () const override
 
size_t onIngress (const folly::IOBuf &buf) override
 
bool supportsPushTransactions () const override
 
void generateHeader (folly::IOBufQueue &writeBuf, StreamID stream, const HTTPMessage &msg, bool eom=false, HTTPHeaderSize *size=nullptr) override
 
void generatePushPromise (folly::IOBufQueue &writeBuf, StreamID stream, const HTTPMessage &msg, StreamID assocstream, bool eom=false, HTTPHeaderSize *size=nullptr) override
 
size_t generateBody (folly::IOBufQueue &writeBuf, StreamID stream, std::unique_ptr< folly::IOBuf > chain, folly::Optional< uint8_t > padding, bool eom) override
 
size_t generateChunkHeader (folly::IOBufQueue &writeBuf, StreamID stream, size_t length) override
 
size_t generateChunkTerminator (folly::IOBufQueue &writeBuf, StreamID stream) override
 
size_t generateTrailers (folly::IOBufQueue &writeBuf, StreamID stream, const HTTPHeaders &trailers) override
 
size_t generateEOM (folly::IOBufQueue &writeBuf, StreamID stream) override
 
size_t generateRstStream (folly::IOBufQueue &writeBuf, StreamID txn, ErrorCode statusCode) override
 
size_t generateGoaway (folly::IOBufQueue &writeBuf, StreamID lastStream, ErrorCode statusCode, std::unique_ptr< folly::IOBuf > debugData=nullptr) override
 
size_t generatePingRequest (folly::IOBufQueue &writeBuf) override
 
size_t generatePingReply (folly::IOBufQueue &writeBuf, uint64_t uniqueID) override
 
size_t generateSettings (folly::IOBufQueue &writeBuf) override
 
size_t generateWindowUpdate (folly::IOBufQueue &writeBuf, StreamID stream, uint32_t delta) override
 
const HTTPSettingsgetIngressSettings () const override
 
HTTPSettingsgetEgressSettings () override
 
uint32_t getDefaultWindowSize () const override
 
uint8_t getVersion () const
 
uint8_t getMinorVersion () const
 
void setMaxFrameLength (uint32_t maxFrameLength)
 
void setMaxUncompressedHeaders (uint32_t maxUncompressed)
 
void setHeaderCodecStats (HeaderCodec::Stats *stats) override
 
size_t addPriorityNodes (PriorityQueue &queue, folly::IOBufQueue &writeBuf, uint8_t maxLevel) override
 
StreamID mapPriorityToDependency (uint8_t priority) const override
 
int8_t mapDependencyToPriority (StreamID parent) const override
 
- Public Member Functions inherited from proxygen::HTTPParallelCodec
 HTTPParallelCodec (TransportDirection direction)
 
TransportDirection getTransportDirection () const override
 
StreamID createStream () override
 
bool isBusy () const override
 
bool supportsParallelRequests () const override
 
bool closeOnEgressComplete () const override
 
void setCallback (Callback *callback) override
 
void setParserPaused (bool) override
 
void onIngressEOF () override
 
bool isReusable () const override
 
bool isWaitingToDrain () const override
 
StreamID getLastIncomingStreamID () const override
 
void enableDoubleGoawayDrain () override
 
bool onIngressUpgradeMessage (const HTTPMessage &msg) override
 
void setNextEgressStreamId (StreamID nextEgressStreamID)
 
bool isInitiatedStream (StreamID stream) const
 
bool isStreamIngressEgressAllowed (StreamID stream) const
 
- Public Member Functions inherited from proxygen::HTTPCodec
virtual ~HTTPCodec ()
 
virtual HPACKTableInfo getHPACKTableInfo () const
 
virtual bool supportsExTransactions () const
 
virtual size_t generateConnectionPreface (folly::IOBufQueue &)
 
virtual void generateExHeader (folly::IOBufQueue &, StreamID, const HTTPMessage &, const HTTPCodec::ExAttributes &, bool, HTTPHeaderSize *)
 
virtual size_t generateSettingsAck (folly::IOBufQueue &)
 
virtual size_t generatePriority (folly::IOBufQueue &, StreamID, const HTTPMessage::HTTPPriority &)
 
virtual size_t generateCertificateRequest (folly::IOBufQueue &, uint16_t, std::unique_ptr< folly::IOBuf >)
 
virtual size_t generateCertificate (folly::IOBufQueue &, uint16_t, std::unique_ptr< folly::IOBuf >)
 

Static Public Member Functions

static const SPDYVersionSettingsgetVersionSettings (SPDYVersion version)
 
static folly::Optional< SPDYVersiongetVersion (const std::string &protocol)
 

Static Public Attributes

static const StreamID NoStream = 0
 
- Static Public Attributes inherited from proxygen::HTTPCodec
static const folly::Optional< StreamIDNoStream
 
static const folly::Optional< uint8_tNoPadding = folly::none
 
static const StreamID MAX_STREAM_ID = 1u << 31
 
static const folly::Optional< ExAttributesNoExAttributes
 

Private Types

enum  FrameState { FRAME_HEADER = 0, CTRL_FRAME_DATA = 1, DATA_FRAME_DATA = 2 }
 

Private Member Functions

void generateSynStream (StreamID stream, StreamID assocStream, folly::IOBufQueue &writeBuf, const HTTPMessage &msg, bool eom, HTTPHeaderSize *size)
 
void generateSynReply (StreamID stream, folly::IOBufQueue &writeBuf, const HTTPMessage &msg, bool eom, HTTPHeaderSize *size)
 
size_t generatePingCommon (folly::IOBufQueue &writeBuf, uint64_t uniqueID)
 
size_t parseIngress (const folly::IOBuf &buf)
 
void onSynStream (uint32_t assocStream, uint8_t pri, uint8_t slot, const compress::HeaderPieceList &headers, const HTTPHeaderSize &size)
 
void onSynReply (const compress::HeaderPieceList &headers, const HTTPHeaderSize &size)
 
void onRstStream (uint32_t statusCode) noexcept
 
void onSettings (const SettingList &settings)
 
void onPing (uint32_t uniqueID) noexcept
 
void onGoaway (uint32_t lastGoodStream, uint32_t statusCode) noexcept
 
void onHeaders (const compress::HeaderPieceList &headers) noexcept
 
void onWindowUpdate (uint32_t delta) noexcept
 
std::unique_ptr< HTTPMessageparseHeaders (TransportDirection direction, StreamID streamID, StreamID assocStreamID, const compress::HeaderPieceList &headers)
 
void onControlFrame (folly::io::Cursor &cursor)
 
void onSynCommon (StreamID streamID, StreamID assocStreamID, const compress::HeaderPieceList &headers, int8_t pri, const HTTPHeaderSize &size)
 
void deliverOnMessageBegin (StreamID streamID, StreamID assocStreamID, HTTPMessage *msg)
 
size_t generateDataFrame (folly::IOBufQueue &writeBuf, uint32_t streamID, uint8_t flags, uint32_t length, std::unique_ptr< folly::IOBuf > payload)
 
std::unique_ptr< folly::IOBufserializeRequestHeaders (const HTTPMessage &msg, bool isPushed, uint32_t headroom=0, HTTPHeaderSize *size=nullptr)
 
std::unique_ptr< folly::IOBufserializeResponseHeaders (const HTTPMessage &msg, uint32_t headroom=0, HTTPHeaderSize *size=nullptr)
 
std::unique_ptr< folly::IOBufencodeHeaders (const HTTPMessage &msg, std::vector< compress::Header > &headers, uint32_t headroom=0, HTTPHeaderSize *size=nullptr)
 
void failStream (bool newTxn, StreamID streamID, uint32_t code, std::string excStr=empty_string)
 
void failSession (uint32_t statusCode)
 
HeaderDecodeResult decodeHeaders (folly::io::Cursor &cursor)
 
void checkLength (uint32_t expectedLength, const std::string &msg)
 
void checkMinLength (uint32_t minLength, const std::string &msg)
 
bool isSPDYReserved (const std::string &name)
 
bool rstStatusSupported (int statusCode) const
 

Private Attributes

folly::fbvector< StreamIDclosedStreams_
 
const SPDYVersionSettingsversionSettings_
 
HTTPSettings ingressSettings_
 
HTTPSettings egressSettings_
 
std::unique_ptr< HTTPMessagepartialMsg_
 
std::string userAgent_
 
const folly::IOBufcurrentIngressBuf_ {nullptr}
 
StreamID nextEgressPingID_
 
uint32_t maxFrameLength_ {spdy::kMaxFrameLength}
 
uint32_t streamId_ {0}
 
uint32_t length_ {0}
 
uint16_t version_ {0}
 
uint16_t type_ {0xffff}
 
uint8_t flags_ {0}
 
enum proxygen::SPDYCodec::FrameState frameState_
 
bool ctrl_:1
 
GzipHeaderCodec headerCodec_
 

Additional Inherited Members

- Protected Types inherited from proxygen::HTTPParallelCodec
enum  ClosingState {
  OPEN = 0, OPEN_WITH_GRACEFUL_DRAIN_ENABLED = 1, FIRST_GOAWAY_SENT = 2, CLOSING = 3,
  CLOSED = 4
}
 
- Protected Member Functions inherited from proxygen::HTTPParallelCodec
template<typename T , typename... Args>
bool deliverCallbackIfAllowed (T callbackFn, char const *cbName, StreamID stream, Args &&...args)
 
- Protected Attributes inherited from proxygen::HTTPParallelCodec
TransportDirection transportDirection_
 
StreamID nextEgressStreamID_
 
StreamID lastStreamID_ {0}
 
HTTPCodec::Callbackcallback_ {nullptr}
 
StreamID ingressGoawayAck_ {std::numeric_limits<uint32_t>::max()}
 
StreamID egressGoawayAck_ {std::numeric_limits<uint32_t>::max()}
 
std::string goawayErrorMessage_
 
enum proxygen::HTTPParallelCodec::ClosingState sessionClosing_
 

Detailed Description

An implementation of the framing layer for all versions of SPDY. Instances of this class must not be used from multiple threads concurrently.

Definition at line 36 of file SPDYCodec.h.

Member Typedef Documentation

Definition at line 153 of file SPDYCodec.h.

Member Enumeration Documentation

Enumerator
FRAME_HEADER 
CTRL_FRAME_DATA 
DATA_FRAME_DATA 

Definition at line 369 of file SPDYCodec.h.

Constructor & Destructor Documentation

proxygen::SPDYCodec::SPDYCodec ( TransportDirection  direction,
SPDYVersion  version,
int  spdyCompressionLevel = Z_NO_COMPRESSION 
)
explicit

Definition at line 170 of file SPDYCodec.cpp.

References headerCodec_, proxygen::SPDYVersionSettings::majorVersion, proxygen::SPDYVersionSettings::minorVersion, nextEgressPingID_, proxygen::HTTPParallelCodec::nextEgressStreamID_, proxygen::HeaderCodec::setMaxUncompressed(), and versionSettings_.

172  : HTTPParallelCodec(direction),
174  frameState_(FrameState::FRAME_HEADER),
175  ctrl_(false),
176  headerCodec_(spdyCompressionLevel, versionSettings_) {
177  VLOG(4) << "creating SPDY/" << static_cast<int>(versionSettings_.majorVersion)
178  << "." << static_cast<int>(versionSettings_.minorVersion)
179  << " codec";
180 
181  // Limit uncompressed headers to 128kb
182  headerCodec_.setMaxUncompressed(kMaxUncompressed);
184 }
ProtocolVersion version
StreamID nextEgressPingID_
Definition: SPDYCodec.h:357
virtual void setMaxUncompressed(uint64_t maxUncompressed)
Definition: HeaderCodec.h:73
HTTPParallelCodec(TransportDirection direction)
GzipHeaderCodec headerCodec_
Definition: SPDYCodec.h:377
static const SPDYVersionSettings & getVersionSettings(SPDYVersion version)
Definition: SPDYCodec.cpp:138
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
enum proxygen::SPDYCodec::FrameState frameState_
proxygen::SPDYCodec::~SPDYCodec ( )
override

Definition at line 186 of file SPDYCodec.cpp.

186  {
187 }

Member Function Documentation

size_t proxygen::SPDYCodec::addPriorityNodes ( PriorityQueue ,
folly::IOBufQueue ,
uint8_t   
)
overridevirtual

Create virtual nodes in HTTP/2 priority tree. Some protocols (SPDY) have a linear priority structure which must be simulated in the HTTP/2 tree structure with "virtual" nodes representing different priority bands. There are other cases we simply want a "plain" linear priority structure even with HTTP/2. In that case a Priority frame will also be sent out for each virtual node created so that peer will have the same linear structure.

Parameters
queuethe priority queue to add nodes
writeBufIOBufQueue to append priority frames to send. For SPDY, the writeBuf will be ignored.
maxLavelthe max level of virtual priority nodes to create. For SPDY, this value will be ignored.

Reimplemented from proxygen::HTTPCodec.

Definition at line 1010 of file SPDYCodec.cpp.

References proxygen::HTTPCodec::PriorityQueue::addPriorityNode(), proxygen::HTTPCodec::MAX_STREAM_ID, parent, and uint8_t.

1013  {
1015  // For SPDY, we always create 8 virtual nodes regardless of maxLevel
1016  for (uint8_t pri = 0; pri < 8; pri++) {
1017  queue.addPriorityNode(HTTPCodec::MAX_STREAM_ID + pri, parent);
1018  parent = HTTPCodec::MAX_STREAM_ID + pri;
1019  }
1020  return 0;
1021 }
static const StreamID MAX_STREAM_ID
Definition: HTTPCodec.h:55
uint64_t StreamID
Definition: HTTPCodec.h:49
folly::Function< void()> parent
Definition: AtFork.cpp:34
void proxygen::SPDYCodec::checkLength ( uint32_t  expectedLength,
const std::string msg 
)
private

Definition at line 219 of file SPDYCodec.cpp.

References proxygen::ERROR, proxygen::spdy::GOAWAY_PROTOCOL_ERROR, and length_.

Referenced by onControlFrame().

219  {
220  if (length_ != expectedLength) {
221  LOG_IF(ERROR, length_ == 4 && msg != "GOAWAY")
222  << msg << ": invalid length " << length_ << " != " << expectedLength;
223  throw SPDYSessionFailed(spdy::GOAWAY_PROTOCOL_ERROR);
224  }
225 }
void proxygen::SPDYCodec::checkMinLength ( uint32_t  minLength,
const std::string msg 
)
private

Definition at line 227 of file SPDYCodec.cpp.

References proxygen::ERROR, proxygen::spdy::GOAWAY_PROTOCOL_ERROR, and length_.

Referenced by onControlFrame().

227  {
228  if (length_ < minLength) {
229  LOG(ERROR) << msg << ": invalid length " << length_ << " < " << minLength;
230  throw SPDYSessionFailed(spdy::GOAWAY_PROTOCOL_ERROR);
231  }
232 }
HeaderDecodeResult proxygen::SPDYCodec::decodeHeaders ( folly::io::Cursor cursor)
private

Decodes the headers from the cursor and returns the result.

Definition at line 466 of file SPDYCodec.cpp.

References proxygen::BAD_ENCODING, proxygen::GzipHeaderCodec::decode(), failStream(), proxygen::spdy::GOAWAY_PROTOCOL_ERROR, headerCodec_, proxygen::spdy::HEADERS, proxygen::HEADERS_TOO_LARGE, proxygen::INFLATE_DICTIONARY, length_, proxygen::spdy::RST_FRAME_TOO_LARGE, proxygen::spdy::RST_PROTOCOL_ERROR, streamId_, and type_.

Referenced by onControlFrame().

466  {
467  auto result = headerCodec_.decode(cursor, length_);
468  if (result.hasError()) {
469  auto err = result.error();
473  // Fail stream only for FRAME_TOO_LARGE error
476  }
477  throw SPDYSessionFailed(spdy::GOAWAY_PROTOCOL_ERROR);
478  }
479  // For other types of errors we throw a stream error
480  bool newStream = (type_ != spdy::HEADERS);
481  throw SPDYStreamFailed(newStream, streamId_, spdy::RST_PROTOCOL_ERROR,
482  "Error parsing header: " + folly::to<string>(err));
483  }
484 
485  length_ -= result->bytesConsumed;
486  return *result;
487 }
uint32_t streamId_
Definition: SPDYCodec.h:362
void failStream(bool newTxn, StreamID streamID, uint32_t code, std::string excStr=empty_string)
Definition: SPDYCodec.cpp:1444
GzipHeaderCodec headerCodec_
Definition: SPDYCodec.h:377
folly::Expected< HeaderDecodeResult, GzipDecodeError > decode(folly::io::Cursor &cursor, uint32_t length) noexcept
void proxygen::SPDYCodec::deliverOnMessageBegin ( StreamID  streamID,
StreamID  assocStreamID,
HTTPMessage msg 
)
private

Definition at line 1271 of file SPDYCodec.cpp.

References proxygen::HTTPParallelCodec::deliverCallbackIfAllowed(), proxygen::HTTPCodec::Callback::onMessageBegin(), and proxygen::HTTPCodec::Callback::onPushMessageBegin().

Referenced by onSynCommon(), and parseHeaders().

1272  {
1273  if (assocStreamID) {
1275  "onPushMessageBegin", streamID, assocStreamID,
1276  msg);
1277  } else {
1279  "onMessageBegin", streamID, msg);
1280  }
1281 }
virtual void onMessageBegin(StreamID stream, HTTPMessage *msg)=0
bool deliverCallbackIfAllowed(T callbackFn, char const *cbName, StreamID stream, Args &&...args)
virtual void onPushMessageBegin(StreamID, StreamID, HTTPMessage *)
Definition: HTTPCodec.h:95
uint32_t streamID
Definition: SPDYCodec.cpp:131
unique_ptr< IOBuf > proxygen::SPDYCodec::encodeHeaders ( const HTTPMessage msg,
std::vector< compress::Header > &  headers,
uint32_t  headroom = 0,
HTTPHeaderSize size = nullptr 
)
private

Helper function to create the compressed Name/Value representation of a message's headers.

Parameters
msgThe message containing headers to serialize.
headersA vector containing any extra headers to serialize
sizeSize of the serialized headers before and after compression
headroomOptional amount of headroom to reserve at the front of the returned IOBuf, in case the caller wants to put some other data there.

Definition at line 503 of file SPDYCodec.cpp.

References proxygen::GzipHeaderCodec::encode(), proxygen::HTTPHeaders::forEachWithCode(), proxygen::HeaderCodec::getEncodedSize(), proxygen::HTTPMessage::getHeaders(), headerCodec_, proxygen::HTTP_HEADER_CONNECTION, proxygen::HTTP_HEADER_HOST, proxygen::HTTP_HEADER_KEEP_ALIVE, proxygen::HTTP_HEADER_OTHER, proxygen::HTTP_HEADER_PROXY_CONNECTION, proxygen::HTTP_HEADER_TRANSFER_ENCODING, proxygen::HTTP_HEADER_UPGRADE, proxygen::spdy::httpVersion, isSPDYReserved(), proxygen::SPDYVersionSettings::majorVersion, name, proxygen::HeaderCodec::setEncodeHeadroom(), value, versionSettings_, and proxygen::SPDYVersionSettings::versionStr.

Referenced by serializeRequestHeaders(), and serializeResponseHeaders().

505  {
506 
507  // We explicitly provide both the code and header name here
508  // as HTTP_HEADER_OTHER does not map to kNameVersionv3 and we don't want a
509  // perf penalty hash kNameVersionv3 to HTTP_HEADER_OTHER
510  allHeaders.emplace_back(
512 
513  // Add the HTTP headers supplied by the caller, but skip
514  // any per-hop headers that aren't supported in SPDY.
515  msg.getHeaders().forEachWithCode([&] (HTTPHeaderCode code,
516  const string& name,
517  const string& value) {
518  static const std::bitset<256> s_perHopHeaderCodes{
519  [] {
520  std::bitset<256> bs;
521  // SPDY per-hop headers
522  bs[HTTP_HEADER_CONNECTION] = true;
523  bs[HTTP_HEADER_HOST] = true;
524  bs[HTTP_HEADER_KEEP_ALIVE] = true;
525  bs[HTTP_HEADER_PROXY_CONNECTION] = true;
527  bs[HTTP_HEADER_UPGRADE] = true;
528  return bs;
529  }()
530  };
531 
532  if (s_perHopHeaderCodes[code] || isSPDYReserved(name)) {
533  VLOG(3) << "Dropping SPDY reserved header " << name;
534  return;
535  }
536  if (name.length() == 0) {
537  VLOG(2) << "Dropping header with empty name";
538  return;
539  }
540  if (versionSettings_.majorVersion == 2 && value.length() == 0) {
541  VLOG(2) << "Dropping header \"" << name
542  << "\" with empty value for spdy/2";
543  return;
544  }
545  allHeaders.emplace_back(code, name, value);
546  });
547 
549  auto out = headerCodec_.encode(allHeaders);
550  if (size) {
552  }
553 
554  return out;
555 }
void setEncodeHeadroom(uint32_t headroom)
Definition: HeaderCodec.h:69
const char * name
Definition: http_parser.c:437
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
static const char *const value
Definition: Conv.cpp:50
const std::string httpVersion
GzipHeaderCodec headerCodec_
Definition: SPDYCodec.h:377
std::unique_ptr< folly::IOBuf > encode(std::vector< compress::Header > &headers) noexcept
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
const HTTPHeaderSize & getEncodedSize()
Definition: HeaderCodec.h:62
bool isSPDYReserved(const std::string &name)
Definition: SPDYCodec.cpp:489
void proxygen::SPDYCodec::failSession ( uint32_t  statusCode)
private

Definition at line 1474 of file SPDYCodec.cpp.

References proxygen::HTTPParallelCodec::callback_, folly::IOBuf::clone(), currentIngressBuf_, proxygen::spdy::goawayToErrorCode(), proxygen::HTTPException::INGRESS_AND_EGRESS, proxygen::kErrorParseHeader, proxygen::HTTPParallelCodec::lastStreamID_, proxygen::HTTPCodec::Callback::onError(), proxygen::HTTPException::setCodecStatusCode(), proxygen::HTTPException::setCurrentIngressBuf(), and proxygen::Exception::setProxygenError().

Referenced by onIngress().

1474  {
1475  HTTPException err(
1477  folly::to<std::string>("SPDYCodec session error: "
1478  "lastGoodStream=", lastStreamID_, " status=", code));
1479  err.setCodecStatusCode(spdy::goawayToErrorCode(spdy::GoawayStatusCode(code)));
1480  err.setProxygenError(kErrorParseHeader);
1481 
1482  // store the ingress buffer
1483  if (currentIngressBuf_) {
1484  err.setCurrentIngressBuf(currentIngressBuf_->clone());
1485  }
1486  callback_->onError(0, err);
1487 }
virtual void onError(StreamID stream, const HTTPException &error, bool newTxn=false)=0
const folly::IOBuf * currentIngressBuf_
Definition: SPDYCodec.h:355
HTTPCodec::Callback * callback_
std::unique_ptr< IOBuf > clone() const
Definition: IOBuf.cpp:527
ErrorCode goawayToErrorCode(GoawayStatusCode code)
void proxygen::SPDYCodec::failStream ( bool  newTxn,
StreamID  streamID,
uint32_t  code,
std::string  excStr = empty_string 
)
private

Definition at line 1444 of file SPDYCodec.cpp.

References proxygen::HTTPParallelCodec::callback_, folly::IOBuf::clone(), proxygen::spdy::CTRL_FLAG_FIN, currentIngressBuf_, flags_, proxygen::HTTPException::INGRESS, proxygen::HTTPException::INGRESS_AND_EGRESS, proxygen::kErrorParseHeader, folly::gen::move, proxygen::HTTPCodec::Callback::onError(), partialMsg_, proxygen::spdy::rstToErrorCode(), proxygen::HTTPException::setCodecStatusCode(), proxygen::HTTPException::setCurrentIngressBuf(), proxygen::HTTPException::setHttpStatusCode(), proxygen::HTTPException::setPartialMsg(), proxygen::Exception::setProxygenError(), and streamId_.

Referenced by decodeHeaders(), and parseIngress().

1445  {
1446  // Suppress any EOM callback for the current frame.
1447  if (streamID == streamId_) {
1448  flags_ &= ~spdy::CTRL_FLAG_FIN;
1449  }
1450 
1451  HTTPException err(
1452  code >= 100 ?
1455  folly::to<std::string>("SPDYCodec stream error: stream=",
1456  streamID, " status=", code, " exception: ", excStr));
1457  if (code >= 100) {
1458  err.setHttpStatusCode(code);
1459  } else {
1460  err.setCodecStatusCode(spdy::rstToErrorCode(spdy::ResetStatusCode(code)));
1461  }
1462  err.setProxygenError(kErrorParseHeader);
1463 
1464  if (partialMsg_) {
1465  err.setPartialMsg(std::move(partialMsg_));
1466  }
1467  // store the ingress buffer
1468  if (currentIngressBuf_) {
1469  err.setCurrentIngressBuf(currentIngressBuf_->clone());
1470  }
1471  callback_->onError(streamID, err, newStream);
1472 }
virtual void onError(StreamID stream, const HTTPException &error, bool newTxn=false)=0
uint32_t streamId_
Definition: SPDYCodec.h:362
const folly::IOBuf * currentIngressBuf_
Definition: SPDYCodec.h:355
HTTPCodec::Callback * callback_
std::unique_ptr< HTTPMessage > partialMsg_
Definition: SPDYCodec.h:353
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::unique_ptr< IOBuf > clone() const
Definition: IOBuf.cpp:527
uint32_t streamID
Definition: SPDYCodec.cpp:131
ErrorCode rstToErrorCode(uint32_t code)
size_t proxygen::SPDYCodec::generateBody ( folly::IOBufQueue writeBuf,
StreamID  stream,
std::unique_ptr< folly::IOBuf chain,
folly::Optional< uint8_t padding,
bool  eom 
)
overridevirtual

Write part of an egress message body.

This will automatically generate a chunk header and footer around the data if necessary (e.g. you haven't manually sent a chunk header and the message should be chunked).

Parameters
paddingOptionally add padding bytes to the body if possible
eomimplicitly generate the EOM marker with this body frame
Returns
number of bytes written

Implements proxygen::HTTPCodec.

Definition at line 765 of file SPDYCodec.cpp.

References folly::IOBuf::computeChainDataLength(), generateDataFrame(), proxygen::HTTPParallelCodec::ingressGoawayAck_, proxygen::HTTPParallelCodec::isStreamIngressEgressAllowed(), folly::gen::move, uint32_t, and uint8_t.

Referenced by TEST_F().

769  {
771  VLOG(2) << "Suppressing DATA for stream=" << stream <<
772  " ingressGoawayAck_=" << ingressGoawayAck_;
773  return 0;
774  }
775  size_t len = chain->computeChainDataLength();
776  if (len == 0) {
777  return len;
778  }
779 
780  // TODO if the data length is 2^24 or greater, split it into
781  // multiple data frames. Proxygen should never be writing that
782  // much data at once, but other apps that use this codec might.
783  CHECK_LT(len, (1 << 24));
784 
785  uint8_t flags = (eom) ? kFlagFin : 0;
786  generateDataFrame(writeBuf, uint32_t(stream), flags, len, std::move(chain));
787  return len;
788 }
flags
Definition: http_parser.h:127
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
bool isStreamIngressEgressAllowed(StreamID stream) const
std::size_t computeChainDataLength() const
Definition: IOBuf.cpp:501
size_t generateDataFrame(folly::IOBufQueue &writeBuf, uint32_t streamID, uint8_t flags, uint32_t length, std::unique_ptr< folly::IOBuf > payload)
Definition: SPDYCodec.cpp:1031
size_t proxygen::SPDYCodec::generateChunkHeader ( folly::IOBufQueue writeBuf,
StreamID  stream,
size_t  length 
)
overridevirtual

Write a body chunk header, if relevant.

Implements proxygen::HTTPCodec.

Definition at line 790 of file SPDYCodec.cpp.

792  {
793  // SPDY chunk headers are built into the data frames
794  return 0;
795 }
size_t proxygen::SPDYCodec::generateChunkTerminator ( folly::IOBufQueue writeBuf,
StreamID  stream 
)
overridevirtual

Write a body chunk terminator, if relevant.

Implements proxygen::HTTPCodec.

Definition at line 797 of file SPDYCodec.cpp.

798  {
799  // SPDY has no chunk terminator
800  return 0;
801 }
size_t proxygen::SPDYCodec::generateDataFrame ( folly::IOBufQueue writeBuf,
uint32_t  streamID,
uint8_t  flags,
uint32_t  length,
std::unique_ptr< folly::IOBuf payload 
)
private

Generate the header for a SPDY data frame

Parameters
writeBufBuffer queue to which the control frame is written.
streamIDStream ID.
flagsBitmap of flags, as defined in the SPDY spec.
lengthLength of the data, in bytes.
Returns
length Length of the encoded bytes
payload data payload

Definition at line 1031 of file SPDYCodec.cpp.

References folly::IOBufQueue::append(), folly::IOBuf::headroom(), folly::IOBuf::isSharedOne(), folly::IOBuf::length(), folly::gen::move, folly::IOBuf::pop(), folly::IOBufQueue::postallocate(), folly::IOBuf::retreat(), folly::IOBufQueue::tailroom(), folly::IOBuf::trimEnd(), uint32_t, uint64_t, and folly::io::detail::Writable< Derived >::writeBE().

Referenced by generateBody(), and generateEOM().

1034  {
1035  const size_t frameSize = kFrameSizeDataCommon;
1036  uint64_t payloadLength = 0;
1037  if (payload && !payload->isSharedOne() &&
1038  payload->headroom() >= frameSize &&
1039  writeBuf.tailroom() < frameSize) {
1040  // Use the headroom in payload for the frame header.
1041  // Make it appear that the payload IOBuf is empty and retreat so
1042  // appender can access the headroom
1043  payloadLength = payload->length();
1044  payload->trimEnd(payloadLength);
1045  payload->retreat(frameSize);
1046  auto tail = payload->pop();
1047  writeBuf.append(std::move(payload));
1048  payload = std::move(tail);
1049  }
1050  QueueAppender cursor(&writeBuf, frameSize);
1051  cursor.writeBE(uint32_t(streamID));
1052  cursor.writeBE(flagsAndLength(flags, length));
1053  writeBuf.postallocate(payloadLength);
1054  writeBuf.append(std::move(payload));
1055  return kFrameSizeDataCommon + length;
1056 }
void append(std::unique_ptr< folly::IOBuf > &&buf, bool pack=false)
Definition: IOBufQueue.cpp:143
flags
Definition: http_parser.h:127
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
bool isSharedOne() const
Definition: IOBuf.h:952
size_t tailroom() const
Definition: IOBufQueue.h:403
std::unique_ptr< IOBuf > pop()
Definition: IOBuf.h:859
std::size_t headroom() const
Definition: IOBuf.h:542
std::size_t length() const
Definition: IOBuf.h:533
void retreat(std::size_t amount)
Definition: IOBuf.h:653
void postallocate(std::size_t n)
Definition: IOBufQueue.h:380
void trimEnd(std::size_t amount)
Definition: IOBuf.h:718
uint32_t streamID
Definition: SPDYCodec.cpp:131
size_t proxygen::SPDYCodec::generateEOM ( folly::IOBufQueue writeBuf,
StreamID  stream 
)
overridevirtual

Generate any protocol framing needed to finalize an egress message. This method must be called to complete a stream.

Returns
number of bytes written

Implements proxygen::HTTPCodec.

Definition at line 812 of file SPDYCodec.cpp.

References generateDataFrame(), proxygen::HTTPParallelCodec::ingressGoawayAck_, proxygen::HTTPParallelCodec::isStreamIngressEgressAllowed(), stream, and uint32_t.

Referenced by TEST().

813  {
814  VLOG(4) << "sending EOM for stream=" << stream;
816  VLOG(2) << "Suppressing EOM for stream=" << stream <<
817  " ingressGoawayAck_=" << ingressGoawayAck_;
818  return 0;
819  }
820  generateDataFrame(writeBuf, uint32_t(stream), kFlagFin, 0, nullptr);
821  return 8; // size of data frame header
822 }
StreamCodecFactory stream
bool isStreamIngressEgressAllowed(StreamID stream) const
size_t generateDataFrame(folly::IOBufQueue &writeBuf, uint32_t streamID, uint8_t flags, uint32_t length, std::unique_ptr< folly::IOBuf > payload)
Definition: SPDYCodec.cpp:1031
size_t proxygen::SPDYCodec::generateGoaway ( folly::IOBufQueue writeBuf,
StreamID  lastStream,
ErrorCode  code,
std::unique_ptr< folly::IOBuf debugData = nullptr 
)
overridevirtual

Generate any protocol framing needed to abort a connection.

Returns
number of bytes written

Implements proxygen::HTTPCodec.

Definition at line 856 of file SPDYCodec.cpp.

References folly::IOBufQueue::chainLength(), proxygen::SPDYVersionSettings::controlVersion, folly::IOBuf::data(), proxygen::HTTPParallelCodec::egressGoawayAck_, proxygen::spdy::errorCodeToGoaway(), proxygen::getErrorCodeString(), proxygen::spdy::GOAWAY, proxygen::SPDYVersionSettings::goawaySize, proxygen::SPDYVersionSettings::majorVersion, max, proxygen::NO_ERROR, proxygen::HTTPParallelCodec::sessionClosing_, statusCode, uint16_t, uint32_t, versionSettings_, and folly::io::detail::Writable< Derived >::writeBE().

Referenced by TEST(), and TEST_F().

859  {
861  const size_t frameSize = kFrameSizeControlCommon +
863 
864  DCHECK_LE(lastStream, egressGoawayAck_) << "Cannot increase last good stream";
865  egressGoawayAck_ = lastStream;
866  if (sessionClosing_ == ClosingState::CLOSING) {
867  VLOG(4) << "Not sending GOAWAY for closed session";
868  return 0;
869  }
870  const size_t expectedLength = writeBuf.chainLength() + frameSize;
871  QueueAppender appender(&writeBuf, frameSize);
872  appender.writeBE(versionSettings_.controlVersion);
873 
874  if (code != ErrorCode::NO_ERROR) {
875  sessionClosing_ = ClosingState::CLOSING;
876  }
877 
878  string debugInfo = (debugData) ?
879  folly::to<string>(" with debug info=",
880  (char*)debugData->data()) : "";
881  VLOG(4) << "Sending GOAWAY with last acknowledged stream="
882  << lastStream << " with code=" << getErrorCodeString(code)
883  << debugInfo;
884 
885  appender.writeBE(uint16_t(spdy::GOAWAY));
886  appender.writeBE(flagsAndLength(0, versionSettings_.goawaySize));
887  appender.writeBE(uint32_t(lastStream));
888  if (versionSettings_.majorVersion == 3) {
889  appender.writeBE(statusCode);
890  }
891  switch (sessionClosing_) {
892  case ClosingState::OPEN:
893  sessionClosing_ = ClosingState::CLOSING;
894  break;
895  case ClosingState::OPEN_WITH_GRACEFUL_DRAIN_ENABLED:
896  if (lastStream == std::numeric_limits<int32_t>::max()) {
897  sessionClosing_ = ClosingState::FIRST_GOAWAY_SENT;
898  } else {
899  // The user of this codec decided not to do the double goaway
900  // drain
901  sessionClosing_ = ClosingState::CLOSING;
902  }
903  break;
904  case ClosingState::FIRST_GOAWAY_SENT:
905  sessionClosing_ = ClosingState::CLOSING;
906  break;
907  case ClosingState::CLOSING:
908  break;
909  case ClosingState::CLOSED:
910  LOG(FATAL) << "unreachable";
911  break;
912  }
913  DCHECK_EQ(writeBuf.chainLength(), expectedLength);
914  return frameSize;
915 }
size_t chainLength() const
Definition: IOBufQueue.h:492
spdy::GoawayStatusCode statusCode
Definition: SPDYCodec.cpp:110
LogLevel max
Definition: LogLevel.cpp:31
const uint8_t * data() const
Definition: IOBuf.h:499
enum proxygen::HTTPParallelCodec::ClosingState sessionClosing_
const char * getErrorCodeString(ErrorCode error)
Definition: ErrorCode.cpp:18
GoawayStatusCode errorCodeToGoaway(ErrorCode code)
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
void proxygen::SPDYCodec::generateHeader ( folly::IOBufQueue writeBuf,
StreamID  stream,
const HTTPMessage msg,
bool  eom = false,
HTTPHeaderSize size = nullptr 
)
overridevirtual

Write an egress message header. For pushed streams, you must specify the assocStream.

Return values
sizethe size of the generated message, both the actual size and the size of the uncompressed data.
Returns
None

Implements proxygen::HTTPCodec.

Definition at line 625 of file SPDYCodec.cpp.

References wangle::HTTPHeaderSize::compressed, generateSynReply(), generateSynStream(), proxygen::HTTPParallelCodec::ingressGoawayAck_, proxygen::HTTPParallelCodec::isStreamIngressEgressAllowed(), proxygen::HTTPParallelCodec::transportDirection_, wangle::HTTPHeaderSize::uncompressed, and proxygen::UPSTREAM.

Referenced by TEST_F().

629  {
631  VLOG(2) << "Suppressing SYN_STREAM/REPLY for stream=" << stream <<
632  " ingressGoawayAck_=" << ingressGoawayAck_;
633  if (size) {
634  size->compressed = 0;
635  size->uncompressed = 0;
636  }
637  return;
638  }
640  generateSynStream(stream, 0, writeBuf, msg, eom, size);
641  } else {
642  generateSynReply(stream, writeBuf, msg, eom, size);
643  }
644 }
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
void generateSynStream(StreamID stream, StreamID assocStream, folly::IOBufQueue &writeBuf, const HTTPMessage &msg, bool eom, HTTPHeaderSize *size)
Definition: SPDYCodec.cpp:665
bool isStreamIngressEgressAllowed(StreamID stream) const
TransportDirection transportDirection_
void generateSynReply(StreamID stream, folly::IOBufQueue &writeBuf, const HTTPMessage &msg, bool eom, HTTPHeaderSize *size)
Definition: SPDYCodec.cpp:724
size_t proxygen::SPDYCodec::generatePingCommon ( folly::IOBufQueue writeBuf,
uint64_t  uniqueID 
)
private

Generates the shared parts of a ping request and reply.

Definition at line 929 of file SPDYCodec.cpp.

References folly::IOBufQueue::chainLength(), proxygen::SPDYVersionSettings::controlVersion, proxygen::spdy::PING, uint16_t, uint32_t, versionSettings_, and folly::io::detail::Writable< Derived >::writeBE().

Referenced by generatePingReply(), and generatePingRequest().

929  {
930  const size_t frameSize = kFrameSizeControlCommon + kFrameSizePing;
931  const size_t expectedLength = writeBuf.chainLength() + frameSize;
932  QueueAppender appender(&writeBuf, frameSize);
933  appender.writeBE(versionSettings_.controlVersion);
934  appender.writeBE(uint16_t(spdy::PING));
935  appender.writeBE(flagsAndLength(0, kFrameSizePing));
936  appender.writeBE(uint32_t(uniqueID));
937  DCHECK_EQ(writeBuf.chainLength(), expectedLength);
938  return frameSize;
939 }
size_t chainLength() const
Definition: IOBufQueue.h:492
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
size_t proxygen::SPDYCodec::generatePingReply ( folly::IOBufQueue ,
uint64_t   
)
overridevirtual

Generate a reply to a ping message, if supported in the protocol implemented by the codec.

Reimplemented from proxygen::HTTPCodec.

Definition at line 924 of file SPDYCodec.cpp.

References generatePingCommon().

Referenced by TEST().

924  {
925  VLOG(4) << "Generating ping reply with id=" << uniqueID;
926  return generatePingCommon(writeBuf, uniqueID);
927 }
void writeBuf(const Buf &buf, folly::io::Appender &out)
size_t generatePingCommon(folly::IOBufQueue &writeBuf, uint64_t uniqueID)
Definition: SPDYCodec.cpp:929
size_t proxygen::SPDYCodec::generatePingRequest ( folly::IOBufQueue )
overridevirtual

If the protocol supports it, generate a ping message that the other side should respond to.

Reimplemented from proxygen::HTTPCodec.

Definition at line 917 of file SPDYCodec.cpp.

References generatePingCommon(), and nextEgressPingID_.

Referenced by TEST().

917  {
918  const auto id = nextEgressPingID_;
919  nextEgressPingID_ += 2;
920  VLOG(4) << "Generating ping request with id=" << id;
921  return generatePingCommon(writeBuf, id);
922 }
void writeBuf(const Buf &buf, folly::io::Appender &out)
StreamID nextEgressPingID_
Definition: SPDYCodec.h:357
size_t generatePingCommon(folly::IOBufQueue &writeBuf, uint64_t uniqueID)
Definition: SPDYCodec.cpp:929
void proxygen::SPDYCodec::generatePushPromise ( folly::IOBufQueue writeBuf,
StreamID  stream,
const HTTPMessage msg,
StreamID  assocstream,
bool  eom = false,
HTTPHeaderSize size = nullptr 
)
overridevirtual

Reimplemented from proxygen::HTTPCodec.

Definition at line 646 of file SPDYCodec.cpp.

References wangle::HTTPHeaderSize::compressed, generateSynStream(), proxygen::HTTPParallelCodec::ingressGoawayAck_, proxygen::HTTPParallelCodec::isStreamIngressEgressAllowed(), NoStream, and wangle::HTTPHeaderSize::uncompressed.

Referenced by TEST_F().

651  {
652  DCHECK(assocStream != NoStream);
654  VLOG(2) << "Suppressing SYN_STREAM/REPLY for stream=" << stream <<
655  " ingressGoawayAck_=" << ingressGoawayAck_;
656  if (size) {
657  size->compressed = 0;
658  size->uncompressed = 0;
659  }
660  return;
661  }
662  generateSynStream(stream, assocStream, writeBuf, msg, eom, size);
663 }
static const StreamID NoStream
Definition: SPDYCodec.h:38
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
void generateSynStream(StreamID stream, StreamID assocStream, folly::IOBufQueue &writeBuf, const HTTPMessage &msg, bool eom, HTTPHeaderSize *size)
Definition: SPDYCodec.cpp:665
bool isStreamIngressEgressAllowed(StreamID stream) const
size_t proxygen::SPDYCodec::generateRstStream ( folly::IOBufQueue writeBuf,
StreamID  stream,
ErrorCode  code 
)
overridevirtual

Generate any protocol framing needed to abort a stream.

Returns
number of bytes written

Implements proxygen::HTTPCodec.

Definition at line 824 of file SPDYCodec.cpp.

References folly::IOBufQueue::chainLength(), proxygen::SPDYVersionSettings::controlVersion, proxygen::spdy::CTRL_FLAG_FIN, proxygen::spdy::errorCodeToReset(), flags_, proxygen::getErrorCodeString(), proxygen::HTTPParallelCodec::ingressGoawayAck_, proxygen::HTTPParallelCodec::isStreamIngressEgressAllowed(), proxygen::spdy::RST_PROTOCOL_ERROR, proxygen::spdy::RST_STREAM, rstStatusSupported(), statusCode, streamId_, uint16_t, uint32_t, versionSettings_, and folly::io::detail::Writable< Derived >::writeBE().

Referenced by TEST().

826  {
827  DCHECK_GT(stream, 0);
828  VLOG(4) << "sending RST_STREAM for stream=" << stream
829  << " with code=" << getErrorCodeString(code);
830 
831  // Suppress any EOM callback for the current frame.
832  if (stream == streamId_) {
833  flags_ &= ~spdy::CTRL_FLAG_FIN;
834  }
835 
837  VLOG(2) << "Suppressing RST_STREAM for stream=" << stream <<
838  " ingressGoawayAck_=" << ingressGoawayAck_;
839  return 0;
840  }
841 
843  const size_t frameSize = kFrameSizeControlCommon + kFrameSizeRstStream;
844  const size_t expectedLength = writeBuf.chainLength() + frameSize;
845  QueueAppender appender(&writeBuf, frameSize);
846  appender.writeBE(versionSettings_.controlVersion);
847  appender.writeBE(uint16_t(spdy::RST_STREAM));
848  appender.writeBE(flagsAndLength(0, kFrameSizeRstStream));
849  appender.writeBE(uint32_t(stream));
850  appender.writeBE(rstStatusSupported(statusCode) ?
851  statusCode : (uint32_t)spdy::RST_PROTOCOL_ERROR);
852  DCHECK_EQ(writeBuf.chainLength(), expectedLength);
853  return frameSize;
854 }
size_t chainLength() const
Definition: IOBufQueue.h:492
spdy::GoawayStatusCode statusCode
Definition: SPDYCodec.cpp:110
uint32_t streamId_
Definition: SPDYCodec.h:362
ResetStatusCode errorCodeToReset(ErrorCode code)
bool rstStatusSupported(int statusCode) const
Definition: SPDYCodec.cpp:1489
const char * getErrorCodeString(ErrorCode error)
Definition: ErrorCode.cpp:18
bool isStreamIngressEgressAllowed(StreamID stream) const
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
size_t proxygen::SPDYCodec::generateSettings ( folly::IOBufQueue )
overridevirtual

Generate a settings message, if supported in the protocol implemented by the codec.

Reimplemented from proxygen::HTTPCodec.

Definition at line 941 of file SPDYCodec.cpp.

References folly::IOBufQueue::chainLength(), proxygen::SPDYVersionSettings::controlVersion, egressSettings_, proxygen::spdy::FLAG_SETTINGS_CLEAR_SETTINGS, proxygen::HTTPSettings::getAllSettings(), proxygen::HTTPSettings::getNumSettings(), proxygen::spdy::httpToSpdySettingsId(), proxygen::SPDYVersionSettings::majorVersion, proxygen::spdy::SETTINGS, uint16_t, uint32_t, versionSettings_, folly::io::detail::Writable< Derived >::writeBE(), and folly::io::detail::Writable< Derived >::writeLE().

Referenced by TEST().

941  {
942  auto numSettings = egressSettings_.getNumSettings();
943  for (const auto& setting: egressSettings_.getAllSettings()) {
944  if (!spdy::httpToSpdySettingsId(setting.id)) {
945  numSettings--;
946  }
947  }
948  VLOG(4) << "generating " << (unsigned)numSettings << " settings";
949  const size_t frameSize = kFrameSizeControlCommon + kFrameSizeSettings +
950  (kFrameSizeSettingsEntry * numSettings);
951  const size_t expectedLength = writeBuf.chainLength() + frameSize;
952  QueueAppender appender(&writeBuf, frameSize);
953  appender.writeBE(versionSettings_.controlVersion);
954  appender.writeBE(uint16_t(spdy::SETTINGS));
955  appender.writeBE(flagsAndLength(spdy::FLAG_SETTINGS_CLEAR_SETTINGS,
956  kFrameSizeSettings +
957  kFrameSizeSettingsEntry * numSettings));
958  appender.writeBE(uint32_t(numSettings));
959  for (const auto& setting: egressSettings_.getAllSettings()) {
960  auto settingId = spdy::httpToSpdySettingsId(setting.id);
961  if (!settingId) {
962  LOG(WARNING) << "Invalid SpdySetting " << (uint32_t)setting.id;
963  continue;
964  }
965  VLOG(5) << " writing setting with id=" << *settingId
966  << ", value=" << setting.value;
967  if (versionSettings_.majorVersion == 2) {
968  // ID: 24-bits in little-endian byte order.
969  // This is inconsistent with other values in SPDY and
970  // is the result of a bug in the initial v2 implementation.
971  appender.writeLE(flagsAndLength(0, *settingId));
972  } else {
973  appender.writeBE(flagsAndLength(0, *settingId));
974  }
975  appender.writeBE<uint32_t>(setting.value);
976  }
977  DCHECK_EQ(writeBuf.chainLength(), expectedLength);
978  return frameSize;
979 }
std::size_t getNumSettings() const
Definition: HTTPSettings.h:58
void writeBuf(const Buf &buf, folly::io::Appender &out)
folly::Optional< proxygen::spdy::SettingsId > httpToSpdySettingsId(proxygen::SettingsId id)
const std::vector< HTTPSetting > & getAllSettings()
Definition: HTTPSettings.h:61
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
HTTPSettings egressSettings_
Definition: SPDYCodec.h:348
void proxygen::SPDYCodec::generateSynReply ( StreamID  stream,
folly::IOBufQueue writeBuf,
const HTTPMessage msg,
bool  eom,
HTTPHeaderSize size 
)
private

Generates a frame of type SYN_REPLY

Definition at line 724 of file SPDYCodec.cpp.

References folly::IOBufQueue::append(), folly::IOBuf::computeChainDataLength(), proxygen::SPDYVersionSettings::controlVersion, proxygen::spdy::CTRL_FLAG_FIN, proxygen::spdy::CTRL_FLAG_NONE, proxygen::SPDYVersionSettings::majorVersion, folly::gen::move, folly::IOBuf::prepend(), serializeResponseHeaders(), proxygen::spdy::SYN_REPLY, proxygen::SPDYVersionSettings::synReplySize, uint16_t, uint32_t, uint8_t, and versionSettings_.

Referenced by generateHeader().

728  {
729  // Serialize the compressed representation of the headers
730  // first because we need to write its length. The
731  // serializeResponseHeaders() method allocates an IOBuf to
732  // hold the headers, but we can tell it to reserve
733  // enough headroom at the start of the IOBuf to hold
734  // the metadata we'll need to add once we know the
735  // length.
736  uint32_t headroom = kFrameSizeControlCommon + versionSettings_.synReplySize;
737  unique_ptr<IOBuf> out(serializeResponseHeaders(msg, headroom, size));
738 
739  // The length field in the SYN_REPLY header holds the number
740  // of bytes that follow it. That's the length of the fields
741  // specific to the SYN_REPLY message (all of which come after
742  // the length field) plus the length of the serialized header
743  // name/value block.
744  uint32_t len = versionSettings_.synReplySize + out->computeChainDataLength();
745 
746  // Generate a control frame header of type SYN_REPLY within
747  // the headroom that we serializeResponseHeaders() reserved for us
748  // at the start of the IOBuf.1
750  out->prepend(headroom);
751  RWPrivateCursor cursor(out.get());
752  cursor.writeBE(versionSettings_.controlVersion);
753  cursor.writeBE(uint16_t(spdy::SYN_REPLY));
754  cursor.writeBE(flagsAndLength(flags, len));
755  cursor.writeBE(uint32_t(stream)); // TODO: stream should never be bigger than 2^31
756  if (versionSettings_.majorVersion == 2) {
757  cursor.writeBE(uint16_t(0));
758  }
759 
760  // Now that we have a complete SYN_REPLY control frame, append
761  // it to the writeBuf.
762  writeBuf.append(std::move(out));
763 }
void append(std::unique_ptr< folly::IOBuf > &&buf, bool pack=false)
Definition: IOBufQueue.cpp:143
flags
Definition: http_parser.h:127
std::unique_ptr< folly::IOBuf > serializeResponseHeaders(const HTTPMessage &msg, uint32_t headroom=0, HTTPHeaderSize *size=nullptr)
Definition: SPDYCodec.cpp:557
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
RWCursor< CursorAccess::PRIVATE > RWPrivateCursor
Definition: Cursor.h:958
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
void proxygen::SPDYCodec::generateSynStream ( StreamID  stream,
StreamID  assocStream,
folly::IOBufQueue writeBuf,
const HTTPMessage msg,
bool  eom,
HTTPHeaderSize size 
)
private

Generates a frame of type SYN_STREAM

Definition at line 665 of file SPDYCodec.cpp.

References folly::IOBufQueue::append(), folly::IOBuf::computeChainDataLength(), proxygen::SPDYVersionSettings::controlVersion, proxygen::spdy::CTRL_FLAG_FIN, proxygen::spdy::CTRL_FLAG_NONE, proxygen::spdy::CTRL_FLAG_UNIDIRECTIONAL, proxygen::HTTPMessage::getPriority(), proxygen::SPDYVersionSettings::majorVersion, folly::gen::move, NoStream, folly::IOBuf::prepend(), proxygen::SPDYVersionSettings::priShift, serializeRequestHeaders(), proxygen::spdy::SYN_STREAM, uint16_t, uint32_t, uint8_t, and versionSettings_.

Referenced by generateHeader(), and generatePushPromise().

670  {
671  // Pushed streams must have an even streamId and an odd assocStream
672  CHECK((assocStream == NoStream && (stream % 2 == 1)) ||
673  ((stream % 2 == 0) && (assocStream % 2 == 1))) <<
674  "Invalid stream ids stream=" << stream << " assocStream=" << assocStream;
675 
676  // Serialize the compressed representation of the headers
677  // first because we need to write its length. The
678  // serializeRequestHeaders() method allocates an IOBuf to
679  // hold the headers, but we can tell it to reserve
680  // enough headroom at the start of the IOBuf to hold
681  // the metadata we'll need to add once we know the
682  // length.
683  uint32_t fieldsSize = kFrameSizeSynStream;
684  uint32_t headroom = kFrameSizeControlCommon + fieldsSize;
685  bool isPushed = (assocStream != NoStream);
686  unique_ptr<IOBuf> out(serializeRequestHeaders(msg, isPushed,
687  headroom, size));
688 
689  // The length field in the SYN_STREAM header holds the number
690  // of bytes that follow it. That's the length of the fields
691  // specific to the SYN_STREAM message (all of which come after
692  // the length field) plus the length of the serialized header
693  // name/value block.
694  uint32_t len = fieldsSize + out->computeChainDataLength();
695 
696  // Generate a control frame header of type SYN_STREAM within
697  // the headroom that serializeRequestHeaders() reserved for us
698  // at the start of the IOBuf.
700  if (assocStream != NoStream) {
702  }
703  if (eom) {
704  flags |= spdy::CTRL_FLAG_FIN;
705  }
706  out->prepend(headroom);
707  RWPrivateCursor cursor(out.get());
708  cursor.writeBE(versionSettings_.controlVersion);
709  cursor.writeBE(uint16_t(spdy::SYN_STREAM));
710  cursor.writeBE(flagsAndLength(flags, len));
711  cursor.writeBE(uint32_t(stream));
712  cursor.writeBE(uint32_t(assocStream));
713  // If the message set HTTP/2 priority instead of SPDY priority, we lose
714  // priority information since we can't collapse it.
715  // halve priority for SPDY/2
716  uint8_t pri = msg.getPriority() >> (3 - versionSettings_.majorVersion);
717  cursor.writeBE(uint16_t(pri << (versionSettings_.priShift + 8)));
718 
719  // Now that we have a complete SYN_STREAM control frame, append
720  // it to the writeBuf.
721  writeBuf.append(std::move(out));
722 }
void append(std::unique_ptr< folly::IOBuf > &&buf, bool pack=false)
Definition: IOBufQueue.cpp:143
flags
Definition: http_parser.h:127
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::unique_ptr< folly::IOBuf > serializeRequestHeaders(const HTTPMessage &msg, bool isPushed, uint32_t headroom=0, HTTPHeaderSize *size=nullptr)
Definition: SPDYCodec.cpp:587
static const StreamID NoStream
Definition: SPDYCodec.h:38
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
RWCursor< CursorAccess::PRIVATE > RWPrivateCursor
Definition: Cursor.h:958
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
size_t proxygen::SPDYCodec::generateTrailers ( folly::IOBufQueue writeBuf,
StreamID  stream,
const HTTPHeaders trailers 
)
overridevirtual

Write the message trailers

Returns
number of bytes written

Implements proxygen::HTTPCodec.

Definition at line 803 of file SPDYCodec.cpp.

805  {
806  // TODO generate a HEADERS frame? An additional HEADERS frame
807  // somewhere after the SYN_REPLY seems to be the SPDY equivalent
808  // of HTTP/1.1's trailers.
809  return 0;
810 }
size_t proxygen::SPDYCodec::generateWindowUpdate ( folly::IOBufQueue writeBuf,
StreamID  stream,
uint32_t  delta 
)
overridevirtual

Reimplemented from proxygen::HTTPCodec.

Definition at line 981 of file SPDYCodec.cpp.

References folly::IOBufQueue::chainLength(), proxygen::SPDYVersionSettings::controlVersion, proxygen::HTTPParallelCodec::ingressGoawayAck_, proxygen::HTTPParallelCodec::isStreamIngressEgressAllowed(), proxygen::SPDYVersionSettings::majorVersion, proxygen::SPDYVersionSettings::minorVersion, NoStream, uint16_t, uint32_t, versionSettings_, proxygen::spdy::WINDOW_UPDATE, and folly::io::detail::Writable< Derived >::writeBE().

983  {
984  if (versionSettings_.majorVersion < 3 ||
987  return 0;
988  }
989 
991  VLOG(2) << "Suppressing WINDOW_UPDATE for stream=" << stream <<
992  " ingressGoawayAck_=" << ingressGoawayAck_;
993  return 0;
994  }
995 
996  VLOG(4) << "generating window update for stream=" << stream
997  << ": Processed " << delta << " bytes";
998  const size_t frameSize = kFrameSizeControlCommon + kFrameSizeWindowUpdate;
999  const size_t expectedLength = writeBuf.chainLength() + frameSize;
1000  QueueAppender appender(&writeBuf, frameSize);
1001  appender.writeBE(versionSettings_.controlVersion);
1002  appender.writeBE(uint16_t(spdy::WINDOW_UPDATE));
1003  appender.writeBE(flagsAndLength(0, kFrameSizeWindowUpdate));
1004  appender.writeBE(uint32_t(stream)); // TODO: ensure stream < 2^31
1005  appender.writeBE(delta); // TODO: delta should never be bigger than 2^31
1006  DCHECK_EQ(writeBuf.chainLength(), expectedLength);
1007  return frameSize;
1008 }
size_t chainLength() const
Definition: IOBufQueue.h:492
static const StreamID NoStream
Definition: SPDYCodec.h:38
bool isStreamIngressEgressAllowed(StreamID stream) const
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
uint32_t proxygen::SPDYCodec::getDefaultWindowSize ( ) const
inlineoverridevirtual

Get the default size of flow control windows for this protocol

Reimplemented from proxygen::HTTPCodec.

Definition at line 108 of file SPDYCodec.h.

References proxygen::http2::kInitialWindow, uint32_t, and uint8_t.

108  {
109  return spdy::kInitialWindow;
110  }
const uint32_t kInitialWindow
HTTPSettings* proxygen::SPDYCodec::getEgressSettings ( )
inlineoverridevirtual

Returns a reference to the egress settings

Reimplemented from proxygen::HTTPCodec.

Definition at line 107 of file SPDYCodec.h.

Referenced by TEST().

107 { return &egressSettings_; }
HTTPSettings egressSettings_
Definition: SPDYCodec.h:348
const HTTPSettings* proxygen::SPDYCodec::getIngressSettings ( ) const
inlineoverridevirtual

Returns a const reference to the ingress settings. Since ingress settings are set by the remote end, it doesn't make sense for these to be mutable outside the codec.

Reimplemented from proxygen::HTTPCodec.

Definition at line 101 of file SPDYCodec.h.

101  {
102  return &ingressSettings_;
103  }
HTTPSettings ingressSettings_
Definition: SPDYCodec.h:344
uint8_t proxygen::SPDYCodec::getMinorVersion ( ) const

Definition at line 1027 of file SPDYCodec.cpp.

References proxygen::SPDYVersionSettings::minorVersion, and versionSettings_.

1027  {
1029 }
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
CodecProtocol proxygen::SPDYCodec::getProtocol ( ) const
overridevirtual

Gets the session protocol currently used by the codec. This can be mapped to a string for logging and diagnostic use.

Implements proxygen::HTTPCodec.

Definition at line 197 of file SPDYCodec.cpp.

References proxygen::SPDY3, proxygen::SPDY3_1, proxygen::SPDY_3, proxygen::SPDY_3_1, proxygen::SPDYVersionSettings::version, and versionSettings_.

Referenced by TEST().

const std::string & proxygen::SPDYCodec::getUserAgent ( ) const
overridevirtual

Gets the user agent string of the client. Thus, it is only meaningful for a DOWNSTREAM session. Note that the value is available after onHeadersComplete(). It can help in diagnosing the interactions between different codec implementation.

Implements proxygen::HTTPCodec.

Definition at line 206 of file SPDYCodec.cpp.

References userAgent_.

206  {
207  return userAgent_;
208 }
std::string userAgent_
Definition: SPDYCodec.h:354
folly::Optional< SPDYVersion > proxygen::SPDYCodec::getVersion ( const std::string protocol)
static

Returns the SPDYVersion for the given protocol string, or none otherwise.

Definition at line 1501 of file SPDYCodec.cpp.

References folly::none, proxygen::SPDY3, and proxygen::SPDY3_1.

1501  {
1502  // Fail fast if it's not possible for the protocol string to define a
1503  // SPDY protocol. strlen("spdy/1") == 6
1504  if (protocol.length() < 6) {
1505  return folly::none;
1506  }
1507 
1508  if (protocol == "spdy/3.1") {
1509  return SPDYVersion::SPDY3_1;
1510  }
1511  if (protocol == "spdy/3") {
1512  return SPDYVersion::SPDY3;
1513  }
1514 
1515  return folly::none;
1516 }
constexpr None none
Definition: Optional.h:87
const SPDYVersionSettings & proxygen::SPDYCodec::getVersionSettings ( SPDYVersion  version)
static

Definition at line 138 of file SPDYCodec.cpp.

References proxygen::spdy::kNameHostv3, proxygen::spdy::kNameMethodv3, proxygen::spdy::kNamePathv3, proxygen::spdy::kNameSchemev3, proxygen::spdy::kNameStatusv3, proxygen::spdy::kNameVersionv3, proxygen::spdy::kSessionProtoNameSPDY3, proxygen::kSPDYv3Dictionary, proxygen::spdy::kVersionStrv3, proxygen::spdy::kVersionStrv31, proxygen::SPDY3, proxygen::SPDY3_1, and version.

138  {
139  // XXX: We new and leak the static here intentionally so it doesn't get
140  // destroyed during a call to exit() when threads are still processing
141  // requests resulting in spurious shutdown crashes.
142 
143  // Indexed by SPDYVersion
144  static const auto spdyVersions = new std::vector<SPDYVersionSettings> {
145  // SPDY2 no longer supported; should it ever be added back the lines in which
146  // this codec creates compress/Header objects need to be updated as SPDY2
147  // constant header names are different from the set of common header names.
148  // SPDY3
151  spdy::kSessionProtoNameSPDY3, parseUint32, appendUint32,
152  (const unsigned char*)kSPDYv3Dictionary, sizeof(kSPDYv3Dictionary),
153  0x8003, kFrameSizeSynReplyv3, kFrameSizeNameValuev3,
154  kFrameSizeGoawayv3, kPriShiftv3, 3, 0, SPDYVersion::SPDY3,
156  // SPDY3.1
159  spdy::kSessionProtoNameSPDY3, parseUint32, appendUint32,
160  (const unsigned char*)kSPDYv3Dictionary, sizeof(kSPDYv3Dictionary),
161  0x8003, kFrameSizeSynReplyv3, kFrameSizeNameValuev3,
162  kFrameSizeGoawayv3, kPriShiftv3, 3, 1, SPDYVersion::SPDY3_1,
164  };
165  auto intVersion = static_cast<unsigned>(version);
166  CHECK_LT(intVersion, spdyVersions->size());
167  return (*spdyVersions)[intVersion];
168 }
const std::string kVersionStrv3
const std::string kSessionProtoNameSPDY3
const std::string kNamePathv3
const unsigned char kSPDYv3Dictionary[]
const std::string kVersionStrv31
ProtocolVersion version
const std::string kNameMethodv3
const std::string kNameVersionv3
const std::string kNameHostv3
const std::string kNameStatusv3
const std::string kNameSchemev3
bool proxygen::SPDYCodec::isSPDYReserved ( const std::string name)
private

Definition at line 489 of file SPDYCodec.cpp.

References proxygen::caseInsensitiveEqual(), proxygen::DOWNSTREAM, proxygen::spdy::kNameMethodv2, proxygen::spdy::kNamePathv2, proxygen::spdy::kNameSchemev2, proxygen::spdy::kNameStatusv2, proxygen::spdy::kNameVersionv2, proxygen::SPDYVersionSettings::majorVersion, proxygen::HTTPParallelCodec::transportDirection_, proxygen::UPSTREAM, and versionSettings_.

Referenced by encodeHeaders().

489  {
490  return (versionSettings_.majorVersion == 2 &&
499 }
bool caseInsensitiveEqual(folly::StringPiece s, folly::StringPiece t)
Definition: UtilInl.h:17
const std::string kNameMethodv2
const char * name
Definition: http_parser.c:437
const std::string kNameStatusv2
const std::string kNameSchemev2
const std::string kNamePathv2
const std::string kNameVersionv2
TransportDirection transportDirection_
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
int8_t proxygen::SPDYCodec::mapDependencyToPriority ( StreamID  ) const
inlineoverridevirtual

Map the parent back to the priority, -1 if this doesn't make sense.

Reimplemented from proxygen::HTTPCodec.

Definition at line 136 of file SPDYCodec.h.

136  {
137  if (parent >= MAX_STREAM_ID) {
138  return parent - MAX_STREAM_ID;
139  }
140  return -1;
141  }
static const StreamID MAX_STREAM_ID
Definition: HTTPCodec.h:55
folly::Function< void()> parent
Definition: AtFork.cpp:34
StreamID proxygen::SPDYCodec::mapPriorityToDependency ( uint8_t  ) const
inlineoverridevirtual

Map the given linear priority to the correct parent node dependency

Reimplemented from proxygen::HTTPCodec.

Definition at line 132 of file SPDYCodec.h.

132  {
133  return MAX_STREAM_ID + priority;
134  }
static const StreamID MAX_STREAM_ID
Definition: HTTPCodec.h:55
void proxygen::SPDYCodec::onControlFrame ( folly::io::Cursor cursor)
private

Helper function to parse out a control frame and execute its handler. All errors are thrown as exceptions.

Definition at line 335 of file SPDYCodec.cpp.

References checkLength(), checkMinLength(), proxygen::spdy::CREDENTIAL, decodeHeaders(), DELTA_WINDOW_SIZE_MASK, proxygen::ERROR, FLAGS_MASK, proxygen::GzipHeaderCodec::getDecodedSize(), proxygen::spdy::GOAWAY, proxygen::spdy::GOAWAY_PROTOCOL_ERROR, proxygen::SPDYVersionSettings::goawaySize, headerCodec_, proxygen::spdy::HEADERS, i, length_, proxygen::spdy::NOOP, onGoaway(), onHeaders(), onPing(), onRstStream(), onSettings(), onSynReply(), onSynStream(), onWindowUpdate(), proxygen::spdy::PING, proxygen::SPDYVersionSettings::priShift, folly::io::detail::CursorBase< Derived, BufType >::read(), folly::io::detail::CursorBase< Derived, BufType >::readBE(), folly::io::detail::CursorBase< Derived, BufType >::readLE(), proxygen::spdy::RST_STREAM, proxygen::spdy::SETTINGS, settings, folly::io::detail::CursorBase< Derived, BufType >::skip(), statusCode, STREAM_ID_MASK, streamId_, proxygen::spdy::SYN_REPLY, proxygen::spdy::SYN_STREAM, proxygen::SPDYVersionSettings::synReplySize, type_, uint32_t, uint8_t, value, version_, versionSettings_, and proxygen::spdy::WINDOW_UPDATE.

Referenced by parseIngress().

335  {
336  switch (type_) {
337  case spdy::SYN_STREAM:
338  {
339  checkMinLength(kFrameSizeSynStream, "SYN_STREAM");
340  streamId_ = cursor.readBE<uint32_t>() & STREAM_ID_MASK;
341  uint32_t assocStream = cursor.readBE<uint32_t>();
342  uint8_t pri = cursor.read<uint8_t>() >> versionSettings_.priShift;
343  uint8_t slot = cursor.read<uint8_t>();
344  length_ -= kFrameSizeSynStream;
345  auto result = decodeHeaders(cursor);
346  checkLength(0, "SYN_STREAM");
347  onSynStream(assocStream, pri, slot,
348  result.headers, headerCodec_.getDecodedSize());
349  break;
350  }
351  case spdy::SYN_REPLY:
352  {
354  streamId_ = cursor.readBE<uint32_t>() & STREAM_ID_MASK;
356  if (version_ == 2) {
357  // 2 byte unused
358  cursor.skip(2);
359  }
360  auto result = decodeHeaders(cursor);
361  checkLength(0, "SYN_REPLY");
362  onSynReply(result.headers,
364  break;
365  }
366  case spdy::RST_STREAM:
367  {
368  checkLength(kFrameSizeRstStream, "RST");
369  streamId_ = cursor.readBE<uint32_t>() & STREAM_ID_MASK;
370  uint32_t statusCode = cursor.readBE<uint32_t>();
371  onRstStream(statusCode);
372  break;
373  }
374  case spdy::SETTINGS:
375  {
376  checkMinLength(kFrameSizeSettings, "SETTINGS");
377  uint32_t numSettings = cursor.readBE<uint32_t>();
378  length_ -= sizeof(uint32_t);
379  if (length_ / 8 < numSettings) {
380  LOG(ERROR) << "SETTINGS: number of settings to high. "
381  << length_ << " < 8 * " << numSettings;
382  throw SPDYSessionFailed(spdy::GOAWAY_PROTOCOL_ERROR);
383  }
385  for (uint32_t i = 0; i < numSettings; i++) {
386  uint32_t id = 0;
387  if (version_ == 2) {
388  id = cursor.readLE<uint32_t>();
389  } else {
390  id = cursor.readBE<uint32_t>();
391  }
392  uint32_t value = cursor.readBE<uint32_t>();
393  uint8_t flags = (id & FLAGS_MASK) >> 24;
394  id &= ~FLAGS_MASK;
395  settings.emplace_back(flags, id, value);
396  }
397  onSettings(settings);
398  break;
399  }
400  case spdy::NOOP:
401  VLOG(4) << "Noop received. Doing nothing.";
402  checkLength(0, "NOOP");
403  break;
404  case spdy::PING:
405  {
406  checkLength(kFrameSizePing, "PING");
407  uint32_t unique_id = cursor.readBE<uint32_t>();
408  onPing(unique_id);
409  break;
410  }
411  case spdy::GOAWAY:
412  {
414  uint32_t lastStream = cursor.readBE<uint32_t>();
415  uint32_t statusCode = 0;
416  if (version_ == 3) {
417  statusCode = cursor.readBE<uint32_t>();
418  }
419  onGoaway(lastStream, statusCode);
420  break;
421  }
422  case spdy::HEADERS:
423  {
424  // Note: this is for the HEADERS frame type, not the initial headers
425  checkMinLength(kFrameSizeHeaders, "HEADERS");
426  streamId_ = cursor.readBE<uint32_t>() & STREAM_ID_MASK;
427  length_ -= kFrameSizeHeaders;
428  if (version_ == 2) {
429  // 2 byte unused
430  cursor.skip(2);
431  length_ -= 2;
432  }
433  auto result = decodeHeaders(cursor);
434  checkLength(0, "HEADERS");
435  onHeaders(result.headers);
436  break;
437  }
438  case spdy::WINDOW_UPDATE:
439  {
440  checkLength(kFrameSizeWindowUpdate, "WINDOW_UPDATE");
441  streamId_ = cursor.readBE<uint32_t>() & STREAM_ID_MASK;
442  uint32_t delta = cursor.readBE<uint32_t>() & DELTA_WINDOW_SIZE_MASK;
443  onWindowUpdate(delta);
444  break;
445  }
446  case spdy::CREDENTIAL:
447  {
448  VLOG(4) << "Skipping unsupported/deprecated CREDENTIAL frame";
449  // Fall through to default case
450  }
451  default:
452  VLOG(3) << "unimplemented control frame type " << type_
453  << ", frame length: " << length_;
454  // From spdy spec:
455  // Control frame processing requirements:
456  // If an endpoint receives a control frame for a type it does not
457  // recognize, it must ignore the frame.
458 
459  // Consume rest of the frame to skip processing it further
460  cursor.skip(length_);
461  length_ = 0;
462  return;
463  }
464 }
void onWindowUpdate(uint32_t delta) noexcept
Definition: SPDYCodec.cpp:1439
void onSettings(const SettingList &settings)
Definition: SPDYCodec.cpp:1345
flags
Definition: http_parser.h:127
spdy::GoawayStatusCode statusCode
Definition: SPDYCodec.cpp:110
void checkLength(uint32_t expectedLength, const std::string &msg)
Definition: SPDYCodec.cpp:219
uint32_t streamId_
Definition: SPDYCodec.h:362
void onSynStream(uint32_t assocStream, uint8_t pri, uint8_t slot, const compress::HeaderPieceList &headers, const HTTPHeaderSize &size)
Definition: SPDYCodec.cpp:1283
std::vector< SettingData > SettingList
Definition: SPDYCodec.h:153
void onRstStream(uint32_t statusCode) noexcept
Definition: SPDYCodec.cpp:1337
static http_parser_settings settings
Definition: test.c:1529
#define FLAGS_MASK
Definition: SPDYCodec.cpp:65
void onSynReply(const compress::HeaderPieceList &headers, const HTTPHeaderSize &size)
Definition: SPDYCodec.cpp:1323
static const char *const value
Definition: Conv.cpp:50
#define DELTA_WINDOW_SIZE_MASK
Definition: SPDYCodec.cpp:68
#define STREAM_ID_MASK
Definition: SPDYCodec.cpp:66
void skip(size_t len)
Definition: Cursor.h:371
GzipHeaderCodec headerCodec_
Definition: SPDYCodec.h:377
HeaderDecodeResult decodeHeaders(folly::io::Cursor &cursor)
Definition: SPDYCodec.cpp:466
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
const HTTPHeaderSize & getDecodedSize()
void checkMinLength(uint32_t minLength, const std::string &msg)
Definition: SPDYCodec.cpp:227
void onPing(uint32_t uniqueID) noexcept
Definition: SPDYCodec.cpp:1393
void onHeaders(const compress::HeaderPieceList &headers) noexcept
Definition: SPDYCodec.cpp:1435
void onGoaway(uint32_t lastGoodStream, uint32_t statusCode) noexcept
Definition: SPDYCodec.cpp:1416
void proxygen::SPDYCodec::onGoaway ( uint32_t  lastGoodStream,
uint32_t  statusCode 
)
privatenoexcept

Definition at line 1416 of file SPDYCodec.cpp.

References proxygen::HTTPParallelCodec::callback_, proxygen::spdy::GOAWAY_FLOW_CONTROL_ERROR, proxygen::spdy::goawayToErrorCode(), proxygen::HTTPParallelCodec::ingressGoawayAck_, proxygen::HTTPCodec::Callback::onGoaway(), proxygen::PROTOCOL_ERROR, and statusCode.

Referenced by onControlFrame().

1417  {
1418  VLOG(4) << "Got GOAWAY, lastGoodStream=" << lastGoodStream
1419  << ", statusCode=" << statusCode;
1420 
1421  if (lastGoodStream < ingressGoawayAck_) {
1422  ingressGoawayAck_ = lastGoodStream;
1423  // Drain all streams <= lastGoodStream
1424  // and abort streams > lastGoodStream
1425  auto errorCode = ErrorCode::PROTOCOL_ERROR;
1427  errorCode = spdy::goawayToErrorCode(spdy::GoawayStatusCode(statusCode));
1428  }
1429  callback_->onGoaway(lastGoodStream, errorCode);
1430  } else {
1431  LOG(WARNING) << "Received multiple GOAWAY with increasing ack";
1432  }
1433 }
spdy::GoawayStatusCode statusCode
Definition: SPDYCodec.cpp:110
HTTPCodec::Callback * callback_
ErrorCode goawayToErrorCode(GoawayStatusCode code)
virtual void onGoaway(uint64_t, ErrorCode, std::unique_ptr< folly::IOBuf >=nullptr)
Definition: HTTPCodec.h:220
void proxygen::SPDYCodec::onHeaders ( const compress::HeaderPieceList headers)
privatenoexcept

Handle a HEADERS frame. This is not invoked when the first headers on a stream are received. This is called when the remote endpoint sends us any additional headers.

Definition at line 1435 of file SPDYCodec.cpp.

Referenced by onControlFrame().

1435  {
1436  VLOG(3) << "onHeaders is unimplemented.";
1437 }
size_t proxygen::SPDYCodec::onIngress ( const folly::IOBuf buf)
overridevirtual

Parse ingress data.

Parameters
bufA single IOBuf of data to parse
Returns
Number of bytes consumed.

Implements proxygen::HTTPCodec.

Definition at line 234 of file SPDYCodec.cpp.

References folly::IOBuf::computeChainDataLength(), currentIngressBuf_, failSession(), and parseIngress().

Referenced by TEST().

234  {
235  size_t bytesParsed = 0;
236  currentIngressBuf_ = &buf;
237  try {
238  bytesParsed = parseIngress(buf);
239  } catch (const SPDYSessionFailed& ex) {
240  failSession(ex.statusCode);
241  bytesParsed = buf.computeChainDataLength();
242  }
243  return bytesParsed;
244 }
const folly::IOBuf * currentIngressBuf_
Definition: SPDYCodec.h:355
size_t parseIngress(const folly::IOBuf &buf)
Definition: SPDYCodec.cpp:246
std::size_t computeChainDataLength() const
Definition: IOBuf.cpp:501
void failSession(uint32_t statusCode)
Definition: SPDYCodec.cpp:1474
void proxygen::SPDYCodec::onPing ( uint32_t  uniqueID)
privatenoexcept

Definition at line 1393 of file SPDYCodec.cpp.

References proxygen::HTTPParallelCodec::callback_, proxygen::DOWNSTREAM, nextEgressPingID_, odd, proxygen::HTTPCodec::Callback::onPingReply(), proxygen::HTTPCodec::Callback::onPingRequest(), and proxygen::HTTPParallelCodec::transportDirection_.

Referenced by onControlFrame().

1393  {
1394  bool odd = uniqueID & 0x1;
1395  bool isReply = true;
1397  if (odd) {
1398  isReply = false;
1399  }
1400  } else if (!odd) {
1401  isReply = false;
1402  }
1403 
1404  if (isReply) {
1405  if (uniqueID >= nextEgressPingID_) {
1406  LOG(INFO) << "Received reply for pingID=" << uniqueID
1407  << " that was never sent";
1408  return;
1409  }
1410  callback_->onPingReply(uniqueID);
1411  } else {
1412  callback_->onPingRequest(uniqueID);
1413  }
1414 }
HTTPCodec::Callback * callback_
virtual void onPingReply(uint64_t)
Definition: HTTPCodec.h:237
auto odd
Definition: CombineTest.cpp:35
virtual void onPingRequest(uint64_t)
Definition: HTTPCodec.h:230
StreamID nextEgressPingID_
Definition: SPDYCodec.h:357
TransportDirection transportDirection_
void proxygen::SPDYCodec::onRstStream ( uint32_t  statusCode)
privatenoexcept

Handle an ingress RST_STREAM control frame.

Definition at line 1337 of file SPDYCodec.cpp.

References proxygen::HTTPParallelCodec::deliverCallbackIfAllowed(), proxygen::HTTPCodec::Callback::onAbort(), proxygen::spdy::rstToErrorCode(), statusCode, streamID, and streamId_.

Referenced by onControlFrame().

1337  {
1338  VLOG(4) << "Got RST_STREAM, stream=" << streamId_
1339  << ", status=" << statusCode;
1343 }
spdy::GoawayStatusCode statusCode
Definition: SPDYCodec.cpp:110
uint32_t streamId_
Definition: SPDYCodec.h:362
bool deliverCallbackIfAllowed(T callbackFn, char const *cbName, StreamID stream, Args &&...args)
virtual void onAbort(StreamID, ErrorCode)
Definition: HTTPCodec.h:192
uint64_t StreamID
Definition: HTTPCodec.h:49
uint32_t streamID
Definition: SPDYCodec.cpp:131
ErrorCode rstToErrorCode(uint32_t code)
void proxygen::SPDYCodec::onSettings ( const SettingList settings)
private

Handle a SETTINGS message that changes/updates settings for the entire SPDY connection (across all transactions)

Definition at line 1345 of file SPDYCodec.cpp.

References proxygen::HTTPParallelCodec::callback_, proxygen::ERROR, flags_, proxygen::HTTPSettings::getSetting(), proxygen::spdy::GOAWAY_PROTOCOL_ERROR, proxygen::spdy::ID_FLAG_SETTINGS_PERSISTED, ingressSettings_, max, proxygen::HTTPCodec::Callback::onSettings(), s, proxygen::HTTPSettings::setSetting(), proxygen::spdy::SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE, proxygen::spdy::SETTINGS_CURRENT_CWND, proxygen::spdy::SETTINGS_DOWNLOAD_BANDWIDTH, proxygen::spdy::SETTINGS_DOWNLOAD_RETRANS_RATE, proxygen::spdy::SETTINGS_INITIAL_WINDOW_SIZE, proxygen::spdy::SETTINGS_MAX_CONCURRENT_STREAMS, proxygen::spdy::SETTINGS_ROUND_TRIP_TIME, proxygen::spdy::SETTINGS_UPLOAD_BANDWIDTH, proxygen::spdy::spdyToHttpSettingsId(), and version_.

Referenced by onControlFrame().

1345  {
1346  VLOG(4) << "Got " << settings.size() << " settings with "
1347  << "version=" << version_ << " and flags="
1348  << std::hex << folly::to<unsigned int>(flags_) << std::dec;
1349  SettingsList settingsList;
1350  for (const SettingData& cur: settings) {
1351  // For now, we never ask for anything to be persisted, so ignore anything
1352  // coming back
1353  if (cur.flags & spdy::ID_FLAG_SETTINGS_PERSISTED) {
1354  VLOG(2) << "Ignoring bogus persisted setting: " << cur.id;
1355  continue;
1356  }
1357 
1358  switch (cur.id) {
1365  // These will be stored in ingressSettings_ and passed to the callback
1366  // but we currently ignore the PERSIST flag
1367  break;
1369  break;
1371  if (cur.value > std::numeric_limits<int32_t>::max()) {
1372  throw SPDYSessionFailed(spdy::GOAWAY_PROTOCOL_ERROR);
1373  }
1374  break;
1375  default:
1376  LOG(ERROR) << "Received unknown setting with ID=" << cur.id
1377  << ", value=" << cur.value
1378  << ", and flags=" << std::hex << cur.flags << std::dec;
1379  }
1382  auto id = spdy::spdyToHttpSettingsId((spdy::SettingsId)cur.id);
1383  if (id) {
1384  ingressSettings_.setSetting(*id, cur.value);
1385  auto s = ingressSettings_.getSetting(*id);
1386  settingsList.push_back(*s);
1387  }
1388  }
1389  }
1390  callback_->onSettings(settingsList);
1391 }
HTTPSettings ingressSettings_
Definition: SPDYCodec.h:344
LogLevel max
Definition: LogLevel.cpp:31
virtual void onSettings(const SettingsList &)
Definition: HTTPCodec.h:251
HTTPCodec::Callback * callback_
static http_parser_settings settings
Definition: test.c:1529
folly::Optional< proxygen::SettingsId > spdyToHttpSettingsId(proxygen::spdy::SettingsId id)
std::vector< HTTPSetting > SettingsList
Definition: HTTPSettings.h:81
static set< string > s
const HTTPSetting * getSetting(SettingsId id) const
void setSetting(SettingsId id, SettingsValue val)
void proxygen::SPDYCodec::onSynCommon ( StreamID  streamID,
StreamID  assocStreamID,
const compress::HeaderPieceList headers,
int8_t  pri,
const HTTPHeaderSize size 
)
private

Helper function that contains the common implementation details of calling the same callbacks for onSynStream() and onSynReply()

Negative values of pri are interpreted much like negative array indexes in python, so -1 will be the largest numerical priority value for this SPDY version (i.e., 3 for SPDY/2 or 7 for SPDY/3), -2 the second largest (i.e., 2 for SPDY/2 or 6 for SPDY/3).

Definition at line 1238 of file SPDYCodec.cpp.

References proxygen::spdy::CTRL_FLAG_FIN, proxygen::HTTPParallelCodec::deliverCallbackIfAllowed(), deliverOnMessageBegin(), proxygen::ERROR, flags_, proxygen::spdy::GOAWAY_PROTOCOL_ERROR, proxygen::HTTP_HEADER_USER_AGENT, proxygen::SPDYVersionSettings::majorVersion, std::tr1::make_tuple(), proxygen::HTTPCodec::MAX_STREAM_ID, folly::gen::move, proxygen::HTTPCodec::Callback::onHeadersComplete(), parseHeaders(), proxygen::SPDYVersionSettings::protocolVersionString, proxygen::HTTPParallelCodec::transportDirection_, userAgent_, version_, and versionSettings_.

Referenced by onSynReply(), and onSynStream().

1242  {
1244  LOG(ERROR) << "Invalid version=" << version_;
1245  throw SPDYSessionFailed(spdy::GOAWAY_PROTOCOL_ERROR);
1246  }
1247 
1248  unique_ptr<HTTPMessage> msg = parseHeaders(transportDirection_,
1249  streamID, assocStreamID, headers);
1250  msg->setIngressHeaderSize(size);
1251 
1252  msg->setAdvancedProtocolString(versionSettings_.protocolVersionString);
1253  // Normalize priority to 3 bits in HTTPMessage.
1254  pri <<= (3 - versionSettings_.majorVersion);
1255  msg->setPriority(pri);
1256  msg->setHTTP2Priority(std::make_tuple(HTTPCodec::MAX_STREAM_ID + pri,
1257  false, 255));
1258  deliverOnMessageBegin(streamID, assocStreamID, msg.get());
1259 
1260  if ((flags_ & spdy::CTRL_FLAG_FIN) == 0) {
1261  // If it there are DATA frames coming, consider it chunked
1262  msg->setIsChunked(true);
1263  }
1264  if (userAgent_.empty()) {
1265  userAgent_ = msg->getHeaders().getSingleOrEmpty(HTTP_HEADER_USER_AGENT);
1266  }
1268  "onHeadersComplete", streamID, std::move(msg));
1269 }
void deliverOnMessageBegin(StreamID streamID, StreamID assocStreamID, HTTPMessage *msg)
Definition: SPDYCodec.cpp:1271
static const StreamID MAX_STREAM_ID
Definition: HTTPCodec.h:55
bool deliverCallbackIfAllowed(T callbackFn, char const *cbName, StreamID stream, Args &&...args)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
const std::string & protocolVersionString
std::string userAgent_
Definition: SPDYCodec.h:354
tuple make_tuple()
Definition: gtest-tuple.h:675
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
std::unique_ptr< HTTPMessage > parseHeaders(TransportDirection direction, StreamID streamID, StreamID assocStreamID, const compress::HeaderPieceList &headers)
Definition: SPDYCodec.cpp:1059
virtual void onHeadersComplete(StreamID stream, std::unique_ptr< HTTPMessage > msg)=0
TransportDirection transportDirection_
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
uint32_t streamID
Definition: SPDYCodec.cpp:131
void proxygen::SPDYCodec::onSynReply ( const compress::HeaderPieceList headers,
const HTTPHeaderSize size 
)
private

Handle an ingress SYN_REPLY control frame. For an upstream-facing SPDY session, this frame is the equivalent of an HTTP response header.

Definition at line 1323 of file SPDYCodec.cpp.

References proxygen::DOWNSTREAM, NoStream, onSynCommon(), proxygen::spdy::RST_PROTOCOL_ERROR, streamId_, and proxygen::HTTPParallelCodec::transportDirection_.

Referenced by onControlFrame().

1324  {
1325  VLOG(4) << "Got SYN_REPLY, stream=" << streamId_;
1327  (streamId_ & 0x1) == 0) {
1328  throw SPDYStreamFailed(true, streamId_, spdy::RST_PROTOCOL_ERROR);
1329  }
1330  // Server push transactions, short of any better heuristics,
1331  // should have a background priority. Thus, we pick the largest
1332  // numerical value for the SPDY priority, which no matter what
1333  // protocol version this is can be conveyed to onSynCommon by -1.
1334  onSynCommon(StreamID(streamId_), NoStream, headers, -1, size);
1335 }
uint32_t streamId_
Definition: SPDYCodec.h:362
static const StreamID NoStream
Definition: SPDYCodec.h:38
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
void onSynCommon(StreamID streamID, StreamID assocStreamID, const compress::HeaderPieceList &headers, int8_t pri, const HTTPHeaderSize &size)
Definition: SPDYCodec.cpp:1238
uint64_t StreamID
Definition: HTTPCodec.h:49
TransportDirection transportDirection_
void proxygen::SPDYCodec::onSynStream ( uint32_t  assocStream,
uint8_t  pri,
uint8_t  slot,
const compress::HeaderPieceList headers,
const HTTPHeaderSize size 
)
private

Handle an ingress SYN_STREAM control frame. For a downstream-facing SPDY session, this frame is the equivalent of an HTTP request header.

Definition at line 1283 of file SPDYCodec.cpp.

References proxygen::HTTPParallelCodec::callback_, proxygen::spdy::CTRL_FLAG_UNIDIRECTIONAL, proxygen::DOWNSTREAM, egressSettings_, proxygen::ERROR, flags_, proxygen::HTTPSettings::getSetting(), proxygen::spdy::GOAWAY_PROTOCOL_ERROR, proxygen::spdy::kMaxConcurrentStreams, proxygen::HTTPParallelCodec::lastStreamID_, proxygen::MAX_CONCURRENT_STREAMS, NoStream, proxygen::HTTPCodec::Callback::numIncomingStreams(), onSynCommon(), proxygen::spdy::RST_PROTOCOL_ERROR, proxygen::spdy::RST_REFUSED_STREAM, proxygen::HTTPParallelCodec::sessionClosing_, streamId_, proxygen::HTTPParallelCodec::transportDirection_, and proxygen::UPSTREAM.

Referenced by onControlFrame().

1287  {
1288  VLOG(4) << "Got SYN_STREAM, stream=" << streamId_
1289  << " pri=" << folly::to<int>(pri);
1290  if (streamId_ == NoStream ||
1293  (streamId_ & 0x01) == 1) ||
1295  ((streamId_ & 0x1) == 0)) ||
1297  assocStream == NoStream)) {
1298  LOG(ERROR) << " invalid syn stream stream_id=" << streamId_
1299  << " lastStreamID_=" << lastStreamID_
1300  << " assocStreamID=" << assocStream
1301  << " direction=" << transportDirection_;
1302  throw SPDYSessionFailed(spdy::GOAWAY_PROTOCOL_ERROR);
1303  }
1304 
1305  if (streamId_ == lastStreamID_) {
1306  throw SPDYStreamFailed(true, streamId_, spdy::RST_PROTOCOL_ERROR);
1307  }
1308  if (callback_->numIncomingStreams() >=
1311  throw SPDYStreamFailed(true, streamId_, spdy::RST_REFUSED_STREAM);
1312  }
1313  if (assocStream != NoStream && !(flags_ & spdy::CTRL_FLAG_UNIDIRECTIONAL)) {
1314  throw SPDYStreamFailed(true, streamId_, spdy::RST_PROTOCOL_ERROR);
1315  }
1316  if (sessionClosing_ != ClosingState::CLOSING) {
1318  }
1320  StreamID(assocStream), headers, pri, size);
1321 }
uint32_t streamId_
Definition: SPDYCodec.h:362
HTTPCodec::Callback * callback_
static const StreamID NoStream
Definition: SPDYCodec.h:38
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
void onSynCommon(StreamID streamID, StreamID assocStreamID, const compress::HeaderPieceList &headers, int8_t pri, const HTTPHeaderSize &size)
Definition: SPDYCodec.cpp:1238
enum proxygen::HTTPParallelCodec::ClosingState sessionClosing_
virtual uint32_t numIncomingStreams() const
Definition: HTTPCodec.h:327
uint64_t StreamID
Definition: HTTPCodec.h:49
const uint32_t kMaxConcurrentStreams
TransportDirection transportDirection_
HTTPSettings egressSettings_
Definition: SPDYCodec.h:348
const HTTPSetting * getSetting(SettingsId id) const
void proxygen::SPDYCodec::onWindowUpdate ( uint32_t  delta)
privatenoexcept

Definition at line 1439 of file SPDYCodec.cpp.

References proxygen::HTTPParallelCodec::deliverCallbackIfAllowed(), proxygen::HTTPCodec::Callback::onWindowUpdate(), and streamId_.

Referenced by onControlFrame().

1439  {
1441  "onWindowUpdate", streamId_, delta);
1442 }
uint32_t streamId_
Definition: SPDYCodec.h:362
bool deliverCallbackIfAllowed(T callbackFn, char const *cbName, StreamID stream, Args &&...args)
virtual void onWindowUpdate(StreamID, uint32_t)
Definition: HTTPCodec.h:243
unique_ptr< HTTPMessage > proxygen::SPDYCodec::parseHeaders ( TransportDirection  direction,
StreamID  streamID,
StreamID  assocStreamID,
const compress::HeaderPieceList headers 
)
private

Parses the headers in the nameValues array and creates an HTTPMessage object initialized for this transaction.

Definition at line 1059 of file SPDYCodec.cpp.

References add, proxygen::HTTPHeaders::add(), proxygen::caseInsensitiveEqual(), deliverOnMessageBegin(), proxygen::DOWNSTREAM, proxygen::HTTPHeaders::exists(), proxygen::HTTPHeaders::getSingleOrEmpty(), proxygen::CodecUtil::hasGzipAndDeflate(), proxygen::spdy::HEADERS, proxygen::HTTP_HEADER_ACCEPT_ENCODING, proxygen::HTTP_HEADER_HOST, i, int16_t, int32_t, folly::gen::move, name, partialMsg_, proxygen::spdy::RST_PROTOCOL_ERROR, proxygen::HTTPHeaders::set(), folly::Range< Iter >::str(), proxygen::CodecUtil::STRICT, type_, uint32_t, uint8_t, proxygen::UPSTREAM, proxygen::CodecUtil::validateHeaderName(), proxygen::CodecUtil::validateHeaderValue(), proxygen::CodecUtil::validateMethod(), proxygen::CodecUtil::validateURL(), value, and version_.

Referenced by onSynCommon().

1061  {
1062  unique_ptr<HTTPMessage> msg(new HTTPMessage());
1063  HTTPHeaders& headers = msg->getHeaders();
1064  bool newStream = (type_ != spdy::HEADERS);
1065 
1066  bool hasScheme = false;
1067  bool hasPath = false;
1068  bool hasContentLength = false;
1069 
1070  // Number of fields must be even
1071  CHECK_EQ((inHeaders.size() & 1), 0);
1072  for (unsigned i = 0; i < inHeaders.size(); i += 2) {
1073  uint8_t off = 0;
1074  uint32_t len = inHeaders[i].str.size();
1075  if (len > 1 && inHeaders[i].str[0] == ':') {
1076  off = 1; // also signals control header
1077  len--;
1078  }
1079  folly::StringPiece name(inHeaders[i].str, off, len);
1080  folly::StringPiece value = inHeaders[i + 1].str;
1081  VLOG(5) << "Header " << name << ": " << value;
1082  bool nameOk = CodecUtil::validateHeaderName(name);
1083  bool valueOk = false;
1084  bool isPath = false;
1085  bool isMethod = false;
1086  if (nameOk) {
1087  if (name == "content-length") {
1088  if (hasContentLength) {
1089  throw SPDYStreamFailed(false, streamID, 400,
1090  "Multiple content-length headers");
1091  }
1092  hasContentLength = true;
1093  }
1094  if ((version_ == 2 && name == "url") ||
1095  (version_ == 3 && off && name == "path")) {
1096  valueOk = CodecUtil::validateURL(value);
1097  isPath = true;
1098  if (hasPath) {
1099  throw SPDYStreamFailed(false, streamID, 400,
1100  "Multiple paths in header");
1101  }
1102  hasPath = true;
1103  } else if ((version_ == 2 || off) && name == "method") {
1104  valueOk = CodecUtil::validateMethod(value);
1105  isMethod = true;
1106  if (value == "CONNECT") {
1107  // We don't support CONNECT request for SPDY
1108  valueOk = false;
1109  }
1110  } else {
1112  }
1113  }
1114  if (!nameOk || !valueOk) {
1115  if (newStream) {
1116  deliverOnMessageBegin(streamID, assocStreamID, nullptr);
1117  }
1118  partialMsg_ = std::move(msg);
1119  throw SPDYStreamFailed(false, streamID, 400, "Bad header value");
1120  }
1121  bool add = false;
1122  if (off || version_ == 2) {
1123  if (isMethod) {
1124  msg->setMethod(value);
1125  } else if (isPath) {
1126  msg->setURL(value.str());
1127  } else if (name == "version") {
1128  if (caseInsensitiveEqual(value, "http/1.0")) {
1129  msg->setHTTPVersion(1, 0);
1130  } else {
1131  msg->setHTTPVersion(1, 1);
1132  }
1133  } else if (version_ == 3 && name == "host") {
1134  headers.add(HTTP_HEADER_HOST, value.str());
1135  } else if (name == "scheme") {
1136  hasScheme = true;
1137  if (value == "https") {
1138  msg->setSecure(true);
1139  }
1140  } else if (name == "status") {
1141  if (direction == TransportDirection::UPSTREAM && !assocStreamID) {
1142  folly::StringPiece codePiece;
1143  folly::StringPiece reasonPiece;
1144  if (value.contains(' ')) {
1145  folly::split<false>(' ', value, codePiece, reasonPiece);
1146  } else {
1147  codePiece = value;
1148  }
1149  int32_t code = -1;
1150  try {
1151  code = folly::to<unsigned int>(codePiece);
1152  } catch (const std::range_error& ex) {
1153  // Toss out the range error cause the exception will get it
1154  }
1155  if (code >= 100 && code <= 999) {
1156  msg->setStatusCode(code);
1157  msg->setStatusMessage(reasonPiece.str());
1158  } else {
1159  msg->setStatusCode(0);
1160  headers.add(name, value);
1161  partialMsg_ = std::move(msg);
1162  throw SPDYStreamFailed(newStream, streamID,
1164  "Invalid status code");
1165  }
1166  } else if (!assocStreamID) {
1167  if (version_ == 2) {
1168  headers.add("Status", value);
1169  }
1170  } else { // is a push status since there is an assocStreamID?
1171  // If there exists a push status, save it.
1172  // If there does not, for now, we *eat* the push status.
1173  if (value.size() > 0) {
1174  int16_t code = -1;
1175  try {
1176  code = folly::to<uint16_t>(value);
1177  } catch (const std::range_error& ex) {
1178  // eat the push status
1179  }
1180  if (code >= 100 && code <= 999) {
1181  msg->setPushStatusCode(code);
1182  } else {
1183  // eat the push status.
1184  }
1185  }
1186  }
1187  } else if (version_ == 2) {
1188  add = true;
1189  }
1190  } else {
1191  add = true;
1192  }
1193  if (add) {
1194  if (!inHeaders[i].isMultiValued() && headers.exists(name)) {
1195  headers.add(name, value);
1196  partialMsg_ = std::move(msg);
1197  throw SPDYStreamFailed(newStream, streamID, spdy::RST_PROTOCOL_ERROR,
1198  "Duplicate header value");
1199  }
1200  headers.add(name, value);
1201  }
1202  }
1203  if (assocStreamID &&
1204  (!headers.exists(HTTP_HEADER_HOST) || !hasScheme || !hasPath)) {
1205  // Fail a server push without host, scheme or path headers
1206  throw SPDYStreamFailed(newStream, streamID, 400, "Bad Request");
1207  }
1208  if (direction == TransportDirection::DOWNSTREAM) {
1209  if (version_ == 2 && !headers.exists(HTTP_HEADER_HOST)) {
1210  ParseURL url(msg->getURL());
1211  if (url.valid()) {
1212  headers.add(HTTP_HEADER_HOST, url.hostAndPort());
1213  }
1214  }
1215 
1216  const string& accept_encoding =
1217  headers.getSingleOrEmpty(HTTP_HEADER_ACCEPT_ENCODING);
1218  if (accept_encoding.empty()) {
1219  headers.add(HTTP_HEADER_ACCEPT_ENCODING, "gzip, deflate");
1220  } else {
1221  bool hasGzip = false;
1222  bool hasDeflate = false;
1223  if (!CodecUtil::hasGzipAndDeflate(accept_encoding, hasGzip, hasDeflate)) {
1224  string new_encoding = accept_encoding;
1225  if (!hasGzip) {
1226  new_encoding.append(", gzip");
1227  }
1228  if (!hasDeflate) {
1229  new_encoding.append(", deflate");
1230  }
1231  headers.set(HTTP_HEADER_ACCEPT_ENCODING, new_encoding);
1232  }
1233  }
1234  }
1235  return msg;
1236 }
void deliverOnMessageBegin(StreamID streamID, StreamID assocStreamID, HTTPMessage *msg)
Definition: SPDYCodec.cpp:1271
std::string str() const
Definition: Range.h:591
bool caseInsensitiveEqual(folly::StringPiece s, folly::StringPiece t)
Definition: UtilInl.h:17
auto add
Definition: BaseTest.cpp:70
static bool validateHeaderName(folly::ByteRange name)
Definition: CodecUtil.h:43
std::unique_ptr< HTTPMessage > partialMsg_
Definition: SPDYCodec.h:353
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
static bool validateMethod(folly::ByteRange method)
Definition: CodecUtil.h:33
const char * name
Definition: http_parser.c:437
static bool validateURL(folly::ByteRange url)
Definition: CodecUtil.h:29
static const char *const value
Definition: Conv.cpp:50
static bool validateHeaderValue(folly::ByteRange value, CtlEscapeMode mode)
Definition: CodecUtil.h:66
uint32_t streamID
Definition: SPDYCodec.cpp:131
static bool hasGzipAndDeflate(const std::string &value, bool &hasGzip, bool &hasDeflate)
Definition: CodecUtil.cpp:61
size_t proxygen::SPDYCodec::parseIngress ( const folly::IOBuf buf)
private

Ingress parser, can throw exceptions

Definition at line 246 of file SPDYCodec.cpp.

References proxygen::HTTPParallelCodec::callback_, folly::io::detail::CursorBase< Derived, BufType >::clone(), folly::IOBuf::computeChainDataLength(), ctrl_, proxygen::spdy::CTRL_FLAG_FIN, CTRL_MASK, data, proxygen::HTTPParallelCodec::deliverCallbackIfAllowed(), proxygen::ERROR, failStream(), flags_, FLAGS_MASK, FRAME_HEADER_LEN, frameState_, proxygen::spdy::GOAWAY_PROTOCOL_ERROR, proxygen::spdy::HEADERS, length_, proxygen::SPDYVersionSettings::majorVersion, max, maxFrameLength_, min, folly::gen::move, proxygen::HTTPCodec::Callback::onBody(), onControlFrame(), proxygen::HTTPCodec::Callback::onFrameHeader(), proxygen::HTTPCodec::Callback::onMessageComplete(), folly::io::detail::CursorBase< Derived, BufType >::peek(), folly::io::detail::CursorBase< Derived, BufType >::readBE(), proxygen::spdy::RST_FRAME_TOO_LARGE, STREAM_ID_MASK, streamId_, proxygen::spdy::SYN_REPLY, proxygen::spdy::SYN_STREAM, folly::io::detail::CursorBase< Derived, BufType >::totalLength(), type_, uint16_t, uint32_t, version_, VERSION_MASK, and versionSettings_.

Referenced by onIngress().

246  {
247  const size_t chainLength = buf.computeChainDataLength();
248  Cursor cursor(&buf);
249  size_t avail = cursor.totalLength();
250 
251  // This can parse beyond the current IOBuf
252  for (; avail > 0; avail = cursor.totalLength()) {
253  if (frameState_ == FrameState::FRAME_HEADER) {
254  if (avail < FRAME_HEADER_LEN) {
255  // Make the caller buffer until we get a full frame header
256  break;
257  }
258  auto data = cursor.peek();
259  ctrl_ = (data.first[0] & CTRL_MASK);
260  if (ctrl_) {
261  version_ = cursor.readBE<uint16_t>() & VERSION_MASK;
262  type_ = cursor.readBE<uint16_t>();
264  LOG(ERROR) << "Invalid version=" << version_;
265  throw SPDYSessionFailed(spdy::GOAWAY_PROTOCOL_ERROR);
266  }
267  } else {
268  streamId_ = cursor.readBE<uint32_t>() & STREAM_ID_MASK;
269  }
270  length_ = cursor.readBE<uint32_t>();
271  flags_ = (length_ & FLAGS_MASK) >> 24;
272  length_ &= ~FLAGS_MASK;
273  if (ctrl_) {
274  if (length_ > maxFrameLength_) {
275  if (type_ == spdy::SYN_STREAM || type_ == spdy::SYN_REPLY ||
276  type_ == spdy::HEADERS) {
277  uint32_t stream_id = cursor.readBE<uint32_t>() & STREAM_ID_MASK;
278  failStream(true, stream_id, spdy::RST_FRAME_TOO_LARGE);
279  // Compression/stream state is out of sync now
280  }
281  // Since maxFrameLength_ must be at least 8kb and most control frames
282  // have fixed size, only an invalid settings or credential frame can
283  // land here. For invalid credential frames we must send a goaway,
284  // and a settings frame would have > 1023 pairs, of which none are
285  // allowed to be duplicates. Just fail everything.
286  LOG(ERROR) << "excessive frame size length_=" << length_;
287  throw SPDYSessionFailed(spdy::GOAWAY_PROTOCOL_ERROR);
288  }
289  frameState_ = FrameState::CTRL_FRAME_DATA;
290  callback_->onFrameHeader(0, flags_, length_, type_, version_);
291  } else {
292  frameState_ = FrameState::DATA_FRAME_DATA;
293  callback_->onFrameHeader(streamId_, flags_, length_, type_);
294  }
295  } else if (frameState_ == FrameState::CTRL_FRAME_DATA) {
296  if (avail < length_) {
297  // Make the caller buffer the rest of the control frame.
298  // We could attempt to decompress incomplete name/value blocks,
299  // but for now we're favoring simplicity.
300  VLOG(6) << "Need more data: length_=" << length_ << " avail=" << avail;
301  break;
302  }
303  try {
304  onControlFrame(cursor);
305  } catch (const SPDYStreamFailed& ex) {
306  failStream(ex.isNew, ex.streamID, ex.statusCode, ex.what());
307  }
308  frameState_ = FrameState::FRAME_HEADER;
309  } else if (avail > 0 || length_ == 0) {
310  // Data frame data. Pass everything we have up to the frame boundary
311  DCHECK(FrameState::DATA_FRAME_DATA == frameState_);
312 
313  uint32_t toClone = (avail > std::numeric_limits<uint32_t>::max()) ?
314  std::numeric_limits<uint32_t>::max() : static_cast<uint32_t>(avail);
315  toClone = std::min(toClone, length_);
316  std::unique_ptr<IOBuf> chunk;
317  cursor.clone(chunk, toClone);
319  streamId_, std::move(chunk), 0);
320  length_ -= toClone;
321  }
322 
323  // Fin handling
324  if (length_ == 0) {
325  if (flags_ & spdy::CTRL_FLAG_FIN) {
327  "onMessageComplete", streamId_, false);
328  }
329  frameState_ = FrameState::FRAME_HEADER;
330  }
331  }
332  return chainLength - avail;
333 }
uint32_t maxFrameLength_
Definition: SPDYCodec.h:361
uint32_t streamId_
Definition: SPDYCodec.h:362
bool deliverCallbackIfAllowed(T callbackFn, char const *cbName, StreamID stream, Args &&...args)
LogLevel max
Definition: LogLevel.cpp:31
#define VERSION_MASK
Definition: SPDYCodec.cpp:67
HTTPCodec::Callback * callback_
virtual void onMessageComplete(StreamID stream, bool upgrade)=0
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define FLAGS_MASK
Definition: SPDYCodec.cpp:65
void onControlFrame(folly::io::Cursor &cursor)
Definition: SPDYCodec.cpp:335
#define FRAME_HEADER_LEN
Definition: SPDYCodec.cpp:71
LogLevel min
Definition: LogLevel.cpp:30
#define CTRL_MASK
Definition: SPDYCodec.cpp:64
virtual void onFrameHeader(StreamID, uint8_t, uint64_t, uint8_t, uint16_t=0)
Definition: HTTPCodec.h:206
std::size_t computeChainDataLength() const
Definition: IOBuf.cpp:501
#define STREAM_ID_MASK
Definition: SPDYCodec.cpp:66
void failStream(bool newTxn, StreamID streamID, uint32_t code, std::string excStr=empty_string)
Definition: SPDYCodec.cpp:1444
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
virtual void onBody(StreamID stream, std::unique_ptr< folly::IOBuf > chain, uint16_t padding)=0
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
enum proxygen::SPDYCodec::FrameState frameState_
bool proxygen::SPDYCodec::rstStatusSupported ( int  statusCode) const
private

Helper function to check if the status code is supported by the SPDY version being used

Definition at line 1489 of file SPDYCodec.cpp.

References proxygen::SPDYVersionSettings::majorVersion, proxygen::spdy::RST_FLOW_CONTROL_ERROR, and versionSettings_.

Referenced by generateRstStream().

1489  {
1490  if (statusCode == 0) {
1491  // 0 is not a valid status code for RST_STREAM
1492  return false;
1493  }
1494  // SPDY/3 supports more status codes for RST_STREAM. For SPDY/2,
1495  // we just use PROTOCOL_ERROR for these new higher numbered error codes.
1496  return (versionSettings_.majorVersion != 2 ||
1498 }
spdy::GoawayStatusCode statusCode
Definition: SPDYCodec.cpp:110
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
unique_ptr< IOBuf > proxygen::SPDYCodec::serializeRequestHeaders ( const HTTPMessage msg,
bool  isPushed,
uint32_t  headroom = 0,
HTTPHeaderSize size = nullptr 
)
private

Serializes headers for requests (aka SYN_STREAM)

Parameters
msgThe message to serialize.
isPushedtrue if this is a push message
sizeSize of the serialized headers before and after compression
headroomOptional amount of headroom to reserve at the front of the returned IOBuf, in case the caller wants to put some other data there.

Definition at line 587 of file SPDYCodec.cpp.

References encodeHeaders(), proxygen::HTTPHeaders::exists(), proxygen::HTTPMessage::getHeaders(), proxygen::HTTPMessage::getMethodString(), proxygen::HTTPMessage::getPushStatusStr(), proxygen::HTTPHeaders::getSingleOrEmpty(), proxygen::HTTPMessage::getURL(), proxygen::SPDYVersionSettings::hostStr, proxygen::HTTP_HEADER_COLON_METHOD, proxygen::HTTP_HEADER_COLON_PATH, proxygen::HTTP_HEADER_COLON_SCHEME, proxygen::HTTP_HEADER_COLON_STATUS, proxygen::HTTP_HEADER_HOST, proxygen::HTTP_HEADER_OTHER, proxygen::HTTPMessage::isSecure(), proxygen::SPDYVersionSettings::majorVersion, proxygen::HTTPHeaders::size(), and versionSettings_.

Referenced by generateSynStream().

591  {
592 
593  const HTTPHeaders& headers = msg.getHeaders();
594  vector<Header> allHeaders;
595  allHeaders.reserve(headers.size() + 6);
596 
597  const string& method = msg.getMethodString();
598  static const string https("https");
599  static const string http("http");
600  const string& scheme = msg.isSecure() ? https : http;
601  string path = msg.getURL();
602 
603  CHECK_GT(versionSettings_.majorVersion, 2) << "SPDY/2 no longer supported";
604 
605  if (isPushed) {
606  const string& pushString = msg.getPushStatusStr();
607  allHeaders.emplace_back(HTTP_HEADER_COLON_STATUS, pushString);
608  } else {
609  allHeaders.emplace_back(HTTP_HEADER_COLON_METHOD, method);
610  }
611  allHeaders.emplace_back(HTTP_HEADER_COLON_SCHEME, scheme);
612  allHeaders.emplace_back(HTTP_HEADER_COLON_PATH, path);
613  if (versionSettings_.majorVersion == 3) {
614  DCHECK(headers.exists(HTTP_HEADER_HOST));
615  const string& host = headers.getSingleOrEmpty(HTTP_HEADER_HOST);
616  // We explicitly provide both the code and header name here
617  // as HTTP_HEADER_OTHER does not map to kNameHostv3 and we don't want a
618  // perf penalty hash kNameHostv3 to HTTP_HEADER_OTHER
619  allHeaders.emplace_back(HTTP_HEADER_OTHER, versionSettings_.hostStr, host);
620 }
621 
622  return encodeHeaders(msg, allHeaders, headroom, size);
623 }
std::unique_ptr< folly::IOBuf > encodeHeaders(const HTTPMessage &msg, std::vector< compress::Header > &headers, uint32_t headroom=0, HTTPHeaderSize *size=nullptr)
Definition: SPDYCodec.cpp:503
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
unique_ptr< IOBuf > proxygen::SPDYCodec::serializeResponseHeaders ( const HTTPMessage msg,
uint32_t  headroom = 0,
HTTPHeaderSize size = nullptr 
)
private

Serializes headers for responses (aka SYN_REPLY)

Parameters
msgThe message to serialize.
sizeSize of the serialized headers before and after compression
headroomOptional amount of headroom to reserve at the front of the returned IOBuf, in case the caller wants to put some other data there.

Definition at line 557 of file SPDYCodec.cpp.

References date, encodeHeaders(), proxygen::HTTPHeaders::exists(), proxygen::HTTPMessage::formatDateHeader(), proxygen::HTTPMessage::getHeaders(), proxygen::HTTPMessage::getStatusCode(), proxygen::HTTPMessage::getStatusMessage(), proxygen::HTTP_HEADER_COLON_STATUS, proxygen::HTTP_HEADER_DATE, and proxygen::HTTPHeaders::size().

Referenced by generateSynReply().

558  {
559 
560  // Note: the header-sorting code works with pointers to strings.
561  // The role of this local status string is to hold the generated
562  // status code long enough for the sort (done later within the
563  // same scope) to be able to access it.
564  string status;
565 
566  const HTTPHeaders& headers = msg.getHeaders();
567  vector<Header> allHeaders;
568  allHeaders.reserve(headers.size() + 4);
569 
570  if (msg.getStatusMessage().empty()) {
571  status = folly::to<string>(msg.getStatusCode());
572  } else {
573  status = folly::to<string>(msg.getStatusCode(), " ",
574  msg.getStatusMessage());
575  }
576  allHeaders.emplace_back(HTTP_HEADER_COLON_STATUS, status);
577  // See comment above regarding status
578  string date;
579  if (!headers.exists(HTTP_HEADER_DATE)) {
581  allHeaders.emplace_back(HTTP_HEADER_DATE, date);
582  }
583 
584  return encodeHeaders(msg, allHeaders, headroom, size);
585 }
static std::string formatDateHeader()
string date
std::unique_ptr< folly::IOBuf > encodeHeaders(const HTTPMessage &msg, std::vector< compress::Header > &headers, uint32_t headroom=0, HTTPHeaderSize *size=nullptr)
Definition: SPDYCodec.cpp:503
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
void proxygen::SPDYCodec::setHeaderCodecStats ( HeaderCodec::Stats )
inlineoverridevirtual

set stats for the header codec, if the protocol supports header compression

Reimplemented from proxygen::HTTPCodec.

Definition at line 123 of file SPDYCodec.h.

References uint8_t.

123  {
124  headerCodec_.setStats(stats);
125  }
void setStats(Stats *stats)
Definition: HeaderCodec.h:84
GzipHeaderCodec headerCodec_
Definition: SPDYCodec.h:377
void proxygen::SPDYCodec::setMaxFrameLength ( uint32_t  maxFrameLength)

Definition at line 189 of file SPDYCodec.cpp.

References maxFrameLength_.

Referenced by TEST().

189  {
190  maxFrameLength_ = maxFrameLength;
191 }
uint32_t maxFrameLength_
Definition: SPDYCodec.h:361
void proxygen::SPDYCodec::setMaxUncompressedHeaders ( uint32_t  maxUncompressed)

Set the maximum size of the uncompressed headers

Definition at line 193 of file SPDYCodec.cpp.

References headerCodec_, and proxygen::HeaderCodec::setMaxUncompressed().

Referenced by TEST().

193  {
194  headerCodec_.setMaxUncompressed(maxUncompressed);
195 }
virtual void setMaxUncompressed(uint64_t maxUncompressed)
Definition: HeaderCodec.h:73
GzipHeaderCodec headerCodec_
Definition: SPDYCodec.h:377
bool proxygen::SPDYCodec::supportsPushTransactions ( ) const
inlineoverridevirtual

Check whether the codec supports pushing resources from server to client.

Implements proxygen::HTTPCodec.

Definition at line 53 of file SPDYCodec.h.

References folly::size(), statusCode, uint32_t, uint64_t, and fizz::detail::writeBuf().

53 { return true; }
bool proxygen::SPDYCodec::supportsSessionFlowControl ( ) const
overridevirtual

Returns true iff this codec supports session level flow control

Reimplemented from proxygen::HTTPParallelCodec.

Definition at line 214 of file SPDYCodec.cpp.

References proxygen::SPDYVersionSettings::majorVersion, proxygen::SPDYVersionSettings::minorVersion, and versionSettings_.

Referenced by TEST().

214  {
215  return versionSettings_.majorVersion > 3 ||
217 }
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
bool proxygen::SPDYCodec::supportsStreamFlowControl ( ) const
overridevirtual

Returns true iff this codec supports per stream flow control

Reimplemented from proxygen::HTTPParallelCodec.

Definition at line 210 of file SPDYCodec.cpp.

References proxygen::SPDYVersionSettings::majorVersion, and versionSettings_.

210  {
211  return versionSettings_.majorVersion > 2;
212 }
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342

Member Data Documentation

folly::fbvector<StreamID> proxygen::SPDYCodec::closedStreams_
private

Definition at line 341 of file SPDYCodec.h.

bool proxygen::SPDYCodec::ctrl_
private

Definition at line 375 of file SPDYCodec.h.

Referenced by parseIngress().

const folly::IOBuf* proxygen::SPDYCodec::currentIngressBuf_ {nullptr}
private

Definition at line 355 of file SPDYCodec.h.

Referenced by failSession(), failStream(), and onIngress().

HTTPSettings proxygen::SPDYCodec::egressSettings_
private
uint8_t proxygen::SPDYCodec::flags_ {0}
private
enum proxygen::SPDYCodec::FrameState proxygen::SPDYCodec::frameState_
private

Referenced by parseIngress().

GzipHeaderCodec proxygen::SPDYCodec::headerCodec_
private
HTTPSettings proxygen::SPDYCodec::ingressSettings_
private
uint32_t proxygen::SPDYCodec::length_ {0}
private

Definition at line 363 of file SPDYCodec.h.

Referenced by checkLength(), checkMinLength(), decodeHeaders(), onControlFrame(), and parseIngress().

uint32_t proxygen::SPDYCodec::maxFrameLength_ {spdy::kMaxFrameLength}
private

Definition at line 361 of file SPDYCodec.h.

Referenced by parseIngress(), and setMaxFrameLength().

StreamID proxygen::SPDYCodec::nextEgressPingID_
private

Definition at line 357 of file SPDYCodec.h.

Referenced by generatePingRequest(), onPing(), and SPDYCodec().

const StreamID proxygen::SPDYCodec::NoStream = 0
static
std::unique_ptr<HTTPMessage> proxygen::SPDYCodec::partialMsg_
private

Definition at line 353 of file SPDYCodec.h.

Referenced by failStream(), and parseHeaders().

uint32_t proxygen::SPDYCodec::streamId_ {0}
private
uint16_t proxygen::SPDYCodec::type_ {0xffff}
private

Definition at line 365 of file SPDYCodec.h.

Referenced by decodeHeaders(), onControlFrame(), parseHeaders(), and parseIngress().

std::string proxygen::SPDYCodec::userAgent_
private

Definition at line 354 of file SPDYCodec.h.

Referenced by getUserAgent(), and onSynCommon().

uint16_t proxygen::SPDYCodec::version_ {0}
private

Definition at line 364 of file SPDYCodec.h.

Referenced by onControlFrame(), onSettings(), onSynCommon(), parseHeaders(), and parseIngress().


The documentation for this class was generated from the following files: