| 220 | } |
| 221 | |
| 222 | bool readFrame() { |
| 223 | uint8_t headerBuffer[8]; |
| 224 | |
| 225 | auto read = transport_->read(headerBuffer, 2); |
| 226 | if (read < 2) { |
| 227 | return false; |
| 228 | } |
| 229 | // Since Thrift has its own message end marker and we read frame by frame, |
| 230 | // it doesn't really matter if the frame is marked as FIN. |
| 231 | // Capture it only for debugging only. |
| 232 | auto fin = (headerBuffer[0] & 0x80) != 0; |
| 233 | THRIFT_UNUSED_VARIABLE(fin); |
| 234 | |
| 235 | // RSV1, RSV2, RSV3 |
| 236 | if ((headerBuffer[0] & 0x70) != 0) { |
| 237 | failConnection(CloseCode::ProtocolError); |
| 238 | throw TTransportException(TTransportException::CORRUPTED_DATA, |
| 239 | "Reserved bits must be zeroes"); |
| 240 | } |
| 241 | |
| 242 | auto opcode = (Opcode)(headerBuffer[0] & 0x0F); |
| 243 | |
| 244 | // Mask |
| 245 | if ((headerBuffer[1] & 0x80) == 0) { |
| 246 | failConnection(CloseCode::ProtocolError); |
| 247 | throw TTransportException(TTransportException::CORRUPTED_DATA, |
| 248 | "Messages from the client must be masked"); |
| 249 | } |
| 250 | |
| 251 | // Read the length |
| 252 | uint64_t payloadLength = headerBuffer[1] & 0x7F; |
| 253 | if (payloadLength == 126) { |
| 254 | read = transport_->read(headerBuffer, 2); |
| 255 | if (read < 2) { |
| 256 | return false; |
| 257 | } |
| 258 | payloadLength = ntohs(*reinterpret_cast<uint16_t*>(headerBuffer)); |
| 259 | } else if (payloadLength == 127) { |
| 260 | read = transport_->read(headerBuffer, 8); |
| 261 | if (read < 8) { |
| 262 | return false; |
| 263 | } |
| 264 | payloadLength = THRIFT_ntohll(*reinterpret_cast<uint64_t*>(headerBuffer)); |
| 265 | if ((payloadLength & 0x8000000000000000) != 0) { |
| 266 | failConnection(CloseCode::ProtocolError); |
| 267 | throw TTransportException( |
| 268 | TTransportException::CORRUPTED_DATA, |
| 269 | "The most significant bit of the payload length must be zero"); |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | // size_t is smaller than a ulong on a 32-bit system |
| 274 | if (payloadLength > UINT32_MAX) { |
| 275 | failConnection(CloseCode::MessageTooBig); |
| 276 | return false; |
| 277 | } |
| 278 | |
| 279 | auto length = static_cast<uint32_t>(payloadLength); |
nothing calls this directly
no test coverage detected