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