Home | History | Annotate | Download | only in protobuf
      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 
     31 ProtobufWireAdapter::ProtobufWireAdapter(PoloWireInterface* interface)
     32     : PoloWireAdapter(interface), read_state_(kNone) {
     33 }
     34 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    359 void ProtobufWireAdapter::OnError() {
    360   LOG(ERROR) << "OnError";
    361   listener()->OnError(pairing::kErrorNetwork);
    362 }
    363 
    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 
    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 
    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 
    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
    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 
    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
    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