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