13 #include <boost/algorithm/string.hpp> 19 #include <glog/logging.h> 38 using std::unique_ptr;
46 const size_t kFrameSizeDataCommon = 8;
47 const size_t kFrameSizeControlCommon = 8;
48 const size_t kFrameSizeSynStream = 10;
49 const size_t kFrameSizeSynReplyv3 = 4;
50 const size_t kFrameSizeRstStream = 8;
51 const size_t kFrameSizeGoawayv3 = 8;
52 const size_t kFrameSizeHeaders = 4;
53 const size_t kFrameSizePing = 4;
54 const size_t kFrameSizeSettings = 4;
55 const size_t kFrameSizeSettingsEntry = 8;
56 const size_t kFrameSizeWindowUpdate = 8;
58 const size_t kFrameSizeNameValuev3 = 4;
60 const size_t kPriShiftv3 = 5;
62 const size_t kMaxUncompressed = 96 * 1024;
64 #define CTRL_MASK 0x80 65 #define FLAGS_MASK 0xff000000 66 #define STREAM_ID_MASK 0x7fffffff 67 #define VERSION_MASK 0x7fff 68 #define DELTA_WINDOW_SIZE_MASK 0x7fffffff 71 #define FRAME_HEADER_LEN 8 87 length |= (
int32_t(flags) << 24);
97 auto chunk = cursor->
peek();
100 return ntohl(*(
uint32_t*)chunk.first);
105 class SPDYSessionFailed :
public std::exception {
113 class SPDYStreamFailed :
public std::exception {
115 SPDYStreamFailed(
bool inIsNew,
uint32_t inStreamID,
126 ~SPDYStreamFailed()
throw()
override {}
128 const char* what()
const throw()
override {
return message.c_str(); }
144 static const auto spdyVersions =
new std::vector<SPDYVersionSettings> {
153 0x8003, kFrameSizeSynReplyv3, kFrameSizeNameValuev3,
161 0x8003, kFrameSizeSynReplyv3, kFrameSizeNameValuev3,
165 auto intVersion =
static_cast<unsigned>(
version);
166 CHECK_LT(intVersion, spdyVersions->size());
167 return (*spdyVersions)[intVersion];
171 int spdyCompressionLevel )
173 versionSettings_(getVersionSettings(version)),
176 headerCodec_(spdyCompressionLevel, versionSettings_) {
202 LOG(FATAL) <<
"unreachable";
220 if (
length_ != expectedLength) {
222 << msg <<
": invalid length " <<
length_ <<
" != " << expectedLength;
229 LOG(
ERROR) << msg <<
": invalid length " <<
length_ <<
" < " << minLength;
235 size_t bytesParsed = 0;
239 }
catch (
const SPDYSessionFailed& ex) {
286 LOG(
ERROR) <<
"excessive frame size length_=" <<
length_;
295 }
else if (
frameState_ == FrameState::CTRL_FRAME_DATA) {
300 VLOG(6) <<
"Need more data: length_=" <<
length_ <<
" avail=" << avail;
305 }
catch (
const SPDYStreamFailed& ex) {
306 failStream(ex.isNew, ex.streamID, ex.statusCode, ex.what());
309 }
else if (avail > 0 ||
length_ == 0) {
311 DCHECK(FrameState::DATA_FRAME_DATA ==
frameState_);
316 std::unique_ptr<IOBuf> chunk;
317 cursor.
clone(chunk, toClone);
332 return chainLength - avail;
344 length_ -= kFrameSizeSynStream;
379 if (length_ / 8 < numSettings) {
380 LOG(
ERROR) <<
"SETTINGS: number of settings to high. " 381 << length_ <<
" < 8 * " << numSettings;
395 settings.emplace_back(flags,
id, value);
401 VLOG(4) <<
"Noop received. Doing nothing.";
440 checkLength(kFrameSizeWindowUpdate,
"WINDOW_UPDATE");
448 VLOG(4) <<
"Skipping unsupported/deprecated CREDENTIAL frame";
452 VLOG(3) <<
"unimplemented control frame type " <<
type_ 453 <<
", frame length: " <<
length_;
460 cursor.
skip(length_);
468 if (result.hasError()) {
469 auto err = result.error();
482 "Error parsing header: " + folly::to<string>(err));
485 length_ -= result->bytesConsumed;
504 const HTTPMessage& msg, vector<Header>& allHeaders,
510 allHeaders.emplace_back(
517 const string&
value) {
518 static const std::bitset<256> s_perHopHeaderCodes{
533 VLOG(3) <<
"Dropping SPDY reserved header " <<
name;
536 if (name.length() == 0) {
537 VLOG(2) <<
"Dropping header with empty name";
541 VLOG(2) <<
"Dropping header \"" << name
542 <<
"\" with empty value for spdy/2";
545 allHeaders.emplace_back(code, name, value);
567 vector<Header> allHeaders;
568 allHeaders.reserve(headers.
size() + 4);
594 vector<Header> allHeaders;
595 allHeaders.reserve(headers.
size() + 6);
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();
631 VLOG(2) <<
"Suppressing SYN_STREAM/REPLY for stream=" << stream <<
654 VLOG(2) <<
"Suppressing SYN_STREAM/REPLY for stream=" << stream <<
672 CHECK((assocStream ==
NoStream && (stream % 2 == 1)) ||
673 ((stream % 2 == 0) && (assocStream % 2 == 1))) <<
674 "Invalid stream ids stream=" << stream <<
" assocStream=" << assocStream;
683 uint32_t fieldsSize = kFrameSizeSynStream;
684 uint32_t headroom = kFrameSizeControlCommon + fieldsSize;
685 bool isPushed = (assocStream !=
NoStream);
710 cursor.writeBE(flagsAndLength(flags, len));
712 cursor.writeBE(
uint32_t(assocStream));
754 cursor.writeBE(flagsAndLength(flags, len));
767 std::unique_ptr<folly::IOBuf> chain,
771 VLOG(2) <<
"Suppressing DATA for stream=" << stream <<
783 CHECK_LT(len, (1 << 24));
814 VLOG(4) <<
"sending EOM for stream=" <<
stream;
816 VLOG(2) <<
"Suppressing EOM for stream=" << stream <<
827 DCHECK_GT(stream, 0);
828 VLOG(4) <<
"sending RST_STREAM for stream=" << stream
837 VLOG(2) <<
"Suppressing RST_STREAM for stream=" << stream <<
843 const size_t frameSize = kFrameSizeControlCommon + kFrameSizeRstStream;
844 const size_t expectedLength = writeBuf.
chainLength() + frameSize;
848 appender.
writeBE(flagsAndLength(0, kFrameSizeRstStream));
859 std::unique_ptr<folly::IOBuf> debugData) {
861 const size_t frameSize = kFrameSizeControlCommon +
864 DCHECK_LE(lastStream,
egressGoawayAck_) <<
"Cannot increase last good stream";
867 VLOG(4) <<
"Not sending GOAWAY for closed session";
870 const size_t expectedLength = writeBuf.
chainLength() + frameSize;
878 string debugInfo = (debugData) ?
879 folly::to<string>(
" with debug info=",
880 (
char*)debugData->
data()) :
"";
881 VLOG(4) <<
"Sending GOAWAY with last acknowledged stream=" 892 case ClosingState::OPEN:
895 case ClosingState::OPEN_WITH_GRACEFUL_DRAIN_ENABLED:
904 case ClosingState::FIRST_GOAWAY_SENT:
907 case ClosingState::CLOSING:
909 case ClosingState::CLOSED:
910 LOG(FATAL) <<
"unreachable";
920 VLOG(4) <<
"Generating ping request with id=" << id;
925 VLOG(4) <<
"Generating ping reply with id=" << uniqueID;
930 const size_t frameSize = kFrameSizeControlCommon + kFrameSizePing;
931 const size_t expectedLength = writeBuf.
chainLength() + frameSize;
935 appender.
writeBE(flagsAndLength(0, kFrameSizePing));
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;
957 kFrameSizeSettingsEntry * numSettings));
962 LOG(WARNING) <<
"Invalid SpdySetting " << (
uint32_t)setting.id;
965 VLOG(5) <<
" writing setting with id=" << *settingId
966 <<
", value=" << setting.value;
971 appender.
writeLE(flagsAndLength(0, *settingId));
973 appender.
writeBE(flagsAndLength(0, *settingId));
991 VLOG(2) <<
"Suppressing WINDOW_UPDATE for stream=" << stream <<
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;
1003 appender.
writeBE(flagsAndLength(0, kFrameSizeWindowUpdate));
1006 DCHECK_EQ(writeBuf.
chainLength(), expectedLength);
1016 for (
uint8_t pri = 0; pri < 8; pri++) {
1034 unique_ptr<IOBuf> payload) {
1035 const size_t frameSize = kFrameSizeDataCommon;
1038 payload->
headroom() >= frameSize &&
1043 payloadLength = payload->
length();
1044 payload->
trimEnd(payloadLength);
1046 auto tail = payload->
pop();
1052 cursor.
writeBE(flagsAndLength(flags, length));
1055 return kFrameSizeDataCommon + length;
1058 unique_ptr<HTTPMessage>
1066 bool hasScheme =
false;
1067 bool hasPath =
false;
1068 bool hasContentLength =
false;
1071 CHECK_EQ((inHeaders.size() & 1), 0);
1072 for (
unsigned i = 0;
i < inHeaders.size();
i += 2) {
1075 if (len > 1 && inHeaders[
i].str[0] ==
':') {
1081 VLOG(5) <<
"Header " << name <<
": " <<
value;
1083 bool valueOk =
false;
1084 bool isPath =
false;
1085 bool isMethod =
false;
1087 if (name ==
"content-length") {
1088 if (hasContentLength) {
1089 throw SPDYStreamFailed(
false, streamID, 400,
1090 "Multiple content-length headers");
1092 hasContentLength =
true;
1094 if ((
version_ == 2 && name ==
"url") ||
1095 (
version_ == 3 && off && name ==
"path")) {
1099 throw SPDYStreamFailed(
false, streamID, 400,
1100 "Multiple paths in header");
1103 }
else if ((
version_ == 2 || off) && name ==
"method") {
1106 if (value ==
"CONNECT") {
1114 if (!nameOk || !valueOk) {
1119 throw SPDYStreamFailed(
false, streamID, 400,
"Bad header value");
1124 msg->setMethod(value);
1125 }
else if (isPath) {
1126 msg->setURL(value.str());
1127 }
else if (name ==
"version") {
1129 msg->setHTTPVersion(1, 0);
1131 msg->setHTTPVersion(1, 1);
1133 }
else if (
version_ == 3 && name ==
"host") {
1135 }
else if (name ==
"scheme") {
1137 if (value ==
"https") {
1138 msg->setSecure(
true);
1140 }
else if (name ==
"status") {
1144 if (value.contains(
' ')) {
1145 folly::split<false>(
' ',
value, codePiece, reasonPiece);
1151 code = folly::to<unsigned int>(codePiece);
1152 }
catch (
const std::range_error& ex) {
1155 if (code >= 100 && code <= 999) {
1156 msg->setStatusCode(code);
1157 msg->setStatusMessage(reasonPiece.
str());
1159 msg->setStatusCode(0);
1160 headers.
add(name, value);
1162 throw SPDYStreamFailed(newStream, streamID,
1164 "Invalid status code");
1166 }
else if (!assocStreamID) {
1168 headers.
add(
"Status", value);
1173 if (value.size() > 0) {
1176 code = folly::to<uint16_t>(
value);
1177 }
catch (
const std::range_error& ex) {
1180 if (code >= 100 && code <= 999) {
1181 msg->setPushStatusCode(code);
1194 if (!inHeaders[
i].isMultiValued() && headers.
exists(name)) {
1195 headers.
add(name, value);
1198 "Duplicate header value");
1200 headers.
add(name, value);
1203 if (assocStreamID &&
1206 throw SPDYStreamFailed(newStream, streamID, 400,
"Bad Request");
1216 const string& accept_encoding =
1218 if (accept_encoding.empty()) {
1221 bool hasGzip =
false;
1222 bool hasDeflate =
false;
1224 string new_encoding = accept_encoding;
1226 new_encoding.append(
", gzip");
1229 new_encoding.append(
", deflate");
1249 streamID, assocStreamID, headers);
1250 msg->setIngressHeaderSize(size);
1255 msg->setPriority(pri);
1262 msg->setIsChunked(
true);
1268 "onHeadersComplete", streamID,
std::move(msg));
1273 if (assocStreamID) {
1275 "onPushMessageBegin", streamID, assocStreamID,
1279 "onMessageBegin", streamID, msg);
1288 VLOG(4) <<
"Got SYN_STREAM, stream=" <<
streamId_ 1289 <<
" pri=" << folly::to<int>(pri);
1300 <<
" assocStreamID=" << assocStream
1320 StreamID(assocStream), headers, pri, size);
1325 VLOG(4) <<
"Got SYN_REPLY, stream=" <<
streamId_;
1338 VLOG(4) <<
"Got RST_STREAM, stream=" <<
streamId_ 1346 VLOG(4) <<
"Got " << settings.size() <<
" settings with " 1347 <<
"version=" <<
version_ <<
" and flags=" 1348 << std::hex << folly::to<unsigned int>(
flags_) << std::dec;
1354 VLOG(2) <<
"Ignoring bogus persisted setting: " << cur.id;
1376 LOG(
ERROR) <<
"Received unknown setting with ID=" << cur.id
1377 <<
", value=" << cur.value
1378 <<
", and flags=" << std::hex << cur.flags << std::dec;
1386 settingsList.push_back(*
s);
1394 bool odd = uniqueID & 0x1;
1395 bool isReply =
true;
1406 LOG(INFO) <<
"Received reply for pingID=" << uniqueID
1407 <<
" that was never sent";
1418 VLOG(4) <<
"Got GOAWAY, lastGoodStream=" << lastGoodStream
1431 LOG(WARNING) <<
"Received multiple GOAWAY with increasing ack";
1436 VLOG(3) <<
"onHeaders is unimplemented.";
1455 folly::to<std::string>(
"SPDYCodec stream error: stream=",
1456 streamID,
" status=", code,
" exception: ", excStr));
1477 folly::to<std::string>(
"SPDYCodec session error: " 1490 if (statusCode == 0) {
1504 if (protocol.length() < 6) {
1508 if (protocol ==
"spdy/3.1") {
1511 if (protocol ==
"spdy/3") {
HTTPSettings ingressSettings_
void onWindowUpdate(uint32_t delta) noexcept
const std::string & getUserAgent() const override
const std::string kVersionStrv3
size_t onIngress(const folly::IOBuf &buf) override
void setHttpStatusCode(uint32_t statusCode)
void onSettings(const SettingList &settings)
void deliverOnMessageBegin(StreamID streamID, StreamID assocStreamID, HTTPMessage *msg)
void append(std::unique_ptr< folly::IOBuf > &&buf, bool pack=false)
size_t chainLength() const
spdy::GoawayStatusCode statusCode
uint8_t getVersion() const
virtual void onError(StreamID stream, const HTTPException &error, bool newTxn=false)=0
void setCurrentIngressBuf(std::unique_ptr< folly::IOBuf > buf)
virtual void onMessageBegin(StreamID stream, HTTPMessage *msg)=0
std::unique_ptr< folly::IOBuf > serializeResponseHeaders(const HTTPMessage &msg, uint32_t headroom=0, HTTPHeaderSize *size=nullptr)
static const StreamID MAX_STREAM_ID
bool caseInsensitiveEqual(folly::StringPiece s, folly::StringPiece t)
void checkLength(uint32_t expectedLength, const std::string &msg)
bool deliverCallbackIfAllowed(T callbackFn, char const *cbName, StreamID stream, Args &&...args)
StreamID egressGoawayAck_
void onSynStream(uint32_t assocStream, uint8_t pri, uint8_t slot, const compress::HeaderPieceList &headers, const HTTPHeaderSize &size)
virtual void onSettings(const SettingsList &)
const folly::IOBuf * currentIngressBuf_
const std::string & getStatusMessage() const
HTTPCodec::Callback * callback_
static bool validateHeaderName(folly::ByteRange name)
StreamCodecFactory stream
virtual void onMessageComplete(StreamID stream, bool upgrade)=0
void clone(std::unique_ptr< folly::IOBuf > &buf, size_t len)
const std::string kSessionProtoNameSPDY3
uint16_t getStatusCode() const
virtual void onPingReply(uint64_t)
std::unique_ptr< HTTPMessage > partialMsg_
constexpr detail::Map< Move > move
const std::string kNamePathv3
void setPartialMsg(std::unique_ptr< HTTPMessage > partialMsg)
void setMaxFrameLength(uint32_t maxFrameLength)
std::vector< SettingData > SettingList
const uint8_t * data() const
const std::string & protocolVersionString
void setProxygenError(ProxygenError proxygenError)
void onRstStream(uint32_t statusCode) noexcept
static std::string formatDateHeader()
const unsigned char kSPDYv3Dictionary[]
bool supportsSessionFlowControl() const override
static http_parser_settings settings
size_t generateRstStream(folly::IOBufQueue &writeBuf, StreamID txn, ErrorCode statusCode) override
void setCodecStatusCode(ErrorCode statusCode)
std::unique_ptr< IOBuf > clone() const
uint8_t getPriority() const
requires E e noexcept(noexcept(s.error(std::move(e))))
size_t parseIngress(const folly::IOBuf &buf)
std::unique_ptr< folly::IOBuf > serializeRequestHeaders(const HTTPMessage &msg, bool isPushed, uint32_t headroom=0, HTTPHeaderSize *size=nullptr)
ResetStatusCode errorCodeToReset(ErrorCode code)
void onControlFrame(folly::io::Cursor &cursor)
const std::string kVersionStrv31
static bool validateMethod(folly::ByteRange method)
const std::string hostStr
std::size_t getNumSettings() const
std::pair< const uint8_t *, size_t > peek()
static const StreamID NoStream
size_t generateChunkHeader(folly::IOBufQueue &writeBuf, StreamID stream, size_t length) override
std::unique_ptr< folly::IOBuf > encodeHeaders(const HTTPMessage &msg, std::vector< compress::Header > &headers, uint32_t headroom=0, HTTPHeaderSize *size=nullptr)
const std::string kNameMethodv2
size_t generatePingReply(folly::IOBufQueue &writeBuf, uint64_t uniqueID) override
size_t generateEOM(folly::IOBufQueue &writeBuf, StreamID stream) override
constexpr auto size(C const &c) -> decltype(c.size())
size_t generateBody(folly::IOBufQueue &writeBuf, StreamID stream, std::unique_ptr< folly::IOBuf > chain, folly::Optional< uint8_t > padding, bool eom) override
void onSynCommon(StreamID streamID, StreamID assocStreamID, const compress::HeaderPieceList &headers, int8_t pri, const HTTPHeaderSize &size)
enum proxygen::HTTPParallelCodec::ClosingState sessionClosing_
virtual void onPingRequest(uint64_t)
void writeBuf(const Buf &buf, folly::io::Appender &out)
virtual uint32_t numIncomingStreams() const
std::unique_ptr< IOBuf > pop()
StreamID ingressGoawayAck_
const std::string kNameStatusv2
void prepend(std::size_t amount)
void onSynReply(const compress::HeaderPieceList &headers, const HTTPHeaderSize &size)
virtual void addPriorityNode(StreamID id, StreamID parent)=0
static bool validateURL(folly::ByteRange url)
std::deque< HeaderPiece > HeaderPieceList
ErrorCode goawayToErrorCode(GoawayStatusCode code)
StreamID nextEgressStreamID_
std::size_t headroom() const
virtual void onFrameHeader(StreamID, uint8_t, uint64_t, uint8_t, uint16_t=0)
const std::string kNameSchemev2
std::size_t length() const
void generateSynStream(StreamID stream, StreamID assocStream, folly::IOBufQueue &writeBuf, const HTTPMessage &msg, bool eom, HTTPHeaderSize *size)
const std::string kNameMethodv3
folly::Optional< proxygen::SettingsId > spdyToHttpSettingsId(proxygen::spdy::SettingsId id)
bool supportsStreamFlowControl() const override
std::unique_ptr< HTTPMessage > parseHeaders(TransportDirection direction, StreamID streamID, StreamID assocStreamID, const compress::HeaderPieceList &headers)
bool rstStatusSupported(int statusCode) const
const char * getErrorCodeString(ErrorCode error)
const std::string kNameVersionv3
void retreat(std::size_t amount)
void generatePushPromise(folly::IOBufQueue &writeBuf, StreamID stream, const HTTPMessage &msg, StreamID assocstream, bool eom=false, HTTPHeaderSize *size=nullptr) override
GoawayStatusCode errorCodeToGoaway(ErrorCode code)
static const char *const value
bool isStreamIngressEgressAllowed(StreamID stream) const
HTTPHeaders & getHeaders()
#define DELTA_WINDOW_SIZE_MASK
size_t generateTrailers(folly::IOBufQueue &writeBuf, StreamID stream, const HTTPHeaders &trailers) override
const std::string kNameHostv3
const std::string httpVersion
RWCursor< CursorAccess::PRIVATE > RWPrivateCursor
StreamID nextEgressPingID_
const std::string & getPushStatusStr() const
const std::string kNamePathv2
std::size_t computeChainDataLength() const
size_t generatePingCommon(folly::IOBufQueue &writeBuf, uint64_t uniqueID)
const std::string kNameStatusv3
uint8_t getMinorVersion() const
folly::Optional< proxygen::spdy::SettingsId > httpToSpdySettingsId(proxygen::SettingsId id)
virtual void onHeadersComplete(StreamID stream, std::unique_ptr< HTTPMessage > msg)=0
size_t generateDataFrame(folly::IOBufQueue &writeBuf, uint32_t streamID, uint8_t flags, uint32_t length, std::unique_ptr< folly::IOBuf > payload)
const std::string empty_string
const std::string kNameVersionv2
std::vector< HTTPSetting > SettingsList
virtual void onGoaway(uint64_t, ErrorCode, std::unique_ptr< folly::IOBuf >=nullptr)
size_t addPriorityNodes(PriorityQueue &queue, folly::IOBufQueue &writeBuf, uint8_t maxLevel) override
const std::vector< HTTPSetting > & getAllSettings()
virtual void onAbort(StreamID, ErrorCode)
void failStream(bool newTxn, StreamID streamID, uint32_t code, std::string excStr=empty_string)
size_t generateWindowUpdate(folly::IOBufQueue &writeBuf, StreamID stream, uint32_t delta) override
const std::string & getMethodString() const
const std::string kNameSchemev3
GzipHeaderCodec headerCodec_
HeaderDecodeResult decodeHeaders(folly::io::Cursor &cursor)
static bool validateHeaderValue(folly::ByteRange value, CtlEscapeMode mode)
virtual void onWindowUpdate(StreamID, uint32_t)
size_t generateChunkTerminator(folly::IOBufQueue &writeBuf, StreamID stream) override
SPDYCodec(TransportDirection direction, SPDYVersion version, int spdyCompressionLevel=Z_NO_COMPRESSION)
const uint32_t kMaxConcurrentStreams
virtual void onPushMessageBegin(StreamID, StreamID, HTTPMessage *)
size_t generateSettings(folly::IOBufQueue &writeBuf) override
const std::string & getURL() const
TransportDirection transportDirection_
static const SPDYVersionSettings & getVersionSettings(SPDYVersion version)
void postallocate(std::size_t n)
void trimEnd(std::size_t amount)
void failSession(uint32_t statusCode)
void generateHeader(folly::IOBufQueue &writeBuf, StreamID stream, const HTTPMessage &msg, bool eom=false, HTTPHeaderSize *size=nullptr) override
const SPDYVersionSettings & versionSettings_
virtual void onBody(StreamID stream, std::unique_ptr< folly::IOBuf > chain, uint16_t padding)=0
size_t generatePingRequest(folly::IOBufQueue &writeBuf) override
static constexpr uint64_t data[1]
bool isSPDYReserved(const std::string &name)
void checkMinLength(uint32_t minLength, const std::string &msg)
CodecProtocol getProtocol() const override
HTTPSettings egressSettings_
void onPing(uint32_t uniqueID) noexcept
size_t totalLength() const
void onHeaders(const compress::HeaderPieceList &headers) noexcept
folly::Function< void()> parent
ErrorCode rstToErrorCode(uint32_t code)
enum proxygen::SPDYCodec::FrameState frameState_
const HTTPSetting * getSetting(SettingsId id) const
void onGoaway(uint32_t lastGoodStream, uint32_t statusCode) noexcept
const std::string versionStr
size_t generateGoaway(folly::IOBufQueue &writeBuf, StreamID lastStream, ErrorCode statusCode, std::unique_ptr< folly::IOBuf > debugData=nullptr) override
static bool hasGzipAndDeflate(const std::string &value, bool &hasGzip, bool &hasDeflate)
void generateSynReply(StreamID stream, folly::IOBufQueue &writeBuf, const HTTPMessage &msg, bool eom, HTTPHeaderSize *size)
void setSetting(SettingsId id, SettingsValue val)
void setMaxUncompressedHeaders(uint32_t maxUncompressed)