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
17package com.google.polo.wire.protobuf;
18
19import com.google.polo.exception.BadSecretException;
20import com.google.polo.exception.NoConfigurationException;
21import com.google.polo.exception.PoloException;
22import com.google.polo.exception.ProtocolErrorException;
23import com.google.polo.pairing.PairingContext;
24import com.google.polo.pairing.PoloUtil;
25import com.google.polo.pairing.message.ConfigurationAckMessage;
26import com.google.polo.pairing.message.ConfigurationMessage;
27import com.google.polo.pairing.message.EncodingOption;
28import com.google.polo.pairing.message.OptionsMessage;
29import com.google.polo.pairing.message.PairingRequestAckMessage;
30import com.google.polo.pairing.message.PairingRequestMessage;
31import com.google.polo.pairing.message.PoloMessage;
32import com.google.polo.pairing.message.SecretAckMessage;
33import com.google.polo.pairing.message.SecretMessage;
34import com.google.polo.wire.PoloWireInterface;
35import com.google.polo.wire.protobuf.nano.PoloProto;
36import com.google.polo.wire.protobuf.nano.PoloProto.OuterMessage;
37import com.google.protobuf.nano.MessageNano;
38
39import java.io.IOException;
40import java.io.InputStream;
41import 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 */
57public 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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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