1 // Copyright 2012 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // A PoloWireAdapter implementation that uses protocol buffers for transmitting
16 // messages.
17
18 #include "polo/wire/protobuf/protobufwireadapter.h"
19
20 #include <glog/logging.h>
21 #include <algorithm>
22 #include <set>
23 #include <string>
24 #include <vector>
25 #include "polo/util/poloutil.h"
26
27 namespace polo {
28 namespace wire {
29 namespace protobuf {
30
ProtobufWireAdapter(PoloWireInterface * interface)31 ProtobufWireAdapter::ProtobufWireAdapter(PoloWireInterface* interface)
32 : PoloWireAdapter(interface), read_state_(kNone) {
33 }
34
GetNextMessage()35 void ProtobufWireAdapter::GetNextMessage() {
36 if (read_state_ != kNone) {
37 LOG(ERROR) << "Invalid state: GetNextMessage called during a read";
38 listener()->OnError(pairing::kErrorProtocol);
39 return;
40 }
41
42 // Read the 4 byte preable which contains the length of the next message.
43 read_state_ = kPreamble;
44 interface()->Receive(4);
45 }
46
SendConfigurationMessage(const pairing::message::ConfigurationMessage & message)47 void ProtobufWireAdapter::SendConfigurationMessage(
48 const pairing::message::ConfigurationMessage& message) {
49 Configuration configuration;
50
51 configuration.mutable_encoding()->set_symbol_length(
52 message.encoding().symbol_length());
53
54 configuration.mutable_encoding()->set_type(
55 EncodingTypeToProto(message.encoding().encoding_type()));
56
57 configuration.set_client_role(RoleToProto(message.client_role()));
58
59 SendMessagePayload(OuterMessage_MessageType_MESSAGE_TYPE_CONFIGURATION,
60 configuration.SerializeAsString());
61 }
62
SendConfigurationAckMessage(const pairing::message::ConfigurationAckMessage & message)63 void ProtobufWireAdapter::SendConfigurationAckMessage(
64 const pairing::message::ConfigurationAckMessage& message) {
65 ConfigurationAck ack;
66
67 SendMessagePayload(OuterMessage_MessageType_MESSAGE_TYPE_CONFIGURATION_ACK,
68 ack.SerializeAsString());
69 }
70
SendOptionsMessage(const pairing::message::OptionsMessage & message)71 void ProtobufWireAdapter::SendOptionsMessage(
72 const pairing::message::OptionsMessage& message) {
73 LOG(INFO) << "Sending " << message.ToString();
74
75 Options options;
76 encoding::EncodingOption::EncodingSet::const_iterator iter;
77 for (iter = message.input_encodings().begin();
78 iter != message.input_encodings().end();
79 iter++) {
80 encoding::EncodingOption option = *iter;
81 Options_Encoding* encoding = options.add_input_encodings();
82 encoding->set_symbol_length(option.symbol_length());
83 encoding->set_type(EncodingTypeToProto(option.encoding_type()));
84 }
85
86 for (iter = message.output_encodings().begin();
87 iter != message.output_encodings().end();
88 iter++) {
89 encoding::EncodingOption option = *iter;
90 Options_Encoding* encoding = options.add_output_encodings();
91 encoding->set_symbol_length(option.symbol_length());
92 encoding->set_type(EncodingTypeToProto(option.encoding_type()));
93 }
94
95 options.set_preferred_role(RoleToProto(message.protocol_role_preference()));
96
97 SendMessagePayload(OuterMessage_MessageType_MESSAGE_TYPE_OPTIONS,
98 options.SerializeAsString());
99 }
100
SendPairingRequestMessage(const pairing::message::PairingRequestMessage & message)101 void ProtobufWireAdapter::SendPairingRequestMessage(
102 const pairing::message::PairingRequestMessage& message) {
103 LOG(INFO) << "Sending " << message.ToString();
104
105 PairingRequest request;
106 request.set_service_name(message.service_name());
107
108 if (message.has_client_name()) {
109 request.set_client_name(message.client_name());
110 }
111
112 SendMessagePayload(OuterMessage_MessageType_MESSAGE_TYPE_PAIRING_REQUEST,
113 request.SerializeAsString());
114 }
115
SendPairingRequestAckMessage(const pairing::message::PairingRequestAckMessage & message)116 void ProtobufWireAdapter::SendPairingRequestAckMessage(
117 const pairing::message::PairingRequestAckMessage& message) {
118 LOG(INFO) << "Sending " << message.ToString();
119
120 PairingRequestAck ack;
121
122 if (message.has_server_name()) {
123 ack.set_server_name(message.server_name());
124 }
125
126 SendMessagePayload(OuterMessage_MessageType_MESSAGE_TYPE_PAIRING_REQUEST_ACK,
127 ack.SerializeAsString());
128 }
129
SendSecretMessage(const pairing::message::SecretMessage & message)130 void ProtobufWireAdapter::SendSecretMessage(
131 const pairing::message::SecretMessage& message) {
132 LOG(INFO) << "Sending " << message.ToString();
133
134 Secret secret;
135 secret.set_secret(&message.secret()[0], message.secret().size());
136
137 SendMessagePayload(OuterMessage_MessageType_MESSAGE_TYPE_SECRET,
138 secret.SerializeAsString());
139 }
140
SendSecretAckMessage(const pairing::message::SecretAckMessage & message)141 void ProtobufWireAdapter::SendSecretAckMessage(
142 const pairing::message::SecretAckMessage& message) {
143 LOG(INFO) << "Sending " << message.ToString();
144
145 SecretAck ack;
146 ack.set_secret(&message.secret()[0], message.secret().size());
147
148 SendMessagePayload(OuterMessage_MessageType_MESSAGE_TYPE_SECRET_ACK,
149 ack.SerializeAsString());
150 }
151
OnBytesReceived(const std::vector<uint8_t> & data)152 void ProtobufWireAdapter::OnBytesReceived(
153 const std::vector<uint8_t>& data) {
154 if (read_state_ == kMessage) {
155 // We were waiting for a message, so parse the message and reset the read
156 // state.
157 read_state_ = kNone;
158 ParseMessage(data);
159 } else if (read_state_ == kPreamble && data.size() == 4) {
160 // If we were waiting for the preamble and we received the expected 4 bytes,
161 // then wait for the rest of the message now that we know the size.
162 read_state_ = kMessage;
163 uint32_t message_length = util::PoloUtil::BigEndianBytesToInt(&data[0]);
164 interface()->Receive(message_length);
165 } else {
166 LOG(ERROR) << "Unexpected state: " << read_state_
167 << " bytes: " << data.size();
168 listener()->OnError(pairing::kErrorProtocol);
169 }
170 }
171
ParseMessage(const std::vector<uint8_t> & data)172 void ProtobufWireAdapter::ParseMessage(const std::vector<uint8_t>& data) {
173 OuterMessage outer;
174
175 std::string string(reinterpret_cast<const char*>(&data[0]), data.size());
176 if (!outer.ParseFromString(string)) {
177 LOG(ERROR) << "Error parsing outer message";
178 listener()->OnError(pairing::kErrorProtocol);
179 return;
180 }
181
182 if (outer.status() != OuterMessage_Status_STATUS_OK) {
183 LOG(ERROR) << "Got error message: " << outer.status();
184 pairing::PoloError error = pairing::kErrorProtocol;
185 switch (outer.status()) {
186 case OuterMessage_Status_STATUS_BAD_CONFIGURATION:
187 error = pairing::kErrorBadConfiguration;
188 break;
189 case OuterMessage_Status_STATUS_BAD_SECRET:
190 error = pairing::kErrorInvalidChallengeResponse;
191 break;
192 }
193 listener()->OnError(error);
194 return;
195 }
196
197 LOG(INFO) << "Parsing message type: " << outer.type();
198
199 switch (outer.type()) {
200 case OuterMessage_MessageType_MESSAGE_TYPE_CONFIGURATION:
201 ParseConfigurationMessage(outer.payload());
202 break;
203 case OuterMessage_MessageType_MESSAGE_TYPE_CONFIGURATION_ACK:
204 ParseConfigurationAckMessage(outer.payload());
205 break;
206 case OuterMessage_MessageType_MESSAGE_TYPE_OPTIONS:
207 ParseOptionsMessage(outer.payload());
208 break;
209 case OuterMessage_MessageType_MESSAGE_TYPE_PAIRING_REQUEST:
210 ParsePairingRequestMessage(outer.payload());
211 break;
212 case OuterMessage_MessageType_MESSAGE_TYPE_PAIRING_REQUEST_ACK:
213 ParsePairingRequestAckMessage(outer.payload());
214 break;
215 case OuterMessage_MessageType_MESSAGE_TYPE_SECRET:
216 ParseSecretMessage(outer.payload());
217 break;
218 case OuterMessage_MessageType_MESSAGE_TYPE_SECRET_ACK:
219 ParseSecretAckMessage(outer.payload());
220 break;
221 default:
222 LOG(ERROR) << "Unknown message type " << outer.type();
223 listener()->OnError(pairing::kErrorProtocol);
224 return;
225 }
226 }
227
ParseConfigurationMessage(const std::string & payload)228 void ProtobufWireAdapter::ParseConfigurationMessage(
229 const std::string& payload) {
230 Configuration configuration;
231 if (!configuration.ParseFromString(payload)) {
232 LOG(ERROR) << "Invalid ConfigurationMessage";
233 listener()->OnError(pairing::kErrorProtocol);
234 return;
235 }
236
237 encoding::EncodingOption encoding(
238 EncodingTypeFromProto(configuration.encoding().type()),
239 configuration.encoding().symbol_length());
240 pairing::message::OptionsMessage::ProtocolRole role =
241 RoleFromProto(configuration.client_role());
242
243 pairing::message::ConfigurationMessage message(encoding, role);
244 listener()->OnConfigurationMessage(message);
245 }
246
ParseConfigurationAckMessage(const std::string & payload)247 void ProtobufWireAdapter::ParseConfigurationAckMessage(
248 const std::string& payload) {
249 ConfigurationAck ack;
250 if (!ack.ParseFromString(payload)) {
251 LOG(ERROR) << "Invalid ConfigurationAckMessage";
252 listener()->OnError(pairing::kErrorProtocol);
253 return;
254 }
255
256 pairing::message::ConfigurationAckMessage message;
257 listener()->OnConfigurationAckMessage(message);
258 }
259
ParseOptionsMessage(const std::string & payload)260 void ProtobufWireAdapter::ParseOptionsMessage(const std::string& payload) {
261 Options options;
262 if (!options.ParseFromString(payload)) {
263 LOG(ERROR) << "Invalid OptionsMessage";
264 listener()->OnError(pairing::kErrorProtocol);
265 return;
266 }
267
268 pairing::message::OptionsMessage message;
269
270 for (int i = 0; i < options.input_encodings().size(); i++) {
271 const Options_Encoding& encoding = options.input_encodings(i);
272
273 encoding::EncodingOption option(EncodingTypeFromProto(encoding.type()),
274 encoding.symbol_length());
275 message.AddInputEncoding(option);
276 }
277
278 for (int i = 0; i < options.output_encodings().size(); i++) {
279 const Options_Encoding& encoding = options.output_encodings(i);
280
281 encoding::EncodingOption option(EncodingTypeFromProto(encoding.type()),
282 encoding.symbol_length());
283 message.AddOutputEncoding(option);
284 }
285
286 message.set_protocol_role_preference(
287 RoleFromProto(options.preferred_role()));
288
289 listener()->OnOptionsMessage(message);
290 }
291
ParsePairingRequestMessage(const std::string & payload)292 void ProtobufWireAdapter::ParsePairingRequestMessage(
293 const std::string& payload) {
294 PairingRequest request;
295 if (!request.ParseFromString(payload)) {
296 LOG(ERROR) << "Invalid PairingRequestMessage";
297 listener()->OnError(pairing::kErrorProtocol);
298 return;
299 }
300
301 if (request.has_client_name()) {
302 pairing::message::PairingRequestMessage message(request.service_name(),
303 request.client_name());
304 listener()->OnPairingRequestMessage(message);
305 } else {
306 pairing::message::PairingRequestMessage message(request.service_name());
307 listener()->OnPairingRequestMessage(message);
308 }
309 }
310
ParsePairingRequestAckMessage(const std::string & payload)311 void ProtobufWireAdapter::ParsePairingRequestAckMessage(
312 const std::string& payload) {
313 PairingRequestAck ack;
314 if (!ack.ParseFromString(payload)) {
315 LOG(ERROR) << "Invalid PairingRequestAckMessage";
316 listener()->OnError(pairing::kErrorProtocol);
317 return;
318 }
319
320 if (ack.has_server_name()) {
321 pairing::message::PairingRequestAckMessage message(ack.server_name());
322 listener()->OnPairingRequestAckMessage(message);
323 } else {
324 pairing::message::PairingRequestAckMessage message;
325 listener()->OnPairingRequestAckMessage(message);
326 }
327 }
328
ParseSecretMessage(const std::string & payload)329 void ProtobufWireAdapter::ParseSecretMessage(const std::string& payload) {
330 Secret secret;
331 if (!secret.ParseFromString(payload)) {
332 LOG(ERROR) << "Invalid SecretMessage";
333 listener()->OnError(pairing::kErrorProtocol);
334 return;
335 }
336
337 const std::vector<uint8_t> secret_bytes(secret.secret().begin(),
338 secret.secret().end());
339
340 pairing::message::SecretMessage message(secret_bytes);
341 listener()->OnSecretMessage(message);
342 }
343
ParseSecretAckMessage(const std::string & payload)344 void ProtobufWireAdapter::ParseSecretAckMessage(const std::string& payload) {
345 SecretAck ack;
346 if (!ack.ParseFromString(payload)) {
347 LOG(ERROR) << "Invalid SecretAckMessage";
348 listener()->OnError(pairing::kErrorProtocol);
349 return;
350 }
351
352 std::vector<uint8_t> secret_bytes(ack.secret().begin(),
353 ack.secret().end());
354
355 pairing::message::SecretAckMessage message(secret_bytes);
356 listener()->OnSecretAckMessage(message);
357 }
358
OnError()359 void ProtobufWireAdapter::OnError() {
360 LOG(ERROR) << "OnError";
361 listener()->OnError(pairing::kErrorNetwork);
362 }
363
SendErrorMessage(pairing::PoloError error)364 void ProtobufWireAdapter::SendErrorMessage(pairing::PoloError error) {
365 OuterMessage outer;
366 outer.set_protocol_version(1);
367
368 OuterMessage_Status status;
369 switch (error) {
370 case pairing::kErrorBadConfiguration:
371 status = OuterMessage_Status_STATUS_BAD_CONFIGURATION;
372 break;
373 case pairing::kErrorInvalidChallengeResponse:
374 status = OuterMessage_Status_STATUS_BAD_SECRET;
375 break;
376 default:
377 status = OuterMessage_Status_STATUS_ERROR;
378 }
379
380 outer.set_status(status);
381
382 SendOuterMessage(outer);
383 }
384
SendMessagePayload(OuterMessage_MessageType type,const std::string & payload)385 void ProtobufWireAdapter::SendMessagePayload(OuterMessage_MessageType type,
386 const std::string& payload) {
387 // Create the outer message which specifies the message type and payload data.
388 OuterMessage outer;
389 outer.set_type(type);
390 outer.set_payload(payload);
391 outer.set_protocol_version(1);
392 outer.set_status(OuterMessage_Status_STATUS_OK);
393
394 SendOuterMessage(outer);
395 }
396
SendOuterMessage(const OuterMessage & message)397 void ProtobufWireAdapter::SendOuterMessage(const OuterMessage& message) {
398 // Send the message as a string, prepended with a 4 byte preamble containing
399 // the length of the message in bytes.
400 std::string outer_string = message.SerializeAsString();
401
402 uint8_t* size_bytes;
403 util::PoloUtil::IntToBigEndianBytes(outer_string.length(), size_bytes);
404
405 std::vector<uint8_t> data(outer_string.length() + 4);
406
407 std::vector<uint8_t>::iterator iter = data.begin();
408 std::copy(size_bytes, size_bytes + 4, iter);
409 std::copy(outer_string.begin(), outer_string.end(), iter + 4);
410 delete[] size_bytes;
411
412 interface()->Send(data);
413 }
414
EncodingTypeToProto(encoding::EncodingOption::EncodingType type)415 Options_Encoding_EncodingType ProtobufWireAdapter::EncodingTypeToProto(
416 encoding::EncodingOption::EncodingType type) {
417 switch (type) {
418 case encoding::EncodingOption::kAlphaNumeric:
419 return Options_Encoding_EncodingType_ENCODING_TYPE_ALPHANUMERIC;
420 case encoding::EncodingOption::kHexadecimal:
421 return Options_Encoding_EncodingType_ENCODING_TYPE_HEXADECIMAL;
422 case encoding::EncodingOption::kNumeric:
423 return Options_Encoding_EncodingType_ENCODING_TYPE_NUMERIC;
424 case encoding::EncodingOption::kQRCode:
425 return Options_Encoding_EncodingType_ENCODING_TYPE_QRCODE;
426 default:
427 return Options_Encoding_EncodingType_ENCODING_TYPE_UNKNOWN;
428 }
429 }
430
431 encoding::EncodingOption::EncodingType
EncodingTypeFromProto(Options_Encoding_EncodingType type)432 ProtobufWireAdapter::EncodingTypeFromProto(
433 Options_Encoding_EncodingType type) {
434 switch (type) {
435 case Options_Encoding_EncodingType_ENCODING_TYPE_ALPHANUMERIC:
436 return encoding::EncodingOption::kAlphaNumeric;
437 case Options_Encoding_EncodingType_ENCODING_TYPE_HEXADECIMAL:
438 return encoding::EncodingOption::kHexadecimal;
439 case Options_Encoding_EncodingType_ENCODING_TYPE_NUMERIC:
440 return encoding::EncodingOption::kNumeric;
441 case Options_Encoding_EncodingType_ENCODING_TYPE_QRCODE:
442 return encoding::EncodingOption::kQRCode;
443 default:
444 return encoding::EncodingOption::kUnknown;
445 }
446 }
447
RoleToProto(pairing::message::OptionsMessage::ProtocolRole role)448 Options_RoleType ProtobufWireAdapter::RoleToProto(
449 pairing::message::OptionsMessage::ProtocolRole role) {
450 switch (role) {
451 case pairing::message::OptionsMessage::kInputDevice:
452 return Options_RoleType_ROLE_TYPE_INPUT;
453 case pairing::message::OptionsMessage::kDisplayDevice:
454 return Options_RoleType_ROLE_TYPE_OUTPUT;
455 default:
456 return Options_RoleType_ROLE_TYPE_UNKNOWN;
457 }
458 }
459
460 pairing::message::OptionsMessage::ProtocolRole
RoleFromProto(Options_RoleType role)461 ProtobufWireAdapter::RoleFromProto(Options_RoleType role) {
462 switch (role) {
463 case Options_RoleType_ROLE_TYPE_INPUT:
464 return pairing::message::OptionsMessage::kInputDevice;
465 case Options_RoleType_ROLE_TYPE_OUTPUT:
466 return pairing::message::OptionsMessage::kDisplayDevice;
467 default:
468 return pairing::message::OptionsMessage::kUnknown;
469 }
470 }
471
472 } // namespace protobuf
473 } // namespace wire
474 } // namespace polo
475