Roll src/third_party/WebKit b4168eb:6c137a7 (svn 202006:202008)
[chromium-blink-merge.git] / components / pairing / proto_decoder.cc
blobf8e42a4bd4d14861c16d90b2cac7c7a1059597ed
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 MESSAGE_ADD_NETWORK,
19 NUM_MESSAGES,
23 namespace pairing_chromeos {
25 ProtoDecoder::ProtoDecoder(Observer* observer)
26 : observer_(observer),
27 next_message_type_(MESSAGE_NONE),
28 next_message_size_(0) {
29 DCHECK(observer_);
32 ProtoDecoder::~ProtoDecoder() {}
34 bool ProtoDecoder::DecodeIOBuffer(int size,
35 ProtoDecoder::IOBufferRefPtr io_buffer) {
36 // Update the message buffer.
37 message_buffer_.AddIOBuffer(io_buffer, size);
39 // If there is no current message, the next byte is the message type.
40 if (next_message_type_ == MESSAGE_NONE) {
41 if (message_buffer_.AvailableBytes() < static_cast<int>(sizeof(uint8_t)))
42 return true;
44 uint8_t message_type = MESSAGE_NONE;
45 message_buffer_.ReadBytes(reinterpret_cast<char*>(&message_type),
46 sizeof(message_type));
48 if (message_type == MESSAGE_NONE || message_type >= NUM_MESSAGES) {
49 LOG(ERROR) << "Unknown message type received: " << message_type;
50 return false;
52 next_message_type_ = message_type;
55 // If the message size isn't set, the next two bytes are the message size.
56 if (next_message_size_ == 0) {
57 if (message_buffer_.AvailableBytes() < static_cast<int>(sizeof(uint16_t)))
58 return true;
60 // The size is sent in network byte order.
61 uint8_t high_byte = 0;
62 message_buffer_.ReadBytes(reinterpret_cast<char*>(&high_byte),
63 sizeof(high_byte));
64 uint8_t low_byte = 0;
65 message_buffer_.ReadBytes(reinterpret_cast<char*>(&low_byte),
66 sizeof(low_byte));
68 next_message_size_ = (high_byte << 8) + low_byte;
71 // If the whole proto buffer is not yet available, return early.
72 if (message_buffer_.AvailableBytes() < next_message_size_)
73 return true;
75 std::vector<char> buffer(next_message_size_);
76 message_buffer_.ReadBytes(&buffer[0], next_message_size_);
78 switch (next_message_type_) {
79 case MESSAGE_HOST_STATUS: {
80 pairing_api::HostStatus message;
81 message.ParseFromArray(&buffer[0], buffer.size());
82 observer_->OnHostStatusMessage(message);
84 break;
85 case MESSAGE_CONFIGURE_HOST: {
86 pairing_api::ConfigureHost message;
87 message.ParseFromArray(&buffer[0], buffer.size());
88 observer_->OnConfigureHostMessage(message);
90 break;
91 case MESSAGE_PAIR_DEVICES: {
92 pairing_api::PairDevices message;
93 message.ParseFromArray(&buffer[0], buffer.size());
94 observer_->OnPairDevicesMessage(message);
96 break;
97 case MESSAGE_COMPLETE_SETUP: {
98 pairing_api::CompleteSetup message;
99 message.ParseFromArray(&buffer[0], buffer.size());
100 observer_->OnCompleteSetupMessage(message);
102 break;
103 case MESSAGE_ERROR: {
104 pairing_api::Error message;
105 message.ParseFromArray(&buffer[0], buffer.size());
106 observer_->OnErrorMessage(message);
108 break;
109 case MESSAGE_ADD_NETWORK: {
110 pairing_api::AddNetwork message;
111 message.ParseFromArray(&buffer[0], buffer.size());
112 observer_->OnAddNetworkMessage(message);
114 break;
116 default:
117 LOG(WARNING) << "Skipping unknown message type: " << next_message_type_;
118 break;
121 // Reset the message data.
122 next_message_type_ = MESSAGE_NONE;
123 next_message_size_ = 0;
125 return true;
128 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendHostStatus(
129 const pairing_api::HostStatus& message, int* size) {
130 std::string serialized_proto;
131 if (!message.SerializeToString(&serialized_proto)) {
132 NOTREACHED();
135 return SendMessage(MESSAGE_HOST_STATUS, serialized_proto, size);
138 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendConfigureHost(
139 const pairing_api::ConfigureHost& message, int* size) {
140 std::string serialized_proto;
141 if (!message.SerializeToString(&serialized_proto)) {
142 NOTREACHED();
145 return SendMessage(MESSAGE_CONFIGURE_HOST, serialized_proto, size);
148 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendPairDevices(
149 const pairing_api::PairDevices& message, int* size) {
150 std::string serialized_proto;
151 if (!message.SerializeToString(&serialized_proto)) {
152 NOTREACHED();
155 return SendMessage(MESSAGE_PAIR_DEVICES, serialized_proto, size);
158 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendCompleteSetup(
159 const pairing_api::CompleteSetup& message, int* size) {
160 std::string serialized_proto;
161 if (!message.SerializeToString(&serialized_proto)) {
162 NOTREACHED();
165 return SendMessage(MESSAGE_COMPLETE_SETUP, serialized_proto, size);
168 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendError(
169 const pairing_api::Error& message, int* size) {
170 std::string serialized_proto;
171 if (!message.SerializeToString(&serialized_proto)) {
172 NOTREACHED();
175 return SendMessage(MESSAGE_ERROR, serialized_proto, size);
178 ProtoDecoder::IOBufferRefPtr ProtoDecoder::SendMessage(
179 uint8_t message_type,
180 const std::string& message,
181 int* size) {
182 uint16_t message_size = message.size();
184 *size = sizeof(message_type) + sizeof(message_size) + message.size();
185 IOBufferRefPtr io_buffer(new net::IOBuffer(*size));
187 // Write the message type.
188 int offset = 0;
189 memcpy(&io_buffer->data()[offset], &message_type, sizeof(message_type));
190 offset += sizeof(message_type);
192 // Network byte order.
193 // Write the high byte of the size.
194 uint8_t data = (message_size >> 8) & 0xFF;
195 memcpy(&io_buffer->data()[offset], &data, sizeof(data));
196 offset += sizeof(data);
197 // Write the low byte of the size.
198 data = message_size & 0xFF;
199 memcpy(&io_buffer->data()[offset], &data, sizeof(data));
200 offset += sizeof(data);
202 // Write the actual message.
203 memcpy(&io_buffer->data()[offset], message.data(), message.size());
205 return io_buffer;
208 } // namespace pairing_chromeos