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
27namespace polo {
28namespace wire {
29namespace protobuf {
30
31ProtobufWireAdapter::ProtobufWireAdapter(PoloWireInterface* interface)
32    : PoloWireAdapter(interface), read_state_(kNone) {
33}
34
35void 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
47void 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
63void 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
71void 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
101void 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
116void 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
130void 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
141void 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
152void 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
172void 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
228void 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
247void 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
260void 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
292void 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
311void 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
329void 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
344void 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
359void ProtobufWireAdapter::OnError() {
360  LOG(ERROR) << "OnError";
361  listener()->OnError(pairing::kErrorNetwork);
362}
363
364void 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
385void 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
397void 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
415Options_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
431encoding::EncodingOption::EncodingType
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
448Options_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
460pairing::message::OptionsMessage::ProtocolRole
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