2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
20 #ifndef THRIFT_TRANSPORT_THEADERTRANSPORT_H_
21 #define THRIFT_TRANSPORT_THEADERTRANSPORT_H_ 1
36 #include <boost/scoped_array.hpp>
38 #include <thrift/protocol/TProtocolTypes.h>
39 #include <thrift/transport/TBufferTransports.h>
40 #include <thrift/transport/TTransport.h>
41 #include <thrift/transport/TVirtualTransport.h>
44 THRIFT_HEADER_CLIENT_TYPE
= 0,
45 THRIFT_FRAMED_BINARY
= 1,
46 THRIFT_UNFRAMED_BINARY
= 2,
47 THRIFT_FRAMED_COMPACT
= 3,
48 THRIFT_UNFRAMED_COMPACT
= 4,
49 THRIFT_UNKNOWN_CLIENT_TYPE
= 5,
56 using apache::thrift::protocol::T_COMPACT_PROTOCOL
;
59 * Header transport. All writes go into an in-memory buffer until flush is
60 * called, at which point the transport writes the length of the entire
61 * binary chunk followed by the data payload. This allows the receiver on the
62 * other end to always do fixed-length reads.
64 * Subclass TFramedTransport because most of the read/write methods are similar
65 * and need similar buffers. Major changes are readFrame & flush.
67 * Header Transport *must* be the same transport for both input and
68 * output when used on the server side - client responses should be
69 * the same protocol as those in the request.
71 class THeaderTransport
: public TVirtualTransport
<THeaderTransport
, TFramedTransport
> {
73 static const int DEFAULT_BUFFER_SIZE
= 512u;
74 static const int THRIFT_MAX_VARINT32_BYTES
= 5;
76 /// Use default buffer sizes.
77 explicit THeaderTransport(const std::shared_ptr
<TTransport
>& transport
)
78 : TVirtualTransport(transport
),
79 outTransport_(transport
),
80 protoId(T_COMPACT_PROTOCOL
),
81 clientType(THRIFT_HEADER_CLIENT_TYPE
),
86 if (!transport_
) throw std::invalid_argument("transport is empty");
90 THeaderTransport(const std::shared_ptr
<TTransport
> inTransport
,
91 const std::shared_ptr
<TTransport
> outTransport
)
92 : TVirtualTransport(inTransport
),
93 outTransport_(outTransport
),
94 protoId(T_COMPACT_PROTOCOL
),
95 clientType(THRIFT_HEADER_CLIENT_TYPE
),
100 if (!transport_
) throw std::invalid_argument("inTransport is empty");
101 if (!outTransport_
) throw std::invalid_argument("outTransport is empty");
105 uint32_t readSlow(uint8_t* buf
, uint32_t len
) override
;
106 void flush() override
;
108 void resizeTransformBuffer(uint32_t additionalSize
= 0);
110 uint16_t getProtocolId() const;
111 void setProtocolId(uint16_t protoId
) { this->protoId
= protoId
; }
113 void resetProtocol();
116 * We know we got a packet in header format here, try to parse the header
118 * @param headerSize size of the header portion
119 * @param sz Size of the whole message, including header
121 void readHeaderFormat(uint16_t headerSize
, uint32_t sz
);
124 * Untransform the data based on the received header flags
125 * On conclusion of function, setReadBuffer is called with the
126 * untransformed data.
128 * @param ptr ptr to data
129 * @param size of data
131 void untransform(uint8_t* ptr
, uint32_t sz
);
134 * Transform the data based on our write transform flags
135 * At conclusion of function the write buffer is set to the
138 * @param ptr Ptr to data to transform
139 * @param sz Size of data buffer
141 void transform(uint8_t* ptr
, uint32_t sz
);
143 uint16_t getNumTransforms() const {
144 return safe_numeric_cast
<uint16_t>(writeTrans_
.size());
147 void setTransform(uint16_t transId
) { writeTrans_
.push_back(transId
); }
151 typedef std::map
<std::string
, std::string
> StringToStringMap
;
153 // these work with write headers
154 void setHeader(const std::string
& key
, const std::string
& value
);
158 StringToStringMap
& getWriteHeaders() { return writeHeaders_
; }
160 // these work with read headers
161 const StringToStringMap
& getHeaders() const { return readHeaders_
; }
163 // accessors for seqId
164 int32_t getSequenceNumber() const { return seqId
; }
165 void setSequenceNumber(int32_t seqId
) { this->seqId
= seqId
; }
168 ZLIB_TRANSFORM
= 0x01,
173 * Reads a frame of input from the underlying stream.
175 * Returns true if a frame was read successfully, or false on EOF.
176 * (Raises a TTransportException if EOF occurs after a partial frame.)
178 bool readFrame() override
;
180 void ensureReadBuffer(uint32_t sz
);
181 uint32_t getWriteBytes();
184 setReadBuffer(nullptr, 0);
185 setWriteBuffer(wBuf_
.get(), wBufSize_
);
188 std::shared_ptr
<TTransport
> outTransport_
;
190 // 0 and 16th bits must be 0 to differentiate from framed & unframed
191 static const uint32_t HEADER_MAGIC
= 0x0FFF0000;
192 static const uint32_t HEADER_MASK
= 0xFFFF0000;
193 static const uint32_t FLAGS_MASK
= 0x0000FFFF;
195 static const uint32_t MAX_FRAME_SIZE
= 0x3FFFFFFF;
202 std::vector
<uint16_t> readTrans_
;
203 std::vector
<uint16_t> writeTrans_
;
205 // Map to use for headers
206 StringToStringMap readHeaders_
;
207 StringToStringMap writeHeaders_
;
210 * Returns the maximum number of bytes that write k/v headers can take
212 uint32_t getMaxWriteHeadersSize() const;
216 // start at 1 to avoid confusing header padding for an infoId
218 END
// signal the end of infoIds we can handle
222 // Buffers to use for transform processing
224 boost::scoped_array
<uint8_t> tBuf_
;
226 void readString(uint8_t*& ptr
, /* out */ std::string
& str
, uint8_t const* headerBoundary
);
228 void writeString(uint8_t*& ptr
, const std::string
& str
);
232 * Read an i16 from the wire as a varint. The MSB of each byte is set
233 * if there is another byte to follow. This can read up to 3 bytes.
235 uint32_t readVarint16(uint8_t const* ptr
, int16_t* i16
, uint8_t const* boundary
);
238 * Read an i32 from the wire as a varint. The MSB of each byte is set
239 * if there is another byte to follow. This can read up to 5 bytes.
241 uint32_t readVarint32(uint8_t const* ptr
, int32_t* i32
, uint8_t const* boundary
);
244 * Write an i32 as a varint. Results in 1-5 bytes on the wire.
246 uint32_t writeVarint32(int32_t n
, uint8_t* pkt
);
249 * Write an i16 as a varint. Results in 1-3 bytes on the wire.
251 uint32_t writeVarint16(int16_t n
, uint8_t* pkt
);
255 * Wraps a transport into a header one.
258 class THeaderTransportFactory
: public TTransportFactory
{
260 THeaderTransportFactory() = default;
262 ~THeaderTransportFactory() override
= default;
265 * Wraps the transport into a header one.
267 std::shared_ptr
<TTransport
> getTransport(std::shared_ptr
<TTransport
> trans
) override
{
268 return std::shared_ptr
<TTransport
>(new THeaderTransport(trans
));
273 } // apache::thrift::transport
275 #endif // #ifndef THRIFT_TRANSPORT_THEADERTRANSPORT_H_