| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef REMOTING_PROTOCOL_MESSAGES_DECODER_H_ | 5 #ifndef REMOTING_PROTOCOL_MESSAGES_DECODER_H_ |
| 6 #define REMOTING_PROTOCOL_MESSAGES_DECODER_H_ | 6 #define REMOTING_PROTOCOL_MESSAGES_DECODER_H_ |
| 7 | 7 |
| 8 #include <deque> | 8 #include <deque> |
| 9 #include <list> | 9 #include <list> |
| 10 | 10 |
| 11 #include "base/ref_counted.h" | 11 #include "base/ref_counted.h" |
| 12 #include "base/scoped_ptr.h" | 12 #include "base/scoped_ptr.h" |
| 13 #include "net/base/io_buffer.h" | 13 #include "net/base/io_buffer.h" |
| 14 #include "remoting/base/compound_buffer.h" | 14 #include "remoting/base/compound_buffer.h" |
| 15 #include "third_party/protobuf/src/google/protobuf/message_lite.h" | 15 #include "third_party/protobuf/src/google/protobuf/message_lite.h" |
| 16 | 16 |
| 17 namespace remoting { | 17 namespace remoting { |
| 18 namespace protocol { | 18 namespace protocol { |
| 19 | 19 |
| 20 // MessageDecoder uses CompoundBuffer to decode bytes into protocol | 20 // MessageDecoder uses CompoundBuffer to split the data received from |
| 21 // buffer messages. This can be used to decode bytes received from the | 21 // the network into separate messages. Each message is expected to be |
| 22 // network. | 22 // decoded in the stream as follows: |
| 23 // +--------------+--------------+ |
| 24 // | message_size | message_data | |
| 25 // +--------------+--------------+ |
| 23 // | 26 // |
| 24 // It provides ParseMessages() which accepts an IOBuffer. If enough bytes | 27 // Here, message_size is 4-byte integer that represents size of |
| 25 // are collected to produce protocol buffer messages then the bytes will be | 28 // message_data in bytes. message_data - content of the message. |
| 26 // consumed and the generated protocol buffer messages are added to the output | |
| 27 // list. | |
| 28 // | |
| 29 // It retains ownership of IOBuffer given to this object and keeps it alive | |
| 30 // until it is full consumed. | |
| 31 class MessageDecoder { | 29 class MessageDecoder { |
| 32 public: | 30 public: |
| 33 MessageDecoder(); | 31 MessageDecoder(); |
| 34 virtual ~MessageDecoder(); | 32 virtual ~MessageDecoder(); |
| 35 | 33 |
| 36 // Parses the bytes in |data| into a protobuf of type MessageType. The bytes | 34 // Add next chunk of data. MessageDecoder retains |data| until all |
| 37 // in |data| are conceptually a stream of bytes to be parsed into a series of | 35 // its bytes are consumed. |
| 38 // protobufs. Each parsed protouf is appended into the |messages|. All calls | 36 void AddData(scoped_refptr<net::IOBuffer> data, int data_size); |
| 39 // to ParseMessages should use same MessageType for any single instace of | |
| 40 // MessageDecoder. | |
| 41 | 37 |
| 42 // This function retains |data| until all its bytes are consumed. | 38 // Get next message from the stream and puts it in |
| 43 // Ownership of the produced protobufs is passed to the caller via the | 39 // |message_buffer|. Returns false if there are no complete messages |
| 44 // |messages| list. | 40 // yet. |
| 45 template <class MessageType> | 41 bool GetNextMessage(CompoundBuffer* message_buffer); |
| 46 void ParseMessages(scoped_refptr<net::IOBuffer> data, | |
| 47 int data_size, std::list<MessageType*>* messages) { | |
| 48 AddBuffer(data, data_size); | |
| 49 | 42 |
| 50 // Then try to parse the next message until we can't parse anymore. | 43 private: |
| 51 MessageType* message; | |
| 52 while (ParseOneMessage<MessageType>(&message)) { | |
| 53 messages->push_back(message); | |
| 54 } | |
| 55 } | |
| 56 | |
| 57 private: | |
| 58 // Parse one message from |buffer_list_|. Return true if sucessful. | |
| 59 template <class MessageType> | |
| 60 bool ParseOneMessage(MessageType** message) { | |
| 61 CompoundBuffer buffer; | |
| 62 if (!GetNextMessageData(&buffer)) | |
| 63 return false; | |
| 64 | |
| 65 CompoundBufferInputStream stream(&buffer); | |
| 66 *message = new MessageType(); | |
| 67 bool ret = (*message)->ParseFromZeroCopyStream(&stream); | |
| 68 if (!ret) | |
| 69 delete *message; | |
| 70 return ret; | |
| 71 } | |
| 72 | |
| 73 void AddBuffer(scoped_refptr<net::IOBuffer> data, int data_size); | |
| 74 | |
| 75 bool GetNextMessageData(CompoundBuffer* message_buffer); | |
| 76 | |
| 77 // Retrieves the read payload size of the current protocol buffer via |size|. | 44 // Retrieves the read payload size of the current protocol buffer via |size|. |
| 78 // Returns false and leaves |size| unmodified, if we do not have enough data | 45 // Returns false and leaves |size| unmodified, if we do not have enough data |
| 79 // to retrieve the current size. | 46 // to retrieve the current size. |
| 80 bool GetPayloadSize(int* size); | 47 bool GetPayloadSize(int* size); |
| 81 | 48 |
| 82 CompoundBuffer buffer_; | 49 CompoundBuffer buffer_; |
| 83 | 50 |
| 84 // |next_payload_| stores the size of the next payload if known. | 51 // |next_payload_| stores the size of the next payload if known. |
| 85 // |next_payload_known_| is true if the size of the next payload is known. | 52 // |next_payload_known_| is true if the size of the next payload is known. |
| 86 // After one payload is read this is reset to false. | 53 // After one payload is read this is reset to false. |
| 87 int next_payload_; | 54 int next_payload_; |
| 88 bool next_payload_known_; | 55 bool next_payload_known_; |
| 89 }; | 56 }; |
| 90 | 57 |
| 91 } // namespace protocol | 58 } // namespace protocol |
| 92 } // namespace remoting | 59 } // namespace remoting |
| 93 | 60 |
| 94 #endif // REMOTING_PROTOCOL_MESSAGES_DECODER_H_ | 61 #endif // REMOTING_PROTOCOL_MESSAGES_DECODER_H_ |
| OLD | NEW |