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