Switch from a DataPipe per DecoderBuffer to a single one.
[chromium-blink-merge.git] / components / pairing / proto_decoder.cc
blob96b3c24feb7a804f946887fdbc1e8ebcb72f554a
1 // Copyright 2014 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.
5 #include "components/pairing/proto_decoder.h"
7 #include "components/pairing/pairing_api.pb.h"
8 #include "net/base/io_buffer.h"
10 namespace {
11 enum {
12 MESSAGE_NONE,
13 MESSAGE_HOST_STATUS,
14 MESSAGE_CONFIGURE_HOST,
15 MESSAGE_PAIR_DEVICES,
16 MESSAGE_COMPLETE_SETUP,
17 MESSAGE_ERROR,
18 NUM_MESSAGES,
22 namespace pairing_chromeos {
24 ProtoDecoder::ProtoDecoder(Observer* observer)
25 : observer_(observer),
26 next_message_type_(MESSAGE_NONE),
27 next_message_size_(0) {
28 DCHECK(observer_);
31 ProtoDecoder::~ProtoDecoder() {}
33 bool ProtoDecoder::DecodeIOBuffer(int size,
34 ProtoDecoder::IOBufferRefPtr io_buffer) {
35 // Update the message buffer.
36 message_buffer_.AddIOBuffer(io_buffer, size);
38 // If there is no current message, the next byte is the message type.
39 if (next_message_type_ == MESSAGE_NONE) {
40 if (message_buffer_.AvailableBytes() < static_cast<int>(sizeof(uint8_t)))
41 return true;
43 uint8_t message_type = MESSAGE_NONE;
44 message_buffer_.ReadBytes(reinterpret_cast<char*>(&message_type),
45 sizeof(message_type));
47 if (message_type == MESSAGE_NONE || message_type >= NUM_MESSAGES) {
48 LOG(ERROR) << "Unknown message type received: " << message_type;
49 return false;
51 next_message_type_ = message_type;
54 // If the message size isn't set, the next two bytes are the message size.
55 if (next_message_size_ == 0) {
56 if (message_buffer_.AvailableBytes() < static_cast<int>(sizeof(uint16_t)))
57 return true;
59 // The size is sent in network byte order.
60 uint8_t high_byte = 0;
61 message_buffer_.ReadBytes(reinterpret_cast<char*>(&high_byte),
62 sizeof(high_byte));
63 uint8_t low_byte = 0;
64 message_buffer_.ReadBytes(reinterpret_cast<char*>(&low_byte),
65 sizeof(low_byte));
67 next_message_size_ = (high_byte << 8) + low_byte;
70 // If the whole proto buffer is not yet available, return early.
71 if (message_buffer_.AvailableBytes() < next_message_size_)
72 return true;
74 std::vector<char> buffer(next_message_size_);
75 message_buffer_.ReadBytes(&buffer[0], next_message_size_);
77 switch (next_message_type_) {
78 case MESSAGE_HOST_STATUS: {
79 pairing_api::HostStatus message;
80 message.ParseFromArray(&buffer[0], buffer.size());
81 observer_->OnHostStatusMessage(message);
83 break;
84 case MESSAGE_CONFIGURE_HOST: {
85 pairing_api::ConfigureHost message;
86 message.ParseFromArray(&buffer[0], buffer.size());
87 observer_->OnConfigureHostMessage(message);
89 break;
90 case MESSAGE_PAIR_DEVICES: {
91 pairing_api::PairDevices message;
92 message.ParseFromArray(&buffer[0], buffer.size());
93 observer_->OnPairDevicesMessage(message);
95 break;
96 case MESSAGE_COMPLETE_SETUP: {
97 pairing_api::CompleteSetup message;
98 message.ParseFromArray(&buffer[0], buffer.size());
99 observer_->OnCompleteSetupMessage(message);
101 break;
102 case MESSAGE_ERROR: {
103 pairing_api::Error message;
104 message.ParseFromArray(&buffer[0], buffer.size());
105 observer_->OnErrorMessage(message);
107 break;
109 default:
110 NOTREACHED();
111 break;
114 // Reset the message data.
115 next_message_type_ = MESSAGE_NONE;
116 next_message_size_ = 0;
118 return true;
121 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendHostStatus(
122 const pairing_api::HostStatus& message, int* size) {
123 std::string serialized_proto;
124 if (!message.SerializeToString(&serialized_proto)) {
125 NOTREACHED();
128 return SendMessage(MESSAGE_HOST_STATUS, serialized_proto, size);
131 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendConfigureHost(
132 const pairing_api::ConfigureHost& message, int* size) {
133 std::string serialized_proto;
134 if (!message.SerializeToString(&serialized_proto)) {
135 NOTREACHED();
138 return SendMessage(MESSAGE_CONFIGURE_HOST, serialized_proto, size);
141 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendPairDevices(
142 const pairing_api::PairDevices& message, int* size) {
143 std::string serialized_proto;
144 if (!message.SerializeToString(&serialized_proto)) {
145 NOTREACHED();
148 return SendMessage(MESSAGE_PAIR_DEVICES, serialized_proto, size);
151 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendCompleteSetup(
152 const pairing_api::CompleteSetup& message, int* size) {
153 std::string serialized_proto;
154 if (!message.SerializeToString(&serialized_proto)) {
155 NOTREACHED();
158 return SendMessage(MESSAGE_COMPLETE_SETUP, serialized_proto, size);
161 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendError(
162 const pairing_api::Error& message, int* size) {
163 std::string serialized_proto;
164 if (!message.SerializeToString(&serialized_proto)) {
165 NOTREACHED();
168 return SendMessage(MESSAGE_ERROR, serialized_proto, size);
171 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendMessage(
172 uint8_t message_type,
173 const std::string& message,
174 int* size) {
175 uint16_t message_size = message.size();
177 *size = sizeof(message_type) + sizeof(message_size) + message.size();
178 IOBufferRefPtr io_buffer(new net::IOBuffer(*size));
180 // Write the message type.
181 int offset = 0;
182 memcpy(&io_buffer->data()[offset], &message_type, sizeof(message_type));
183 offset += sizeof(message_type);
185 // Network byte order.
186 // Write the high byte of the size.
187 uint8_t data = (message_size >> 8) & 0xFF;
188 memcpy(&io_buffer->data()[offset], &data, sizeof(data));
189 offset += sizeof(data);
190 // Write the low byte of the size.
191 data = message_size & 0xFF;
192 memcpy(&io_buffer->data()[offset], &data, sizeof(data));
193 offset += sizeof(data);
195 // Write the actual message.
196 memcpy(&io_buffer->data()[offset], message.data(), message.size());
198 return io_buffer;
201 } // namespace pairing_chromeos