1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "remoting/protocol/message_decoder.h" 6 7 #include "base/logging.h" 8 #include "net/base/io_buffer.h" 9 #include "remoting/base/compound_buffer.h" 10 #include "remoting/proto/internal.pb.h" 11 #include "third_party/libjingle/source/talk/base/byteorder.h" 12 13 namespace remoting { 14 namespace protocol { 15 16 MessageDecoder::MessageDecoder() 17 : next_payload_(0), 18 next_payload_known_(false) { 19 } 20 21 MessageDecoder::~MessageDecoder() {} 22 23 void MessageDecoder::AddData(scoped_refptr<net::IOBuffer> data, 24 int data_size) { 25 buffer_.Append(data.get(), data_size); 26 } 27 28 CompoundBuffer* MessageDecoder::GetNextMessage() { 29 // Determine the payload size. If we already know it then skip this part. 30 // We may not have enough data to determine the payload size so use a 31 // utility function to find out. 32 int next_payload = -1; 33 if (!next_payload_known_ && GetPayloadSize(&next_payload)) { 34 DCHECK_NE(-1, next_payload); 35 next_payload_ = next_payload; 36 next_payload_known_ = true; 37 } 38 39 // If the next payload size is still not known or we don't have enough 40 // data for parsing then exit. 41 if (!next_payload_known_ || buffer_.total_bytes() < next_payload_) 42 return NULL; 43 44 CompoundBuffer* message_buffer = new CompoundBuffer(); 45 message_buffer->CopyFrom(buffer_, 0, next_payload_); 46 message_buffer->Lock(); 47 buffer_.CropFront(next_payload_); 48 next_payload_known_ = false; 49 50 return message_buffer; 51 } 52 53 bool MessageDecoder::GetPayloadSize(int* size) { 54 // The header has a size of 4 bytes. 55 const int kHeaderSize = sizeof(int32); 56 57 if (buffer_.total_bytes() < kHeaderSize) 58 return false; 59 60 CompoundBuffer header_buffer; 61 char header[kHeaderSize]; 62 header_buffer.CopyFrom(buffer_, 0, kHeaderSize); 63 header_buffer.CopyTo(header, kHeaderSize); 64 *size = talk_base::GetBE32(header); 65 buffer_.CropFront(kHeaderSize); 66 return true; 67 } 68 69 } // namespace protocol 70 } // namespace remoting 71