31 using std::unique_ptr;
37 const size_t kMaxExpandedHeaderLineBytes = 80 * 1024;
45 ZlibConfig(
SPDYVersion inVersion,
int inCompressionLevel)
46 :
version(inVersion), compressionLevel(inCompressionLevel) {}
49 return (
version == lhs.version) &&
50 (compressionLevel == lhs.compressionLevel);
53 bool operator<(
const ZlibConfig& lhs)
const {
54 return (
version < lhs.version) ||
56 (compressionLevel < lhs.compressionLevel));
64 deflateEnd(&deflater);
65 inflateEnd(&inflater);
78 if (size > buf->capacity()) {
84 DCHECK(!buf->isShared());
88 void appendString(
uint8_t*& dst,
const string& str) {
89 size_t len = str.length();
90 memcpy(dst, str.data(), len);
98 int compressionLevel) {
100 using ZlibContextMap = std::map<ZlibConfig, std::unique_ptr<ZlibContext>>;
102 ZlibConfig zlibConfig(versionSettings.
version, compressionLevel);
103 auto match = ctxmap.find(zlibConfig);
104 if (match != ctxmap.end()) {
105 return match->second.get();
110 auto newContext = std::make_unique<ZlibContext>();
111 newContext->deflater.zalloc = Z_NULL;
112 newContext->deflater.zfree = Z_NULL;
113 newContext->deflater.opaque = Z_NULL;
114 newContext->deflater.avail_in = 0;
115 newContext->deflater.next_in = Z_NULL;
116 int windowBits = (compressionLevel == Z_NO_COMPRESSION) ? 8 : 11;
117 int r = deflateInit2(
118 &(newContext->deflater),
126 if (compressionLevel != Z_NO_COMPRESSION) {
127 r = deflateSetDictionary(&(newContext->deflater), versionSettings.
dict,
132 newContext->inflater.zalloc = Z_NULL;
133 newContext->inflater.zfree = Z_NULL;
134 newContext->inflater.opaque = Z_NULL;
135 newContext->inflater.avail_in = 0;
136 newContext->inflater.next_in = Z_NULL;
138 #if ZLIB_VERNUM == 0x1250 141 newContext->inflater.reserved = 0x01;
143 r = inflateInit2(&(newContext->inflater), MAX_WBITS);
146 auto result = newContext.get();
147 ctxmap.emplace(zlibConfig,
std::move(newContext));
158 : versionSettings_(versionSettings) {
161 auto context = getZlibContext(versionSettings, compressionLevel);
170 SPDYCodec::getVersionSettings(version)) {}
187 std::sort(headers.begin(), headers.end());
196 for (
const Header& header : headers) {
198 maxUncompressedSize += header.name->length();
200 maxUncompressedSize += header.value->length();
208 VLOG(5) <<
"reserving " << maxUncompressedSize
209 <<
" bytes for uncompressed headers";
210 uncompressed.reserve(0, maxUncompressedSize);
213 uint8_t* dst = uncompressed.writableData();
217 uint8_t* lastValueLenPtr =
nullptr;
218 size_t lastValueLen = 0;
219 unsigned numHeaders = 0;
220 for (
const Header& header : headers) {
221 if ((header.code != lastCode) || (*header.name != *lastName)) {
228 char* nameBegin = (
char *)dst;
229 appendString(dst, *header.name);
232 lastValueLenPtr = dst;
233 lastValueLen = header.value->length();
235 appendString(dst, *header.value);
236 lastCode = header.code;
237 lastName = header.name;
238 }
else if (header.value->length() > 0) {
240 if (lastValueLen > 0) {
245 appendString(dst, *header.value);
247 lastValueLen += header.value->length();
248 uint8_t* tmp = lastValueLenPtr;
255 size_t uncompressedLen = dst - uncompressed.writableData();
258 dst = uncompressed.writableData();
263 size_t maxDeflatedSize = deflateBound(&
deflater_, uncompressedLen);
264 unique_ptr<IOBuf> out(IOBuf::create(maxDeflatedSize +
encodeHeadroom_));
268 deflater_.next_in = uncompressed.writableData();
272 int r = deflate(&
deflater_, Z_SYNC_FLUSH);
277 VLOG(4) <<
"header size orig=" << uncompressedLen
278 <<
", max deflated=" << maxDeflatedSize
279 <<
", actual deflated=" << out->
length();
304 auto next = cursor.peek();
309 if (uncompressed.tailroom() == 0) {
313 LOG(
ERROR) <<
"Doubling capacity of SPDY headers buffer";
314 uncompressed.reserve(0, uncompressed.capacity());
317 inflater_.next_out = uncompressed.writableTail();
318 inflater_.avail_out = uncompressed.tailroom();
320 if (r == Z_NEED_DICT) {
326 LOG(
ERROR) <<
"inflate set dictionary failed with error=" << r;
334 LOG(
ERROR) <<
"inflate failed with error=" << r;
337 uncompressed.append(uncompressed.tailroom() -
inflater_.avail_out);
339 LOG(
ERROR) <<
"Decompressed headers too large";
344 consumed += chunkLen;
345 cursor.skip(chunkLen);
354 size_t expandedHeaderLineBytes = 0;
356 if (result.hasError()) {
359 expandedHeaderLineBytes = *result;
361 if (
UNLIKELY(expandedHeaderLineBytes > kMaxExpandedHeaderLineBytes)) {
362 LOG(
ERROR) <<
"expanded headers too large";
373 size_t expandedHeaderLineBytes = 0;
374 Cursor headerCursor(&uncompressed);
380 }
catch (
const std::out_of_range& ex) {
389 }
catch (
const std::out_of_range& ex) {
393 if (len == 0 && !headerName) {
394 LOG(
ERROR) <<
"empty header name";
399 if (len > uncompressedLength) {
400 throw std::out_of_range(
401 folly::to<string>(
"bad length=", len,
" uncompressedLength=",
402 uncompressedLength));
403 }
else if (
next.second >= len) {
406 headerCursor.
skip(len);
409 unique_ptr<char[]>
data (
new char[len]);
410 headerCursor.
pull(data.get(), len);
411 outHeaders_.emplace_back(data.release(), len,
true,
false);
413 uncompressedLength -= len;
414 }
catch (
const std::out_of_range& ex) {
415 LOG(
ERROR) <<
"bad encoding for nv=" <<
i <<
": " 422 for (
const char c: headerName->
str) {
423 if (c < 0x20 || c > 0x7e || (
'A' <= c && c <=
'Z')) {
424 LOG(
ERROR) <<
"invalid header value";
431 const char* valueStart = headerValue.
str.
data();
432 const char* pos = valueStart;
433 const char*
stop = valueStart + headerValue.
str.
size();
436 if (pos - valueStart == 0) {
437 LOG(
ERROR) <<
"empty header value for header=" << headerName;
441 headerValue.
str.
reset(valueStart, pos - valueStart);
447 outHeaders_.emplace_back(valueStart, pos - valueStart,
false,
true);
448 expandedHeaderLineBytes += ((pos - valueStart) +
451 valueStart = pos + 1;
457 if (pos - valueStart == 0) {
458 LOG(
ERROR) <<
"empty header value for header=" << headerName;
464 outHeaders_.emplace_back(valueStart, pos - valueStart,
false,
true);
465 expandedHeaderLineBytes += (pos - valueStart) + headerName->
str.
size();
467 headerName =
nullptr;
470 return expandedHeaderLineBytes;
const uint32_t kMaxFrameLength
static std::string printHexFolly(const folly::IOBuf *buf, bool coalesce=false)
fbstring exceptionStr(const std::exception &e)
constexpr detail::Map< Move > move
constexpr size_type size() const
bool operator==(const HTTPMessage &msg1, const HTTPMessage &msg2)
void advance(std::size_t amount)
requires E e noexcept(noexcept(s.error(std::move(e))))
void pull(void *buf, size_t len)
bool operator<(const AcceptorAddress &lv, const AcceptorAddress &rv)
std::pair< const uint8_t *, size_t > peek()
constexpr auto size(C const &c) -> decltype(c.size())
std::deque< HeaderPiece > HeaderPieceList
constexpr Unexpected< typename std::decay< Error >::type > makeUnexpected(Error &&)
constexpr Iter data() const
std::size_t length() const
void(* appendSizeFun)(uint8_t *&, size_t)
if(FOLLY_USE_SYMBOLIZER) add_library(folly_exception_tracer_base ExceptionTracer.cpp StackTrace.cpp) apply_folly_compile_options_to_target(folly_exception_tracer_base) target_link_libraries(folly_exception_tracer_base PUBLIC folly) add_library(folly_exception_tracer ExceptionStackTraceLib.cpp ExceptionTracerLib.cpp) apply_folly_compile_options_to_target(folly_exception_tracer) target_link_libraries(folly_exception_tracer PUBLIC folly_exception_tracer_base) add_library(folly_exception_counter ExceptionCounterLib.cpp) apply_folly_compile_options_to_target(folly_exception_counter) target_link_libraries(folly_exception_counter PUBLIC folly_exception_tracer) install(FILES ExceptionAbi.h ExceptionCounterLib.h ExceptionTracer.h ExceptionTracerLib.h StackTrace.h DESTINATION $
const std::string empty_string
void toLowerAscii(char *str, size_t length)
FOLLY_EXPORT static FOLLY_ALWAYS_INLINE T & get()
const unsigned char * dict
PUSHMI_INLINE_VAR constexpr detail::get_fn< T > get
static constexpr uint64_t data[1]
uint32_t(* parseSizeFun)(folly::io::Cursor *)
void append(std::size_t amount)
void reset(Iter start, size_type size)
constexpr detail::First first