| 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
|
|
|