16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
26e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
36e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// found in the LICENSE file.
46e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/pairing/proto_decoder.h"
66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/pairing/pairing_api.pb.h"
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/base/io_buffer.h"
96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace {
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)enum {
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  MESSAGE_NONE,
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  MESSAGE_HOST_STATUS,
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  MESSAGE_CONFIGURE_HOST,
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  MESSAGE_PAIR_DEVICES,
166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  MESSAGE_COMPLETE_SETUP,
176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  MESSAGE_ERROR,
186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  NUM_MESSAGES,
196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace pairing_chromeos {
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ProtoDecoder::ProtoDecoder(Observer* observer)
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : observer_(observer),
266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      next_message_type_(MESSAGE_NONE),
276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      next_message_size_(0) {
286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(observer_);
296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ProtoDecoder::~ProtoDecoder() {}
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool ProtoDecoder::DecodeIOBuffer(int size,
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  ProtoDecoder::IOBufferRefPtr io_buffer) {
356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Update the message buffer.
366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  message_buffer_.AddIOBuffer(io_buffer, size);
376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // If there is no current message, the next byte is the message type.
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (next_message_type_ == MESSAGE_NONE) {
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (message_buffer_.AvailableBytes() < static_cast<int>(sizeof(uint8_t)))
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return true;
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    uint8_t message_type = MESSAGE_NONE;
446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    message_buffer_.ReadBytes(reinterpret_cast<char*>(&message_type),
456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                               sizeof(message_type));
466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (message_type == MESSAGE_NONE || message_type >= NUM_MESSAGES) {
486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      LOG(ERROR) << "Unknown message type received: " << message_type;
496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return false;
506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    next_message_type_ = message_type;
526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // If the message size isn't set, the next two bytes are the message size.
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (next_message_size_ == 0) {
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (message_buffer_.AvailableBytes() < static_cast<int>(sizeof(uint16_t)))
576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return true;
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // The size is sent in network byte order.
606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    uint8_t high_byte = 0;
616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    message_buffer_.ReadBytes(reinterpret_cast<char*>(&high_byte),
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                               sizeof(high_byte));
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    uint8_t low_byte = 0;
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    message_buffer_.ReadBytes(reinterpret_cast<char*>(&low_byte),
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                               sizeof(low_byte));
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    next_message_size_ = (high_byte << 8) + low_byte;
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // If the whole proto buffer is not yet available, return early.
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (message_buffer_.AvailableBytes() < next_message_size_)
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return true;
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::vector<char> buffer(next_message_size_);
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  message_buffer_.ReadBytes(&buffer[0], next_message_size_);
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  switch (next_message_type_) {
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case MESSAGE_HOST_STATUS: {
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        pairing_api::HostStatus message;
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        message.ParseFromArray(&buffer[0], buffer.size());
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        observer_->OnHostStatusMessage(message);
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case MESSAGE_CONFIGURE_HOST: {
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        pairing_api::ConfigureHost message;
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        message.ParseFromArray(&buffer[0], buffer.size());
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        observer_->OnConfigureHostMessage(message);
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case MESSAGE_PAIR_DEVICES: {
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        pairing_api::PairDevices message;
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        message.ParseFromArray(&buffer[0], buffer.size());
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        observer_->OnPairDevicesMessage(message);
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case MESSAGE_COMPLETE_SETUP: {
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        pairing_api::CompleteSetup message;
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        message.ParseFromArray(&buffer[0], buffer.size());
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        observer_->OnCompleteSetupMessage(message);
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case MESSAGE_ERROR: {
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        pairing_api::Error message;
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        message.ParseFromArray(&buffer[0], buffer.size());
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        observer_->OnErrorMessage(message);
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    default:
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      NOTREACHED();
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Reset the message data.
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  next_message_type_ = MESSAGE_NONE;
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  next_message_size_ = 0;
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return true;
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendHostStatus(
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const pairing_api::HostStatus& message, int* size) {
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string serialized_proto;
1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!message.SerializeToString(&serialized_proto)) {
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    NOTREACHED();
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return SendMessage(MESSAGE_HOST_STATUS, serialized_proto, size);
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendConfigureHost(
1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const pairing_api::ConfigureHost& message, int* size) {
1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string serialized_proto;
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!message.SerializeToString(&serialized_proto)) {
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    NOTREACHED();
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return SendMessage(MESSAGE_CONFIGURE_HOST, serialized_proto, size);
1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendPairDevices(
1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const pairing_api::PairDevices& message, int* size) {
1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string serialized_proto;
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!message.SerializeToString(&serialized_proto)) {
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    NOTREACHED();
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return SendMessage(MESSAGE_PAIR_DEVICES, serialized_proto, size);
1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendCompleteSetup(
1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const pairing_api::CompleteSetup& message, int* size) {
1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string serialized_proto;
1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!message.SerializeToString(&serialized_proto)) {
1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    NOTREACHED();
1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return SendMessage(MESSAGE_COMPLETE_SETUP, serialized_proto, size);
1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendError(
1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const pairing_api::Error& message, int* size) {
1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string serialized_proto;
1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!message.SerializeToString(&serialized_proto)) {
1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    NOTREACHED();
1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return SendMessage(MESSAGE_ERROR, serialized_proto, size);
1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendMessage(
1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    uint8_t message_type,
1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const std::string& message,
1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int* size) {
1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  uint16_t message_size = message.size();
1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  *size = sizeof(message_type) + sizeof(message_size) + message.size();
1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  IOBufferRefPtr io_buffer(new net::IOBuffer(*size));
1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Write the message type.
1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int offset = 0;
1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  memcpy(&io_buffer->data()[offset], &message_type, sizeof(message_type));
1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  offset += sizeof(message_type);
1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Network byte order.
1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Write the high byte of the size.
1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  uint8_t data = (message_size >> 8) & 0xFF;
1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  memcpy(&io_buffer->data()[offset], &data, sizeof(data));
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  offset += sizeof(data);
1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Write the low byte of the size.
1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  data = message_size & 0xFF;
1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  memcpy(&io_buffer->data()[offset], &data, sizeof(data));
1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  offset += sizeof(data);
1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Write the actual message.
1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  memcpy(&io_buffer->data()[offset], message.data(), message.size());
1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return io_buffer;
1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace pairing_chromeos
202