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

Side by Side Diff: remoting/base/protocol_decoder.cc

Issue 2690003: Copy the (early prototype of) remoting in Chrome into the public tree.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 6 months 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/base/protocol_decoder.h ('k') | remoting/base/protocol_decoder_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
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/base/protocol_decoder.h"
6
7 #include "remoting/base/multiple_array_input_stream.h"
8 #include "talk/base/byteorder.h"
9
10 namespace remoting {
11
12 ProtocolDecoder::ProtocolDecoder()
13 : last_read_position_(0),
14 available_bytes_(0),
15 next_payload_(0),
16 next_payload_known_(false) {
17 }
18
19 void ProtocolDecoder::ParseClientMessages(scoped_refptr<media::DataBuffer> data,
20 ClientMessageList* messages) {
21 ParseMessages<chromotocol_pb::ClientMessage>(data, messages);
22 }
23
24 void ProtocolDecoder::ParseHostMessages(scoped_refptr<media::DataBuffer> data,
25 HostMessageList* messages) {
26 ParseMessages<chromotocol_pb::HostMessage>(data, messages);
27 }
28
29 template <typename T>
30 void ProtocolDecoder::ParseMessages(scoped_refptr<media::DataBuffer> data,
31 std::vector<T*>* messages) {
32 // If this is the first data in the processing queue, then set the
33 // last read position to 0.
34 if (data_list_.empty())
35 last_read_position_ = 0;
36
37 // First enqueue the data received.
38 data_list_.push_back(data);
39 available_bytes_ += data->GetDataSize();
40
41 // Then try to parse one message until we can't parse anymore.
42 T* message;
43 while (ParseOneMessage<T>(&message)) {
44 messages->push_back(message);
45 }
46 }
47
48 template <typename T>
49 bool ProtocolDecoder::ParseOneMessage(T** message) {
50 // Determine the payload size. If we already know it, then skip this
51 // part.
52 // We have the value set to -1 for checking later.
53 int next_payload = -1;
54 if (!next_payload_known_ && GetPayloadSize(&next_payload)) {
55 DCHECK_NE(-1, next_payload);
56 next_payload_ = next_payload;
57 next_payload_known_ = true;
58 }
59
60 // If the next payload size is still not known or we don't have enough
61 // data for parsing then exit.
62 if (!next_payload_known_ || available_bytes_ < next_payload_)
63 return false;
64 next_payload_known_ = false;
65
66 // Extract data from |data_list_| used to form a full protocol buffer.
67 DataList buffers;
68 std::deque<const uint8*> buffer_pointers;
69 std::deque<int> buffer_sizes;
70 while (next_payload_ > 0 && !data_list_.empty()) {
71 scoped_refptr<media::DataBuffer> buffer = data_list_.front();
72 int read_bytes = std::min(
73 static_cast<int>(buffer->GetDataSize()) - last_read_position_,
74 next_payload_);
75
76 buffers.push_back(buffer);
77 buffer_pointers.push_back(buffer->GetData() + last_read_position_);
78 buffer_sizes.push_back(read_bytes);
79
80 // Adjust counters.
81 last_read_position_ += read_bytes;
82 next_payload_ -= read_bytes;
83 available_bytes_ -= read_bytes;
84
85 // If the front buffer is fully read, remove it from the queue.
86 if (buffer->GetDataSize() == last_read_position_) {
87 data_list_.pop_front();
88 last_read_position_ = 0;
89 }
90 }
91 DCHECK_EQ(0, next_payload_);
92 DCHECK_EQ(buffers.size(), buffer_pointers.size());
93 DCHECK_EQ(buffers.size(), buffer_sizes.size());
94
95 // Create a MultipleArrayInputStream for parsing.
96 MultipleArrayInputStream stream(buffers.size());
97 for (size_t i = 0; i < buffers.size(); ++i) {
98 stream.SetBuffer(i, buffer_pointers[i], buffer_sizes[i]);
99 }
100
101 // And finally it is parsing.
102 *message = new T();
103 bool ret = (*message)->ParseFromZeroCopyStream(&stream);
104 if (!ret)
105 delete *message;
106 return ret;
107 }
108
109 bool ProtocolDecoder::GetPayloadSize(int* size) {
110 // The header has a size of 4 bytes.
111 const int kHeaderSize = sizeof(int32);
112
113 if (available_bytes_ < kHeaderSize)
114 return false;
115
116 std::string header;
117 while (header.length() < kHeaderSize && !data_list_.empty()) {
118 scoped_refptr<media::DataBuffer> buffer = data_list_.front();
119
120 // Find out how many bytes we need and how many bytes are available in this
121 // buffer.
122 int needed_bytes = kHeaderSize - header.length();
123 int available_bytes = buffer->GetDataSize() - last_read_position_;
124
125 // Then append the required bytes into the header and advance the last
126 // read position.
127 int read_bytes = std::min(needed_bytes, available_bytes);
128 header.append(
129 reinterpret_cast<const char*>(buffer->GetData()) + last_read_position_,
130 read_bytes);
131 last_read_position_ += read_bytes;
132 available_bytes_ -= read_bytes;
133
134 // If the buffer is depleted then remove it from the queue.
135 if (last_read_position_ == buffer->GetDataSize()) {
136 last_read_position_ = 0;
137 data_list_.pop_front();
138 }
139 }
140
141 if (header.length() == kHeaderSize) {
142 *size = talk_base::GetBE32(header.c_str());
143 return true;
144 }
145 NOTREACHED() << "Unable to extract payload size";
146 return false;
147 }
148
149 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/base/protocol_decoder.h ('k') | remoting/base/protocol_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698