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
,
22 namespace pairing_chromeos
{
24 ProtoDecoder::ProtoDecoder(Observer
* observer
)
25 : observer_(observer
),
26 next_message_type_(MESSAGE_NONE
),
27 next_message_size_(0) {
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)))
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
;
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)))
59 // The size is sent in network byte order.
60 uint8_t high_byte
= 0;
61 message_buffer_
.ReadBytes(reinterpret_cast<char*>(&high_byte
),
64 message_buffer_
.ReadBytes(reinterpret_cast<char*>(&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_
)
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
);
84 case MESSAGE_CONFIGURE_HOST
: {
85 pairing_api::ConfigureHost message
;
86 message
.ParseFromArray(&buffer
[0], buffer
.size());
87 observer_
->OnConfigureHostMessage(message
);
90 case MESSAGE_PAIR_DEVICES
: {
91 pairing_api::PairDevices message
;
92 message
.ParseFromArray(&buffer
[0], buffer
.size());
93 observer_
->OnPairDevicesMessage(message
);
96 case MESSAGE_COMPLETE_SETUP
: {
97 pairing_api::CompleteSetup message
;
98 message
.ParseFromArray(&buffer
[0], buffer
.size());
99 observer_
->OnCompleteSetupMessage(message
);
102 case MESSAGE_ERROR
: {
103 pairing_api::Error message
;
104 message
.ParseFromArray(&buffer
[0], buffer
.size());
105 observer_
->OnErrorMessage(message
);
114 // Reset the message data.
115 next_message_type_
= MESSAGE_NONE
;
116 next_message_size_
= 0;
121 ProtoDecoder::IOBufferRefPtr
ProtoDecoder::SendHostStatus(
122 const pairing_api::HostStatus
& message
, int* size
) {
123 std::string serialized_proto
;
124 if (!message
.SerializeToString(&serialized_proto
)) {
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
)) {
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
)) {
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
)) {
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
)) {
168 return SendMessage(MESSAGE_ERROR
, serialized_proto
, size
);
171 ProtoDecoder::IOBufferRefPtr
ProtoDecoder::SendMessage(
172 uint8_t message_type
,
173 const std::string
& message
,
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.
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());
201 } // namespace pairing_chromeos