proxygen
LengthFieldBasedFrameDecoder.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
18 
19 using folly::IOBuf;
20 using folly::IOBufQueue;
21 
22 namespace wangle {
23 
25  uint32_t lengthFieldLength,
26  uint32_t maxFrameLength,
27  uint32_t lengthFieldOffset,
28  int32_t lengthAdjustment,
29  uint32_t initialBytesToStrip,
30  bool networkByteOrder)
31  : lengthFieldLength_(lengthFieldLength)
32  , maxFrameLength_(maxFrameLength)
33  , lengthFieldOffset_(lengthFieldOffset)
34  , lengthAdjustment_(lengthAdjustment)
35  , initialBytesToStrip_(initialBytesToStrip)
36  , networkByteOrder_(networkByteOrder)
37  , lengthFieldEndOffset_(lengthFieldOffset + lengthFieldLength) {
38  CHECK(maxFrameLength > 0);
39  CHECK(lengthFieldOffset <= maxFrameLength - lengthFieldLength);
40 }
41 
43  IOBufQueue& buf,
44  std::unique_ptr<IOBuf>& result,
45  size_t&) {
46  // discarding too long frame
47  if (buf.chainLength() < lengthFieldEndOffset_) {
48  return false;
49  }
50 
51  uint64_t frameLength = getUnadjustedFrameLength(
53 
55 
56  if (frameLength < lengthFieldEndOffset_) {
57  buf.trimStart(lengthFieldEndOffset_);
58  ctx->fireReadException(folly::make_exception_wrapper<std::runtime_error>(
59  "Frame too small"));
60  return false;
61  }
62 
63  if (frameLength > maxFrameLength_) {
64  buf.trimStartAtMost(frameLength);
65  ctx->fireReadException(folly::make_exception_wrapper<std::runtime_error>(
66  "Frame larger than " +
67  folly::to<std::string>(maxFrameLength_)));
68  return false;
69  }
70 
71  if (buf.chainLength() < frameLength) {
72  return false;
73  }
74 
75  if (initialBytesToStrip_ > frameLength) {
76  buf.trimStart(frameLength);
77  ctx->fireReadException(folly::make_exception_wrapper<std::runtime_error>(
78  "InitialBytesToSkip larger than frame"));
79  return false;
80  }
81 
83  int actualFrameLength = frameLength - initialBytesToStrip_;
84  result = buf.split(actualFrameLength);
85  return true;
86 }
87 
89  IOBufQueue& buf, int offset, int length, bool networkByteOrder) {
90  folly::io::Cursor c(buf.front());
91  uint64_t frameLength;
92 
93  c.skip(offset);
94 
95  switch(length) {
96  case 1:{
97  if (networkByteOrder) {
98  frameLength = c.readBE<uint8_t>();
99  } else {
100  frameLength = c.readLE<uint8_t>();
101  }
102  break;
103  }
104  case 2:{
105  if (networkByteOrder) {
106  frameLength = c.readBE<uint16_t>();
107  } else {
108  frameLength = c.readLE<uint16_t>();
109  }
110  break;
111  }
112  case 4:{
113  if (networkByteOrder) {
114  frameLength = c.readBE<uint32_t>();
115  } else {
116  frameLength = c.readLE<uint32_t>();
117  }
118  break;
119  }
120  case 8:{
121  if (networkByteOrder) {
122  frameLength = c.readBE<uint64_t>();
123  } else {
124  frameLength = c.readLE<uint64_t>();
125  }
126  break;
127  }
128  }
129 
130  return frameLength;
131 }
132 
133 
134 } // namespace wangle
std::unique_ptr< folly::IOBuf > split(size_t n)
Definition: IOBufQueue.h:420
const folly::IOBuf * front() const
Definition: IOBufQueue.h:476
bool decode(Context *ctx, folly::IOBufQueue &buf, std::unique_ptr< folly::IOBuf > &result, size_t &) override
LengthFieldBasedFrameDecoder(uint32_t lengthFieldLength=4, uint32_t maxFrameLength=UINT_MAX, uint32_t lengthFieldOffset=0, int32_t lengthAdjustment=0, uint32_t initialBytesToStrip=4, bool networkByteOrder=true)
size_t chainLength() const
Definition: IOBufQueue.h:492
size_t trimStartAtMost(size_t amount)
Definition: IOBufQueue.cpp:263
InboundHandler< folly::IOBufQueue &, M >::Context Context
uint64_t getUnadjustedFrameLength(folly::IOBufQueue &buf, int offset, int length, bool networkByteOrder)
void trimStart(size_t amount)
Definition: IOBufQueue.cpp:255
char c