1 /* 2 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.polo.wire.protobuf; 18 19 import com.google.polo.exception.BadSecretException; 20 import com.google.polo.exception.NoConfigurationException; 21 import com.google.polo.exception.PoloException; 22 import com.google.polo.exception.ProtocolErrorException; 23 import com.google.polo.pairing.PairingContext; 24 import com.google.polo.pairing.PoloUtil; 25 import com.google.polo.pairing.message.ConfigurationAckMessage; 26 import com.google.polo.pairing.message.ConfigurationMessage; 27 import com.google.polo.pairing.message.EncodingOption; 28 import com.google.polo.pairing.message.OptionsMessage; 29 import com.google.polo.pairing.message.PairingRequestAckMessage; 30 import com.google.polo.pairing.message.PairingRequestMessage; 31 import com.google.polo.pairing.message.PoloMessage; 32 import com.google.polo.pairing.message.SecretAckMessage; 33 import com.google.polo.pairing.message.SecretMessage; 34 import com.google.polo.wire.PoloWireInterface; 35 import com.google.polo.wire.protobuf.PoloProto.OuterMessage; 36 import com.google.protobuf.nano.MessageNano; 37 38 import java.io.IOException; 39 import java.io.InputStream; 40 import java.io.OutputStream; 41 42 /** 43 * Implementation of {@link PoloWireInterface} that uses Protocol Buffers for 44 * the data representation. 45 * <p/> 46 * The primary work of this class is to translate Protocol Buffer messages 47 * instances (derived from {@link MessageNano} to an internal message 48 * instance (derived from {@link PoloMessage}, and vice versa. 49 * <p/> 50 * The reason we are going through all this trouble, and not using protocol 51 * buffer objects directly, is that we'd like to limit the scope of protocol 52 * buffers to the wire protocol only. Some applications may prefer to use 53 * a different wire format, where the requirement of adding the protobuf library 54 * could be an impediment. 55 */ 56 public class ProtobufWireAdapter implements PoloWireInterface { 57 58 /** 59 * The output coming from the peer. 60 */ 61 private final InputStream mInputStream; 62 /** 63 * The input going to the peer. 64 */ 65 private final OutputStream mOutputStream; 66 67 /** 68 * Constructor. 69 * 70 * @param input the {@link InputStream} from the peer 71 * @param output the {@link OutputStream} to the peer 72 */ ProtobufWireAdapter(InputStream input, OutputStream output)73 public ProtobufWireAdapter(InputStream input, OutputStream output) { 74 mInputStream = input; 75 mOutputStream = output; 76 } 77 78 /** 79 * Generates a new instance from a {@link PairingContext}. 80 * 81 * @param context the {@link PairingContext} 82 * @return the new instance 83 */ fromContext(PairingContext context)84 public static ProtobufWireAdapter fromContext(PairingContext context) { 85 return new ProtobufWireAdapter(context.getPeerInputStream(), 86 context.getPeerOutputStream()); 87 } 88 89 /** 90 * Returns the next message sent over the wire, blocking as necessary. 91 */ getNextMessage()92 public PoloMessage getNextMessage() throws IOException, PoloException { 93 return protoToPoloMessage(readNextInnerMessage()); 94 } 95 96 /** 97 * Returns the next message read over the wire, requiring it to be a certain 98 * type. 99 * 100 * @param type the required message type 101 * @throws IOException on error during read 102 * @throws PoloException if the wrong message type was read, or on protocol 103 * error 104 */ getNextMessage(PoloMessage.PoloMessageType type)105 public PoloMessage getNextMessage(PoloMessage.PoloMessageType type) 106 throws IOException, PoloException { 107 PoloMessage message = getNextMessage(); 108 if (message.getType() != type) { 109 throw new PoloException("Wrong message type (wanted " + type + 110 ", got " + message.getType() + ")"); 111 } 112 return message; 113 } 114 115 /** 116 * Returns the next message seen on the input stream. 117 * 118 * @return the next OuterMessage read from the wire 119 * @throws IOException on error during read 120 */ readNextOuterMessage()121 private OuterMessage readNextOuterMessage() throws IOException, PoloException { 122 // Read the preamble (length of payload) 123 byte[] preambleBuffer = readBytesBlocking(4); 124 int messageLen = (int) PoloUtil.intBigEndianBytesToLong(preambleBuffer); 125 126 // Read the payload (serialized PoloMessage) 127 byte[] messageBuffer = readBytesBlocking(messageLen); 128 129 // Decode and return the payload 130 OuterMessage message = OuterMessage.parseFrom(messageBuffer); 131 132 if (message.status != OuterMessage.STATUS_OK) { 133 throw new ProtocolErrorException(); 134 } 135 136 return message; 137 } 138 139 /** 140 * Reads the next inner message from the wire, decoding and handling the outer 141 * message in the process. 142 * 143 * @return a protocol buffer message 144 * @throws IOException on error during read 145 * @throws PoloException on protocol error 146 */ readNextInnerMessage()147 private MessageNano readNextInnerMessage() 148 throws IOException, PoloException { 149 OuterMessage message = readNextOuterMessage(); 150 151 byte[] payload = message.payload; 152 153 if (message.type == OuterMessage.MESSAGE_TYPE_OPTIONS) { 154 return PoloProto.Options.parseFrom(payload); 155 } else if (message.type == OuterMessage.MESSAGE_TYPE_PAIRING_REQUEST) { 156 return PoloProto.PairingRequest.parseFrom(payload); 157 } else if (message.type == OuterMessage.MESSAGE_TYPE_PAIRING_REQUEST_ACK) { 158 return PoloProto.PairingRequestAck.parseFrom(payload); 159 } else if (message.type == OuterMessage.MESSAGE_TYPE_CONFIGURATION) { 160 return PoloProto.Configuration.parseFrom(payload); 161 } else if (message.type == OuterMessage.MESSAGE_TYPE_CONFIGURATION_ACK) { 162 return PoloProto.ConfigurationAck.parseFrom(payload); 163 } else if (message.type == OuterMessage.MESSAGE_TYPE_SECRET) { 164 return PoloProto.Secret.parseFrom(payload); 165 } else if (message.type == OuterMessage.MESSAGE_TYPE_SECRET_ACK) { 166 return PoloProto.SecretAck.parseFrom(payload); 167 } 168 169 throw new IOException("Could not unparse message"); 170 } 171 172 /** 173 * Convenience method to read a fixed number of bytes from the client 174 * InputStream, blocking if necessary. 175 * 176 * @param numBytes the number of bytes to read 177 * @return the bytes read 178 * @throws IOException on error during read 179 */ readBytesBlocking(int numBytes)180 private byte[] readBytesBlocking(int numBytes) throws IOException { 181 byte[] buf = new byte[numBytes]; 182 int bytesRead = 0; 183 184 // For an SSLSocket, read() can frequently return zero bytes, 185 // or fewer bytes than desired, due to SSL unwrapping and other 186 // non-application-data events. 187 while (bytesRead < numBytes) { 188 int inc = mInputStream.read(buf, bytesRead, numBytes - bytesRead); 189 if (inc < 0) { 190 throw new IOException("Stream closed while reading."); 191 } 192 bytesRead += inc; 193 } 194 return buf; 195 } 196 197 /** 198 * Wraps an outer message in an inner message. 199 * 200 * @param message the {@link MessageNano} to wrap 201 * @throws PoloException if the message was not well formed 202 */ wrapInnerMessage(MessageNano message)203 private OuterMessage wrapInnerMessage(MessageNano message) 204 throws PoloException { 205 int type; 206 if (message instanceof PoloProto.Options) { 207 type = OuterMessage.MESSAGE_TYPE_OPTIONS; 208 } else if (message instanceof PoloProto.PairingRequest) { 209 type = OuterMessage.MESSAGE_TYPE_PAIRING_REQUEST; 210 } else if (message instanceof PoloProto.PairingRequestAck) { 211 type = OuterMessage.MESSAGE_TYPE_PAIRING_REQUEST_ACK; 212 } else if (message instanceof PoloProto.Configuration) { 213 type = OuterMessage.MESSAGE_TYPE_CONFIGURATION; 214 } else if (message instanceof PoloProto.ConfigurationAck) { 215 type = OuterMessage.MESSAGE_TYPE_CONFIGURATION_ACK; 216 } else if (message instanceof PoloProto.Secret) { 217 type = OuterMessage.MESSAGE_TYPE_SECRET; 218 } else if (message instanceof PoloProto.SecretAck) { 219 type = OuterMessage.MESSAGE_TYPE_SECRET_ACK; 220 } else { 221 throw new PoloException("Bad inner message type."); 222 } 223 224 // compose outer message 225 OuterMessage outerMessage = new OuterMessage(); 226 outerMessage.status = OuterMessage.STATUS_OK; 227 outerMessage.protocolVersion = 1; 228 outerMessage.type = type; 229 outerMessage.payload = MessageNano.toByteArray(message); 230 return outerMessage; 231 } 232 233 /** 234 * Writes an {@link OuterMessage} to the wire. 235 * 236 * @param message the message 237 * @throws IOException on error during write 238 */ writeMessage(OuterMessage message)239 private void writeMessage(OuterMessage message) throws IOException { 240 byte[] messageBytes = message.payload; 241 int messageLength = messageBytes.length; 242 243 mOutputStream.write(PoloUtil.intToBigEndianIntBytes(messageLength)); 244 mOutputStream.write(messageBytes); 245 } 246 247 /** 248 * Writes a new message to the wire. 249 */ sendMessage(PoloMessage message)250 public void sendMessage(PoloMessage message) 251 throws IOException, PoloException { 252 MessageNano pb = poloMessageToProto(message); 253 OuterMessage outerMessage = wrapInnerMessage(pb); 254 writeMessage(outerMessage); 255 } 256 257 /** 258 * Sends a new error message to the wire. 259 */ sendErrorMessage(Exception e)260 public void sendErrorMessage(Exception e) throws IOException { 261 OuterMessage outerMessage = new OuterMessage(); 262 outerMessage.protocolVersion = 1; 263 264 if (e instanceof NoConfigurationException) { 265 outerMessage.status = OuterMessage.STATUS_BAD_CONFIGURATION; 266 } else if (e instanceof BadSecretException) { 267 outerMessage.status = OuterMessage.STATUS_BAD_SECRET; 268 } else { 269 outerMessage.status = OuterMessage.STATUS_ERROR; 270 } 271 272 writeMessage(outerMessage); 273 } 274 275 /** 276 * Converts an internal message to the corresponding protocol buffer message. 277 * 278 * @param poloMessage the internal message 279 * @return a new {@link MessageNano} instance 280 */ poloMessageToProto(PoloMessage poloMessage)281 private MessageNano poloMessageToProto(PoloMessage poloMessage) { 282 if (poloMessage instanceof PairingRequestMessage) { 283 return toProto((PairingRequestMessage) poloMessage); 284 } else if (poloMessage instanceof PairingRequestAckMessage) { 285 return toProto((PairingRequestAckMessage) poloMessage); 286 } else if (poloMessage instanceof OptionsMessage) { 287 return toProto((OptionsMessage) poloMessage); 288 } else if (poloMessage instanceof ConfigurationMessage) { 289 return toProto((ConfigurationMessage) poloMessage); 290 } else if (poloMessage instanceof ConfigurationAckMessage) { 291 return toProto((ConfigurationAckMessage) poloMessage); 292 } else if (poloMessage instanceof SecretMessage) { 293 return toProto((SecretMessage) poloMessage); 294 } else if (poloMessage instanceof SecretAckMessage) { 295 return toProto((SecretAckMessage) poloMessage); 296 } 297 return null; 298 } 299 300 /** 301 * Converts a {@link PairingRequestMessage} to a 302 * {@link PoloProto.PairingRequest}. 303 */ toProto(PairingRequestMessage poloMessage)304 private PoloProto.PairingRequest toProto(PairingRequestMessage poloMessage) { 305 PoloProto.PairingRequest pairingRequest = new PoloProto.PairingRequest(); 306 pairingRequest.serviceName = poloMessage.getServiceName(); 307 308 if (poloMessage.hasClientName()) { 309 pairingRequest.clientName = poloMessage.getClientName(); 310 } 311 return pairingRequest; 312 } 313 314 /** 315 * Converts a {@link PairingRequestAckMessage} to a 316 * {@link PoloProto.PairingRequestAck}. 317 */ toProto(PairingRequestAckMessage poloMessage)318 private PoloProto.PairingRequestAck toProto(PairingRequestAckMessage poloMessage) { 319 PoloProto.PairingRequestAck pairingRequestAck = new PoloProto.PairingRequestAck(); 320 if (poloMessage.hasServerName()) { 321 pairingRequestAck.serverName = poloMessage.getServerName(); 322 } 323 return pairingRequestAck; 324 } 325 326 /** 327 * Converts a {@link OptionsMessage} to a {@link PoloProto.Options}. 328 */ toProto(OptionsMessage poloMessage)329 private PoloProto.Options toProto(OptionsMessage poloMessage) { 330 PoloProto.Options options = new PoloProto.Options(); 331 332 switch (poloMessage.getProtocolRolePreference()) { 333 case DISPLAY_DEVICE: 334 options.preferredRole = PoloProto.Options.ROLE_TYPE_INPUT; 335 break; 336 case INPUT_DEVICE: 337 options.preferredRole = PoloProto.Options.ROLE_TYPE_OUTPUT; 338 break; 339 } 340 341 int i = 0, n = poloMessage.getOutputEncodingSet().size(); 342 options.outputEncodings = new PoloProto.Options.Encoding[n]; 343 for (EncodingOption enc : poloMessage.getOutputEncodingSet()) { 344 options.outputEncodings[i++] = toProto(enc); 345 } 346 347 i = 0; 348 n = poloMessage.getInputEncodingSet().size(); 349 options.inputEncodings = new PoloProto.Options.Encoding[n]; 350 for (EncodingOption enc : poloMessage.getInputEncodingSet()) { 351 options.inputEncodings[i++] = toProto(enc); 352 } 353 354 return options; 355 } 356 357 /** 358 * Converts a {@link ConfigurationMessage} to a 359 * {@link PoloProto.Configuration}. 360 */ toProto(ConfigurationMessage poloMessage)361 private PoloProto.Configuration toProto(ConfigurationMessage poloMessage) { 362 PoloProto.Configuration configuration = new PoloProto.Configuration(); 363 configuration.encoding = toProto(poloMessage.getEncoding()); 364 configuration.clientRole = toProto(poloMessage.getClientRole()); 365 return configuration; 366 } 367 368 /** 369 * Converts a {@link EncodingOption} to a {@link PoloProto.Options.Encoding}. 370 */ toProto(EncodingOption enc)371 private PoloProto.Options.Encoding toProto(EncodingOption enc) { 372 PoloProto.Options.Encoding encoding = new PoloProto.Options.Encoding(); 373 374 switch (enc.getType()) { 375 case ENCODING_ALPHANUMERIC: 376 encoding.type = PoloProto.Options.Encoding.ENCODING_TYPE_ALPHANUMERIC; 377 break; 378 case ENCODING_HEXADECIMAL: 379 encoding.type = PoloProto.Options.Encoding.ENCODING_TYPE_HEXADECIMAL; 380 break; 381 case ENCODING_NUMERIC: 382 encoding.type = PoloProto.Options.Encoding.ENCODING_TYPE_NUMERIC; 383 break; 384 case ENCODING_QRCODE: 385 encoding.type = PoloProto.Options.Encoding.ENCODING_TYPE_QRCODE; 386 break; 387 default: 388 encoding.type = PoloProto.Options.Encoding.ENCODING_TYPE_UNKNOWN; 389 break; 390 } 391 392 encoding.symbolLength = enc.getSymbolLength(); 393 return encoding; 394 } 395 396 /** 397 * Converts a {@link OptionsMessage.ProtocolRole} to a 398 * {@link PoloProto.Options}. 399 */ toProto(OptionsMessage.ProtocolRole role)400 private int toProto(OptionsMessage.ProtocolRole role) { 401 switch (role) { 402 case DISPLAY_DEVICE: 403 return PoloProto.Options.ROLE_TYPE_OUTPUT; 404 case INPUT_DEVICE: 405 return PoloProto.Options.ROLE_TYPE_INPUT; 406 default: 407 return PoloProto.Options.ROLE_TYPE_UNKNOWN; 408 } 409 } 410 411 /** 412 * Converts a {@link ConfigurationAckMessage} to a 413 * {@link PoloProto.ConfigurationAck}. 414 */ toProto(ConfigurationAckMessage poloMessage)415 private PoloProto.ConfigurationAck toProto(ConfigurationAckMessage poloMessage) { 416 PoloProto.ConfigurationAck configurationAck = new PoloProto.ConfigurationAck(); 417 return configurationAck; 418 } 419 420 /** 421 * Converts a {@link SecretMessage} to a {@link PoloProto.Secret}. 422 */ toProto(SecretMessage poloMessage)423 private PoloProto.Secret toProto(SecretMessage poloMessage) { 424 PoloProto.Secret secret = new PoloProto.Secret(); 425 secret.secret = poloMessage.getSecret(); 426 return secret; 427 } 428 429 /** 430 * Converts a {@link SecretAckMessage} to a {@link PoloProto.SecretAck}. 431 */ toProto(SecretAckMessage poloMessage)432 private PoloProto.SecretAck toProto(SecretAckMessage poloMessage) { 433 PoloProto.SecretAck secretAck = new PoloProto.SecretAck(); 434 secretAck.secret = poloMessage.getSecret(); 435 return secretAck; 436 } 437 438 // 439 // polo -> protocol buffer routines 440 // 441 442 /** 443 * Converts a protocol buffer message to the corresponding internal 444 * message. 445 * 446 * @param protoMessage the protobuf message to convert 447 * @return the new {@link PoloMessage} 448 */ protoToPoloMessage(MessageNano protoMessage)449 private PoloMessage protoToPoloMessage(MessageNano protoMessage) { 450 if (protoMessage instanceof PoloProto.PairingRequest) { 451 return fromProto((PoloProto.PairingRequest) protoMessage); 452 } else if (protoMessage instanceof PoloProto.PairingRequestAck) { 453 return fromProto((PoloProto.PairingRequestAck) protoMessage); 454 } else if (protoMessage instanceof PoloProto.Options) { 455 return fromProto((PoloProto.Options) protoMessage); 456 } else if (protoMessage instanceof PoloProto.Configuration) { 457 return fromProto((PoloProto.Configuration) protoMessage); 458 } else if (protoMessage instanceof PoloProto.ConfigurationAck) { 459 return fromProto((PoloProto.ConfigurationAck) protoMessage); 460 } else if (protoMessage instanceof PoloProto.Secret) { 461 return fromProto((PoloProto.Secret) protoMessage); 462 } else if (protoMessage instanceof PoloProto.SecretAck) { 463 return fromProto((PoloProto.SecretAck) protoMessage); 464 } 465 return null; 466 } 467 468 /** 469 * Converts a {@link PoloProto.PairingRequest} to a 470 * {@link PairingRequestMessage}. 471 */ fromProto(PoloProto.PairingRequest protoMessage)472 private PairingRequestMessage fromProto(PoloProto.PairingRequest protoMessage) { 473 return new PairingRequestMessage(protoMessage.serviceName, protoMessage.clientName); 474 } 475 476 /** 477 * Converts a {@link PoloProto.PairingRequestAck} to a 478 * {@link PairingRequestAckMessage}. 479 */ fromProto(PoloProto.PairingRequestAck protoMessage)480 private PairingRequestAckMessage fromProto(PoloProto.PairingRequestAck protoMessage) { 481 return new PairingRequestAckMessage(protoMessage.serverName); 482 } 483 484 /** 485 * Converts a {@link PoloProto.Options} to a {@link OptionsMessage}. 486 */ fromProto(PoloProto.Options protoMessage)487 private OptionsMessage fromProto(PoloProto.Options protoMessage) { 488 OptionsMessage optionsMessage = new OptionsMessage(); 489 490 switch (protoMessage.preferredRole) { 491 case PoloProto.Options.ROLE_TYPE_INPUT: 492 optionsMessage.setProtocolRolePreference(OptionsMessage.ProtocolRole.INPUT_DEVICE); 493 break; 494 case PoloProto.Options.ROLE_TYPE_OUTPUT: 495 optionsMessage.setProtocolRolePreference(OptionsMessage.ProtocolRole.DISPLAY_DEVICE); 496 break; 497 } 498 499 for (PoloProto.Options.Encoding e : protoMessage.inputEncodings) { 500 optionsMessage.addInputEncoding(fromProto(e)); 501 } 502 503 for (PoloProto.Options.Encoding e : protoMessage.outputEncodings) { 504 optionsMessage.addOutputEncoding(fromProto(e)); 505 } 506 507 return optionsMessage; 508 } 509 510 /** 511 * Converts a {@link PoloProto.Configuration} to a 512 * {@link ConfigurationMessage}. 513 */ fromProto(PoloProto.Configuration protoMessage)514 private ConfigurationMessage fromProto(PoloProto.Configuration protoMessage) { 515 EncodingOption enc = fromProto(protoMessage.encoding); 516 OptionsMessage.ProtocolRole role = OptionsMessage.ProtocolRole.UNKNOWN; 517 518 switch (protoMessage.clientRole) { 519 case PoloProto.Options.ROLE_TYPE_INPUT: 520 role = OptionsMessage.ProtocolRole.INPUT_DEVICE; 521 break; 522 case PoloProto.Options.ROLE_TYPE_OUTPUT: 523 role = OptionsMessage.ProtocolRole.DISPLAY_DEVICE; 524 break; 525 } 526 527 return new ConfigurationMessage(enc, role); 528 } 529 530 /** 531 * Converts a {@link PoloProto.ConfigurationAck} to a 532 * {@link ConfigurationAckMessage}. 533 */ fromProto(PoloProto.ConfigurationAck protoMessage)534 private ConfigurationAckMessage fromProto(PoloProto.ConfigurationAck protoMessage) { 535 return new ConfigurationAckMessage(); 536 } 537 538 /** 539 * Converts a {@link PoloProto.Secret} to a {@link SecretMessage}. 540 */ fromProto(PoloProto.Secret protoMessage)541 private SecretMessage fromProto(PoloProto.Secret protoMessage) { 542 return new SecretMessage(protoMessage.secret); 543 } 544 545 /** 546 * Converts a {@link PoloProto.SecretAck} to a {@link SecretAckMessage}. 547 */ fromProto(PoloProto.SecretAck protoMessage)548 private SecretAckMessage fromProto(PoloProto.SecretAck protoMessage) { 549 return new SecretAckMessage(protoMessage.secret); 550 } 551 552 /** 553 * Converts a {@link PoloProto.Options.Encoding} to a {@link EncodingOption}. 554 */ fromProto(PoloProto.Options.Encoding enc)555 private EncodingOption fromProto(PoloProto.Options.Encoding enc) { 556 EncodingOption.EncodingType type; 557 558 switch (enc.type) { 559 case PoloProto.Options.Encoding.ENCODING_TYPE_ALPHANUMERIC: 560 type = EncodingOption.EncodingType.ENCODING_ALPHANUMERIC; 561 break; 562 case PoloProto.Options.Encoding.ENCODING_TYPE_HEXADECIMAL: 563 type = EncodingOption.EncodingType.ENCODING_HEXADECIMAL; 564 break; 565 case PoloProto.Options.Encoding.ENCODING_TYPE_NUMERIC: 566 type = EncodingOption.EncodingType.ENCODING_NUMERIC; 567 break; 568 case PoloProto.Options.Encoding.ENCODING_TYPE_QRCODE: 569 type = EncodingOption.EncodingType.ENCODING_QRCODE; 570 break; 571 default: 572 type = EncodingOption.EncodingType.ENCODING_UNKNOWN; 573 } 574 575 return new EncodingOption(type, enc.symbolLength); 576 577 } 578 579 } 580