1// Copyright 2012 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef POLO_PAIRING_PAIRINGSESSION_H_
16#define POLO_PAIRING_PAIRINGSESSION_H_
17
18#include <string>
19
20#include "polo/encoding/secretencoder.h"
21#include "polo/pairing/pairingcontext.h"
22#include "polo/pairing/pairinglistener.h"
23#include "polo/pairing/message/messagelistener.h"
24#include "polo/wire/polowireadapter.h"
25
26namespace polo {
27namespace pairing {
28
29class PairingSession : public message::MessageListener {
30 public:
31  // The state of the Polo pairing session.
32  enum ProtocolState {
33    // The Polo session has not yet been initialized.
34    kUninitialized,
35
36    // The session is initializing.
37    kInitializing,
38
39    // The configuration options are being negotiated with the peer.
40    kConfiguring,
41
42    // The local device is being paired with the peer.
43    kPairing,
44
45    // Waiting for the secret challenge messsage or response from the peer.
46    kWaitingForSecret,
47
48    // The pairing completely successfully.
49    kSuccess,
50
51    // There was an error pairing.
52    kFailure,
53  };
54
55  // Creates a new pairing session. The given wire adapter will be used for
56  // sending and receiving protocol messages. The given context contains the
57  // local and peer SSL certificates from the establishment of the SSL
58  // connection. No ownership is taken of the given pointers.
59  PairingSession(wire::PoloWireAdapter* wire,
60                 PairingContext* context,
61                 PoloChallengeResponse* challenge);
62
63  virtual ~PairingSession();
64
65  // Adds a supported input encoding. This must be called before the session is
66  // started.
67  void AddInputEncoding(const encoding::EncodingOption& encoding);
68
69  // Adds a supported output encoding. This must be called before the session is
70  // started.
71  void AddOutputEncoding(const encoding::EncodingOption& encoding);
72
73  // Starts the pairing session. The given listener will be invoked during the
74  // pairing session.
75  void DoPair(PairingListener* listener);
76
77  // Sets the secret entered by the user. This must be invoked when, and only
78  // when, OnPerformInputDeviceRole has been called on the listener.
79  // @return Whether the secret was successfully set. If the given secret is
80  //         invalid or fails the local check, this will return false.
81  bool SetSecret(const Gamma& secret);
82
83  // Gets the encoder used for encoding and decoding the secret challenge. This
84  // should only be invoked after OnPerformInputDeviceRole or
85  // OnPerformOutputDeviceRole has been called on the listener.
86  const encoding::SecretEncoder* encoder() const { return encoder_; }
87
88 protected:
89  // Starts the pairing process.
90  void DoPairingPhase();
91
92  // Performs the initialization phase of the pairing process.
93  virtual void DoInitializationPhase() = 0;
94
95  // Performs the configuration phase of the pairing process.
96  virtual void DoConfigurationPhase() = 0;
97
98  // Sets the configuration once it has been negotiated. This must be called
99  // by implementations during the configuration phase. Returns true if the
100  // configuration was valid and false otherwise. If the configuration was
101  // invalid the pairing process can not continue.
102  bool SetConfiguration(const message::ConfigurationMessage& message);
103
104  const message::ConfigurationMessage* configuration() const {
105    return configuration_;
106  }
107
108  // @override
109  virtual void OnSecretMessage(const message::SecretMessage& message);
110
111  // @override
112  virtual void OnSecretAckMessage(const message::SecretAckMessage& message);
113
114  // @override
115  virtual void OnError(pairing::PoloError error);
116
117  // Determines whether this device is acting as the input device.
118  bool IsInputDevice() const;
119
120  // Gets the local device role or kUnknown if the configuration has not been
121  // established yet.
122  message::OptionsMessage::ProtocolRole GetLocalRole() const;
123
124  // Set the current protocol state.
125  void set_state(ProtocolState state);
126
127  // Gets the current state of the pairing process.
128  ProtocolState state() const { return state_; }
129
130  // Sets the service name.
131  void set_service_name(const std::string& service_name) {
132    service_name_.assign(service_name);
133  }
134
135  // Sets the peer name.
136  void set_peer_name(const std::string& peer_name) {
137    peer_name_.assign(peer_name);
138  }
139
140  // Gets the service name.
141  std::string service_name() const { return service_name_; }
142
143  // Gets the peer name.
144  std::string peer_name() const { return peer_name_; }
145
146  // Gets the local options.
147  const message::OptionsMessage& local_options() const {
148    return local_options_;
149  }
150
151  // Gets the wire adapter used to send and receive Polo messages.
152  wire::PoloWireAdapter* wire() const { return wire_; }
153
154  // Gets the listener that will be notified of pairing events.
155  PairingListener* listener() const { return listener_; }
156
157  // Gets the challenge response.
158  const PoloChallengeResponse& challenge() const { return *challenge_; }
159
160  // Gets the nonce value.
161  const Nonce* nonce() const { return nonce_; }
162
163 private:
164  // Performs pairing as the input device.
165  void DoInputPairing();
166
167  // Performs pairing as the output device.
168  void DoOutputPairing();
169
170  // Determines whether the given encoding option is valid.
171  bool IsValidEncodingOption(const encoding::EncodingOption& option) const;
172
173  // Verifies that the given secret is correct.
174  bool VerifySecret(const Alpha& secret) const;
175
176  enum {
177    // Whether to verify the secret ack. This is not currently required since
178    // the ack means the peer already verified the secret.
179    kVerifySecretAck = false,
180
181    // The time to wait for a secret.
182    kSecretPollTimeoutMs = 500
183  };
184
185  ProtocolState state_;
186  wire::PoloWireAdapter* wire_;
187  PairingContext* context_;
188  message::OptionsMessage local_options_;
189  PoloChallengeResponse* challenge_;
190  PairingListener* listener_;
191  message::ConfigurationMessage* configuration_;
192  encoding::SecretEncoder* encoder_;
193  Nonce* nonce_;
194  Gamma* secret_;
195  std::string service_name_;
196  std::string peer_name_;
197};
198
199}  // namespace pairing
200}  // namespace polo
201
202#endif  // POLO_PAIRING_PAIRINGSESSION_H_
203