Jerome Poichet | 7c99785 | 2014-05-20 10:50:05 -0700 | [diff] [blame^] | 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | */ |
| 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 | } |