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"
14 MESSAGE_CONFIGURE_HOST
,
16 MESSAGE_COMPLETE_SETUP
,
23 namespace pairing_chromeos
{
25 ProtoDecoder::ProtoDecoder(Observer
* observer
)
26 : observer_(observer
),
27 next_message_type_(MESSAGE_NONE
),
28 next_message_size_(0) {
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)))
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
;
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)))
60 // The size is sent in network byte order.
61 uint8_t high_byte
= 0;
62 message_buffer_
.ReadBytes(reinterpret_cast<char*>(&high_byte
),
65 message_buffer_
.ReadBytes(reinterpret_cast<char*>(&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_
)
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
);
85 case MESSAGE_CONFIGURE_HOST
: {
86 pairing_api::ConfigureHost message
;
87 message
.ParseFromArray(&buffer
[0], buffer
.size());
88 observer_
->OnConfigureHostMessage(message
);
91 case MESSAGE_PAIR_DEVICES
: {
92 pairing_api::PairDevices message
;
93 message
.ParseFromArray(&buffer
[0], buffer
.size());
94 observer_
->OnPairDevicesMessage(message
);
97 case MESSAGE_COMPLETE_SETUP
: {
98 pairing_api::CompleteSetup message
;
99 message
.ParseFromArray(&buffer
[0], buffer
.size());
100 observer_
->OnCompleteSetupMessage(message
);
103 case MESSAGE_ERROR
: {
104 pairing_api::Error message
;
105 message
.ParseFromArray(&buffer
[0], buffer
.size());
106 observer_
->OnErrorMessage(message
);
109 case MESSAGE_ADD_NETWORK
: {
110 pairing_api::AddNetwork message
;
111 message
.ParseFromArray(&buffer
[0], buffer
.size());
112 observer_
->OnAddNetworkMessage(message
);
117 LOG(WARNING
) << "Skipping unknown message type: " << next_message_type_
;
121 // Reset the message data.
122 next_message_type_
= MESSAGE_NONE
;
123 next_message_size_
= 0;
128 ProtoDecoder::IOBufferRefPtr
ProtoDecoder::SendHostStatus(
129 const pairing_api::HostStatus
& message
, int* size
) {
130 std::string serialized_proto
;
131 if (!message
.SerializeToString(&serialized_proto
)) {
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
)) {
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
)) {
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
)) {
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
)) {
175 return SendMessage(MESSAGE_ERROR
, serialized_proto
, size
);
178 ProtoDecoder::IOBufferRefPtr
ProtoDecoder::SendMessage(
179 uint8_t message_type
,
180 const std::string
& message
,
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.
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());
208 } // namespace pairing_chromeos