Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: remoting/protocol/messages_decoder.cc

Issue 4017002: HostMessageDispatcher to parse control messages (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merged again Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/protocol/messages_decoder.h ('k') | remoting/protocol/socket_reader_base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "remoting/protocol/messages_decoder.h"
6
7 #include "base/logging.h"
8 #include "net/base/io_buffer.h"
9 #include "remoting/base/multiple_array_input_stream.h"
10 #include "talk/base/byteorder.h"
11
12 namespace remoting {
13
14 MessagesDecoder::MessagesDecoder()
15 : last_read_position_(0),
16 available_bytes_(0),
17 next_payload_(0),
18 next_payload_known_(false) {
19 }
20
21 MessagesDecoder::~MessagesDecoder() {}
22
23 void MessagesDecoder::ParseClientMessages(scoped_refptr<net::IOBuffer> data,
24 int data_size,
25 ClientMessageList* messages) {
26 ParseMessages<ChromotingClientMessage>(data, data_size, messages);
27 }
28
29 void MessagesDecoder::ParseHostMessages(scoped_refptr<net::IOBuffer> data,
30 int data_size,
31 HostMessageList* messages) {
32 ParseMessages<ChromotingHostMessage>(data, data_size, messages);
33 }
34
35 MessagesDecoder::DataChunk::DataChunk(net::IOBuffer* data, size_t data_size)
36 : data(data),
37 data_size(data_size) {
38 }
39
40 MessagesDecoder::DataChunk::~DataChunk() {}
41
42 template <typename T>
43 void MessagesDecoder::ParseMessages(scoped_refptr<net::IOBuffer> data,
44 int data_size,
45 std::list<T*>* messages) {
46 // If this is the first data in the processing queue, then set the
47 // last read position to 0.
48 if (data_list_.empty())
49 last_read_position_ = 0;
50
51 // First enqueue the data received.
52 data_list_.push_back(DataChunk(data, data_size));
53 available_bytes_ += data_size;
54
55 // Then try to parse one message until we can't parse anymore.
56 T* message;
57 while (ParseOneMessage<T>(&message)) {
58 messages->push_back(message);
59 }
60 }
61
62 template <typename T>
63 bool MessagesDecoder::ParseOneMessage(T** message) {
64 // Determine the payload size. If we already know it, then skip this
65 // part.
66 // We have the value set to -1 for checking later.
67 int next_payload = -1;
68 if (!next_payload_known_ && GetPayloadSize(&next_payload)) {
69 DCHECK_NE(-1, next_payload);
70 next_payload_ = next_payload;
71 next_payload_known_ = true;
72 }
73
74 // If the next payload size is still not known or we don't have enough
75 // data for parsing then exit.
76 if (!next_payload_known_ || available_bytes_ < next_payload_)
77 return false;
78 next_payload_known_ = false;
79
80 // Create a MultipleArrayInputStream for parsing.
81 MultipleArrayInputStream stream;
82 std::vector<scoped_refptr<net::IOBuffer> > buffers;
83 while (next_payload_ > 0 && !data_list_.empty()) {
84 DataChunk* buffer = &(data_list_.front());
85 size_t read_bytes = std::min(buffer->data_size - last_read_position_,
86 next_payload_);
87
88 buffers.push_back(buffer->data);
89 stream.AddBuffer(buffer->data->data() + last_read_position_, read_bytes);
90
91 // Adjust counters.
92 last_read_position_ += read_bytes;
93 next_payload_ -= read_bytes;
94 available_bytes_ -= read_bytes;
95
96 // If the front buffer is fully read, remove it from the queue.
97 if (buffer->data_size == last_read_position_) {
98 data_list_.pop_front();
99 last_read_position_ = 0;
100 }
101 }
102 DCHECK_EQ(0UL, next_payload_);
103
104 // And finally it is parsing.
105 *message = new T();
106 bool ret = (*message)->ParseFromZeroCopyStream(&stream);
107 if (!ret) {
108 LOG(ERROR) << "Received invalid message.";
109 delete *message;
110 }
111 return ret;
112 }
113
114 bool MessagesDecoder::GetPayloadSize(int* size) {
115 // The header has a size of 4 bytes.
116 const size_t kHeaderSize = sizeof(int32);
117
118 if (available_bytes_ < kHeaderSize)
119 return false;
120
121 std::string header;
122 while (header.length() < kHeaderSize && !data_list_.empty()) {
123 DataChunk* buffer = &(data_list_.front());
124
125 // Find out how many bytes we need and how many bytes are available in this
126 // buffer.
127 int needed_bytes = kHeaderSize - header.length();
128 int available_bytes = buffer->data_size - last_read_position_;
129
130 // Then append the required bytes into the header and advance the last
131 // read position.
132 int read_bytes = std::min(needed_bytes, available_bytes);
133 header.append(
134 reinterpret_cast<char*>(buffer->data->data()) + last_read_position_,
135 read_bytes);
136 last_read_position_ += read_bytes;
137 available_bytes_ -= read_bytes;
138
139 // If the buffer is depleted then remove it from the queue.
140 if (last_read_position_ == buffer->data_size) {
141 last_read_position_ = 0;
142 data_list_.pop_front();
143 }
144 }
145
146 if (header.length() == kHeaderSize) {
147 *size = talk_base::GetBE32(header.c_str());
148 return true;
149 }
150 NOTREACHED() << "Unable to extract payload size";
151 return false;
152 }
153
154 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/protocol/messages_decoder.h ('k') | remoting/protocol/socket_reader_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698