Home | History | Annotate | Download | only in pairing
      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 
     26 namespace polo {
     27 namespace pairing {
     28 
     29 class 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