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