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

Unified Diff: remoting/protocol/message_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, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/protocol/message_decoder.h ('k') | remoting/protocol/message_decoder_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/protocol/message_decoder.cc
diff --git a/remoting/protocol/message_decoder.cc b/remoting/protocol/message_decoder.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4a31ee1d48e36a83f76c8f5b6c7e36d69c5d8057
--- /dev/null
+++ b/remoting/protocol/message_decoder.cc
@@ -0,0 +1,112 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/protocol/message_decoder.h"
+
+#include "base/logging.h"
+#include "net/base/io_buffer.h"
+#include "remoting/base/multiple_array_input_stream.h"
+#include "remoting/proto/internal.pb.h"
+#include "talk/base/byteorder.h"
+
+namespace remoting {
+
+MessageDecoder::MessageDecoder()
+ : available_bytes_(0),
+ next_payload_(0),
+ next_payload_known_(false) {
+}
+
+MessageDecoder::~MessageDecoder() {}
+
+void MessageDecoder::AddBuffer(scoped_refptr<net::IOBuffer> data,
+ int data_size) {
+ buffer_list_.push_back(new net::DrainableIOBuffer(data, data_size));
+ available_bytes_ += data_size;
+}
+
+MultipleArrayInputStream* MessageDecoder::CreateInputStreamFromData() {
+ // Determine the payload size. If we already know it then skip this part.
+ // We may not have enough data to determine the payload size so use a
+ // utility function to find out.
+ int next_payload = -1;
+ if (!next_payload_known_ && GetPayloadSize(&next_payload)) {
+ DCHECK_NE(-1, next_payload);
+ next_payload_ = next_payload;
+ next_payload_known_ = true;
+ }
+
+ // If the next payload size is still not known or we don't have enough
+ // data for parsing then exit.
+ if (!next_payload_known_ || available_bytes_ < next_payload_)
+ return NULL;
+ next_payload_known_ = false;
+
+ // The following loop gather buffers in |buffer_list_| that sum up to
+ // |next_payload_| bytes. These buffers are added to |stream|.
+
+ // Create a MultipleArrayInputStream for parsing.
+ // TODO(hclam): Avoid creating this object everytime.
+ MultipleArrayInputStream* stream = new MultipleArrayInputStream();
+ while (next_payload_ > 0 && !buffer_list_.empty()) {
+ scoped_refptr<net::DrainableIOBuffer> buffer = buffer_list_.front();
+ int read_bytes = std::min(buffer->BytesRemaining(), next_payload_);
+
+ // This call creates a new instance of DrainableIOBuffer internally.
+ // This will reference the same base pointer but maintain it's own
+ // version of data pointer.
+ stream->AddBuffer(buffer, read_bytes);
+
+ // Adjust counters.
+ buffer->DidConsume(read_bytes);
+ next_payload_ -= read_bytes;
+ available_bytes_ -= read_bytes;
+
+ // If the front buffer is fully read then remove it from the queue.
+ if (!buffer->BytesRemaining())
+ buffer_list_.pop_front();
+ }
+ DCHECK_EQ(0, next_payload_);
+ DCHECK_LE(0, available_bytes_);
+ return stream;
+}
+
+static int GetHeaderSize(const std::string& header) {
+ return header.length();
+}
+
+bool MessageDecoder::GetPayloadSize(int* size) {
+ // The header has a size of 4 bytes.
+ const int kHeaderSize = sizeof(int32);
+
+ if (available_bytes_ < kHeaderSize)
+ return false;
+
+ std::string header;
+ while (GetHeaderSize(header) < kHeaderSize && !buffer_list_.empty()) {
+ scoped_refptr<net::DrainableIOBuffer> buffer = buffer_list_.front();
+
+ // Find out how many bytes we need and how many bytes are available in this
+ // buffer.
+ int needed_bytes = kHeaderSize - GetHeaderSize(header);
+ int available_bytes = buffer->BytesRemaining();
+
+ // Then append the required bytes into the header and advance the last
+ // read position.
+ int read_bytes = std::min(needed_bytes, available_bytes);
+ header.append(buffer->data(), read_bytes);
+ buffer->DidConsume(read_bytes);
+ available_bytes_ -= read_bytes;
+
+ // If the buffer is depleted then remove it from the queue.
+ if (!buffer->BytesRemaining()) {
+ buffer_list_.pop_front();
+ }
+ }
+
+ *size = talk_base::GetBE32(header.c_str());
+ return true;
+}
+
+} // namespace remoting
« no previous file with comments | « remoting/protocol/message_decoder.h ('k') | remoting/protocol/message_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698