2 * Copyright 2015 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include <folly/wangle/codec/LengthFieldBasedFrameDecoder.h>
18 namespace folly { namespace wangle {
20 LengthFieldBasedFrameDecoder::LengthFieldBasedFrameDecoder(
21 uint32_t lengthFieldLength,
22 uint32_t maxFrameLength,
23 uint32_t lengthFieldOffset,
24 uint32_t lengthAdjustment,
25 uint32_t initialBytesToStrip,
26 bool networkByteOrder)
27 : lengthFieldLength_(lengthFieldLength)
28 , maxFrameLength_(maxFrameLength)
29 , lengthFieldOffset_(lengthFieldOffset)
30 , lengthAdjustment_(lengthAdjustment)
31 , initialBytesToStrip_(initialBytesToStrip)
32 , networkByteOrder_(networkByteOrder)
33 , lengthFieldEndOffset_(lengthFieldOffset + lengthFieldLength) {
34 CHECK(maxFrameLength > 0);
35 CHECK(lengthFieldOffset <= maxFrameLength - lengthFieldLength);
38 std::unique_ptr<IOBuf> LengthFieldBasedFrameDecoder::decode(
39 Context* ctx, IOBufQueue& buf, size_t&) {
40 // discarding too long frame
41 if (buf.chainLength() < lengthFieldEndOffset_) {
45 uint64_t frameLength = getUnadjustedFrameLength(
46 buf, lengthFieldOffset_, lengthFieldLength_, networkByteOrder_);
48 frameLength += lengthAdjustment_ + lengthFieldEndOffset_;
50 if (frameLength < lengthFieldEndOffset_) {
51 buf.trimStart(lengthFieldEndOffset_);
52 ctx->fireReadException(folly::make_exception_wrapper<std::runtime_error>(
57 if (frameLength > maxFrameLength_) {
58 buf.trimStart(frameLength);
59 ctx->fireReadException(folly::make_exception_wrapper<std::runtime_error>(
60 "Frame larger than " +
61 folly::to<std::string>(maxFrameLength_)));
65 if (buf.chainLength() < frameLength) {
69 if (initialBytesToStrip_ > frameLength) {
70 buf.trimStart(frameLength);
71 ctx->fireReadException(folly::make_exception_wrapper<std::runtime_error>(
72 "InitialBytesToSkip larger than frame"));
76 buf.trimStart(initialBytesToStrip_);
77 int actualFrameLength = frameLength - initialBytesToStrip_;
78 return buf.split(actualFrameLength);
81 uint64_t LengthFieldBasedFrameDecoder::getUnadjustedFrameLength(
82 IOBufQueue& buf, int offset, int length, bool networkByteOrder) {
83 folly::io::Cursor c(buf.front());
90 if (networkByteOrder) {
91 frameLength = c.readBE<uint8_t>();
93 frameLength = c.readLE<uint8_t>();
98 if (networkByteOrder) {
99 frameLength = c.readBE<uint16_t>();
101 frameLength = c.readLE<uint16_t>();
106 if (networkByteOrder) {
107 frameLength = c.readBE<uint32_t>();
109 frameLength = c.readLE<uint32_t>();
114 if (networkByteOrder) {
115 frameLength = c.readBE<uint64_t>();
117 frameLength = c.readLE<uint64_t>();