OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "components/pairing/proto_decoder.h" | |
6 | |
7 #include "components/pairing/message_buffer.h" | |
8 #include "components/pairing/pairing_api.pb.h" | |
9 #include "net/base/io_buffer.h" | |
10 | |
11 namespace { | |
12 enum { | |
13 MESSAGE_NONE, | |
14 MESSAGE_HOST_STATUS, | |
15 MESSAGE_CONFIGURE_HOST, | |
16 MESSAGE_PAIR_DEVICES, | |
17 MESSAGE_COMPLETE_SETUP, | |
18 MESSAGE_ERROR, | |
19 NUM_MESSAGES, | |
20 }; | |
21 } | |
22 | |
23 namespace pairing_chromeos { | |
24 | |
25 ProtoDecoder::ProtoDecoder(Observer* observer) | |
26 : observer_(observer), | |
27 message_buffer_(new MessageBuffer), | |
28 next_message_type_(MESSAGE_NONE), | |
29 next_message_size_(0) {} | |
achuithb
2014/08/11 22:04:31
DCHECK(observer);
Zachary Kuznia
2014/08/11 23:40:29
Done.
| |
30 | |
31 ProtoDecoder::~ProtoDecoder() {} | |
32 | |
33 bool ProtoDecoder::DecodeIOBuffer(int size, | |
34 scoped_refptr<net::IOBuffer> io_buffer) { | |
35 // Update the message buffer. | |
36 message_buffer_->AddIOBuffer(io_buffer, size); | |
37 | |
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() < (int)sizeof(uint8_t)) { | |
achuithb
2014/08/11 22:04:31
Don't need curly braces.
You should use reinterpr
Zachary Kuznia
2014/08/11 23:40:29
I went back and forth on that as well, but this mi
| |
41 return true; | |
42 } | |
43 | |
44 uint8_t message_type = MESSAGE_NONE; | |
achuithb
2014/08/11 22:04:31
Why not char instead of uint8_t?
Zachary Kuznia
2014/08/11 23:40:29
Unsigned types have less undefined behavior with t
| |
45 message_buffer_->ReadBytes(reinterpret_cast<char*>(&message_type), | |
46 sizeof(message_type)); | |
47 | |
48 if (message_type == MESSAGE_NONE || message_type >= NUM_MESSAGES) { | |
49 LOG(ERROR) << "Unknown message type received: " << message_type; | |
50 return false; | |
51 } | |
52 next_message_type_ = message_type; | |
53 } | |
54 | |
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() < (int)sizeof(uint16_t)) { | |
achuithb
2014/08/11 22:04:30
reinterpret cast, no curly braces, consider changi
Zachary Kuznia
2014/08/11 23:40:29
Changed to static_cast, removed braces.
I conside
| |
58 return true; | |
59 } | |
60 | |
61 // The size is sent in network byte order. | |
62 uint8_t high_byte = 0; | |
63 message_buffer_->ReadBytes(reinterpret_cast<char*>(&high_byte), | |
64 sizeof(high_byte)); | |
65 uint8_t low_byte = 0; | |
66 message_buffer_->ReadBytes(reinterpret_cast<char*>(&low_byte), | |
67 sizeof(low_byte)); | |
68 | |
69 next_message_size_ = (high_byte << 8) + low_byte; | |
achuithb
2014/08/11 22:04:31
It feels like hte proto libraries should help us w
Zachary Kuznia
2014/08/11 23:40:29
See comment at line 190
| |
70 } | |
71 | |
72 // If the whole proto buffer is not yet available, return early. | |
73 if (message_buffer_->AvailableBytes() < next_message_size_) { | |
achuithb
2014/08/11 22:04:30
No curly braces.
Zachary Kuznia
2014/08/11 23:40:29
Done.
| |
74 return true; | |
75 } | |
76 | |
77 std::vector<char> buffer(next_message_size_); | |
78 message_buffer_->ReadBytes(&buffer[0], next_message_size_); | |
79 | |
80 switch (next_message_type_) { | |
81 case MESSAGE_HOST_STATUS: { | |
82 pairing_api::HostStatus message; | |
83 message.ParseFromArray(&buffer[0], buffer.size()); | |
84 observer_->OnHostStatusMessage(message); | |
85 } | |
86 break; | |
87 case MESSAGE_CONFIGURE_HOST: { | |
88 pairing_api::ConfigureHost message; | |
89 message.ParseFromArray(&buffer[0], buffer.size()); | |
90 observer_->OnConfigureHostMessage(message); | |
91 } | |
92 break; | |
93 case MESSAGE_PAIR_DEVICES: { | |
94 pairing_api::PairDevices message; | |
95 message.ParseFromArray(&buffer[0], buffer.size()); | |
96 observer_->OnPairDevicesMessage(message); | |
97 } | |
98 break; | |
99 case MESSAGE_COMPLETE_SETUP: { | |
100 pairing_api::CompleteSetup message; | |
101 message.ParseFromArray(&buffer[0], buffer.size()); | |
102 observer_->OnCompleteSetupMessage(message); | |
103 } | |
104 break; | |
105 case MESSAGE_ERROR: { | |
106 pairing_api::Error message; | |
107 message.ParseFromArray(&buffer[0], buffer.size()); | |
108 observer_->OnErrorMessage(message); | |
109 } | |
110 break; | |
111 | |
112 default: | |
113 NOTREACHED(); | |
114 break; | |
115 } | |
116 | |
117 // Reset the message data. | |
118 next_message_type_ = MESSAGE_NONE; | |
119 next_message_size_ = 0; | |
120 | |
121 return true; | |
122 } | |
123 | |
124 scoped_refptr<net::IOBuffer> ProtoDecoder::SendHostStatus( | |
125 const pairing_api::HostStatus& message, int* size) { | |
126 std::string serialized_proto; | |
127 if (!message.SerializeToString(&serialized_proto)) { | |
achuithb
2014/08/11 22:04:31
Shouldn't this be a DCHECK?
Here and everywhere b
Zachary Kuznia
2014/08/11 23:40:29
I avoid putting a function call in any kind of ass
| |
128 NOTREACHED(); | |
129 } | |
130 | |
131 return SendMessage(MESSAGE_HOST_STATUS, serialized_proto, size); | |
132 } | |
133 | |
134 scoped_refptr<net::IOBuffer> ProtoDecoder::SendConfigureHost( | |
135 const pairing_api::ConfigureHost& message, int* size) { | |
136 std::string serialized_proto; | |
137 if (!message.SerializeToString(&serialized_proto)) { | |
138 NOTREACHED(); | |
139 } | |
140 | |
141 return SendMessage(MESSAGE_CONFIGURE_HOST, serialized_proto, size); | |
142 } | |
143 | |
144 scoped_refptr<net::IOBuffer> ProtoDecoder::SendPairDevices( | |
145 const pairing_api::PairDevices& message, int* size) { | |
146 std::string serialized_proto; | |
147 if (!message.SerializeToString(&serialized_proto)) { | |
148 NOTREACHED(); | |
149 } | |
150 | |
151 return SendMessage(MESSAGE_PAIR_DEVICES, serialized_proto, size); | |
152 } | |
153 | |
154 scoped_refptr<net::IOBuffer> ProtoDecoder::SendCompleteSetup( | |
155 const pairing_api::CompleteSetup& message, int* size) { | |
156 std::string serialized_proto; | |
157 if (!message.SerializeToString(&serialized_proto)) { | |
158 NOTREACHED(); | |
159 } | |
160 | |
161 return SendMessage(MESSAGE_COMPLETE_SETUP, serialized_proto, size); | |
162 } | |
163 | |
164 scoped_refptr<net::IOBuffer> ProtoDecoder::SendError( | |
165 const pairing_api::Error& message, int* size) { | |
166 std::string serialized_proto; | |
167 if (!message.SerializeToString(&serialized_proto)) { | |
168 NOTREACHED(); | |
169 } | |
170 | |
171 return SendMessage(MESSAGE_ERROR, serialized_proto, size); | |
172 } | |
173 | |
174 scoped_refptr<net::IOBuffer> ProtoDecoder::SendMessage( | |
175 uint8_t message_type, | |
176 const std::string& message, | |
177 int* size) { | |
achuithb
2014/08/11 22:04:31
Should this be size_t? You're doing an implicit co
Zachary Kuznia
2014/08/11 23:40:29
The BluetoothSocket function deals in IOBuffer and
| |
178 uint16_t message_size = message.size(); | |
179 | |
180 *size = sizeof(message_type) + sizeof(message_size) + message.size(); | |
181 scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(*size)); | |
182 | |
183 // Write the message type. | |
184 int offset = 0; | |
185 memcpy(&io_buffer->data()[offset], &message_type, sizeof(message_type)); | |
186 offset += sizeof(message_type); | |
187 | |
188 // Network byte order. | |
189 // Write the high byte of the size. | |
190 uint8_t data = (message_size >> 8) & 0xFF; | |
achuithb
2014/08/11 22:04:31
Is there no way of getting protobufs to do this wo
Zachary Kuznia
2014/08/11 23:40:29
The other call sites I've seen in Chrome serialize
| |
191 memcpy(&io_buffer->data()[offset], &data, sizeof(data)); | |
192 offset += sizeof(data); | |
193 // Write the low byte of the size. | |
194 data = message_size & 0xFF; | |
195 memcpy(&io_buffer->data()[offset], &data, sizeof(data)); | |
196 offset += sizeof(data); | |
197 | |
198 // Write the actual message. | |
199 memcpy(&io_buffer->data()[offset], message.data(), message.size()); | |
200 | |
201 return io_buffer; | |
202 } | |
203 | |
204 } // namespace pairing_chromeos | |
OLD | NEW |