Index: components/pairing/proto_decoder.cc |
diff --git a/components/pairing/proto_decoder.cc b/components/pairing/proto_decoder.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..96b3c24feb7a804f946887fdbc1e8ebcb72f554a |
--- /dev/null |
+++ b/components/pairing/proto_decoder.cc |
@@ -0,0 +1,201 @@ |
+// Copyright 2014 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 "components/pairing/proto_decoder.h" |
+ |
+#include "components/pairing/pairing_api.pb.h" |
+#include "net/base/io_buffer.h" |
+ |
+namespace { |
+enum { |
+ MESSAGE_NONE, |
+ MESSAGE_HOST_STATUS, |
+ MESSAGE_CONFIGURE_HOST, |
+ MESSAGE_PAIR_DEVICES, |
+ MESSAGE_COMPLETE_SETUP, |
+ MESSAGE_ERROR, |
+ NUM_MESSAGES, |
+}; |
+} |
+ |
+namespace pairing_chromeos { |
+ |
+ProtoDecoder::ProtoDecoder(Observer* observer) |
+ : observer_(observer), |
+ next_message_type_(MESSAGE_NONE), |
+ next_message_size_(0) { |
+ DCHECK(observer_); |
+} |
+ |
+ProtoDecoder::~ProtoDecoder() {} |
+ |
+bool ProtoDecoder::DecodeIOBuffer(int size, |
+ ProtoDecoder::IOBufferRefPtr io_buffer) { |
+ // Update the message buffer. |
+ message_buffer_.AddIOBuffer(io_buffer, size); |
+ |
+ // If there is no current message, the next byte is the message type. |
+ if (next_message_type_ == MESSAGE_NONE) { |
+ if (message_buffer_.AvailableBytes() < static_cast<int>(sizeof(uint8_t))) |
+ return true; |
+ |
+ uint8_t message_type = MESSAGE_NONE; |
+ message_buffer_.ReadBytes(reinterpret_cast<char*>(&message_type), |
+ sizeof(message_type)); |
+ |
+ if (message_type == MESSAGE_NONE || message_type >= NUM_MESSAGES) { |
+ LOG(ERROR) << "Unknown message type received: " << message_type; |
+ return false; |
+ } |
+ next_message_type_ = message_type; |
+ } |
+ |
+ // If the message size isn't set, the next two bytes are the message size. |
+ if (next_message_size_ == 0) { |
+ if (message_buffer_.AvailableBytes() < static_cast<int>(sizeof(uint16_t))) |
+ return true; |
+ |
+ // The size is sent in network byte order. |
+ uint8_t high_byte = 0; |
+ message_buffer_.ReadBytes(reinterpret_cast<char*>(&high_byte), |
+ sizeof(high_byte)); |
+ uint8_t low_byte = 0; |
+ message_buffer_.ReadBytes(reinterpret_cast<char*>(&low_byte), |
+ sizeof(low_byte)); |
+ |
+ next_message_size_ = (high_byte << 8) + low_byte; |
+ } |
+ |
+ // If the whole proto buffer is not yet available, return early. |
+ if (message_buffer_.AvailableBytes() < next_message_size_) |
+ return true; |
+ |
+ std::vector<char> buffer(next_message_size_); |
+ message_buffer_.ReadBytes(&buffer[0], next_message_size_); |
+ |
+ switch (next_message_type_) { |
+ case MESSAGE_HOST_STATUS: { |
+ pairing_api::HostStatus message; |
+ message.ParseFromArray(&buffer[0], buffer.size()); |
+ observer_->OnHostStatusMessage(message); |
+ } |
+ break; |
+ case MESSAGE_CONFIGURE_HOST: { |
+ pairing_api::ConfigureHost message; |
+ message.ParseFromArray(&buffer[0], buffer.size()); |
+ observer_->OnConfigureHostMessage(message); |
+ } |
+ break; |
+ case MESSAGE_PAIR_DEVICES: { |
+ pairing_api::PairDevices message; |
+ message.ParseFromArray(&buffer[0], buffer.size()); |
+ observer_->OnPairDevicesMessage(message); |
+ } |
+ break; |
+ case MESSAGE_COMPLETE_SETUP: { |
+ pairing_api::CompleteSetup message; |
+ message.ParseFromArray(&buffer[0], buffer.size()); |
+ observer_->OnCompleteSetupMessage(message); |
+ } |
+ break; |
+ case MESSAGE_ERROR: { |
+ pairing_api::Error message; |
+ message.ParseFromArray(&buffer[0], buffer.size()); |
+ observer_->OnErrorMessage(message); |
+ } |
+ break; |
+ |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ |
+ // Reset the message data. |
+ next_message_type_ = MESSAGE_NONE; |
+ next_message_size_ = 0; |
+ |
+ return true; |
+} |
+ |
+ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendHostStatus( |
+ const pairing_api::HostStatus& message, int* size) { |
+ std::string serialized_proto; |
+ if (!message.SerializeToString(&serialized_proto)) { |
+ NOTREACHED(); |
+ } |
+ |
+ return SendMessage(MESSAGE_HOST_STATUS, serialized_proto, size); |
+} |
+ |
+ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendConfigureHost( |
+ const pairing_api::ConfigureHost& message, int* size) { |
+ std::string serialized_proto; |
+ if (!message.SerializeToString(&serialized_proto)) { |
+ NOTREACHED(); |
+ } |
+ |
+ return SendMessage(MESSAGE_CONFIGURE_HOST, serialized_proto, size); |
+} |
+ |
+ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendPairDevices( |
+ const pairing_api::PairDevices& message, int* size) { |
+ std::string serialized_proto; |
+ if (!message.SerializeToString(&serialized_proto)) { |
+ NOTREACHED(); |
+ } |
+ |
+ return SendMessage(MESSAGE_PAIR_DEVICES, serialized_proto, size); |
+} |
+ |
+ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendCompleteSetup( |
+ const pairing_api::CompleteSetup& message, int* size) { |
+ std::string serialized_proto; |
+ if (!message.SerializeToString(&serialized_proto)) { |
+ NOTREACHED(); |
+ } |
+ |
+ return SendMessage(MESSAGE_COMPLETE_SETUP, serialized_proto, size); |
+} |
+ |
+ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendError( |
+ const pairing_api::Error& message, int* size) { |
+ std::string serialized_proto; |
+ if (!message.SerializeToString(&serialized_proto)) { |
+ NOTREACHED(); |
+ } |
+ |
+ return SendMessage(MESSAGE_ERROR, serialized_proto, size); |
+} |
+ |
+ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendMessage( |
+ uint8_t message_type, |
+ const std::string& message, |
+ int* size) { |
+ uint16_t message_size = message.size(); |
+ |
+ *size = sizeof(message_type) + sizeof(message_size) + message.size(); |
+ IOBufferRefPtr io_buffer(new net::IOBuffer(*size)); |
+ |
+ // Write the message type. |
+ int offset = 0; |
+ memcpy(&io_buffer->data()[offset], &message_type, sizeof(message_type)); |
+ offset += sizeof(message_type); |
+ |
+ // Network byte order. |
+ // Write the high byte of the size. |
+ uint8_t data = (message_size >> 8) & 0xFF; |
+ memcpy(&io_buffer->data()[offset], &data, sizeof(data)); |
+ offset += sizeof(data); |
+ // Write the low byte of the size. |
+ data = message_size & 0xFF; |
+ memcpy(&io_buffer->data()[offset], &data, sizeof(data)); |
+ offset += sizeof(data); |
+ |
+ // Write the actual message. |
+ memcpy(&io_buffer->data()[offset], message.data(), message.size()); |
+ |
+ return io_buffer; |
+} |
+ |
+} // namespace pairing_chromeos |