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 |