| // Copyright 2012 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef POLO_PAIRING_PAIRINGSESSION_H_ |
| #define POLO_PAIRING_PAIRINGSESSION_H_ |
| |
| #include <string> |
| |
| #include "polo/encoding/secretencoder.h" |
| #include "polo/pairing/pairingcontext.h" |
| #include "polo/pairing/pairinglistener.h" |
| #include "polo/pairing/message/messagelistener.h" |
| #include "polo/wire/polowireadapter.h" |
| |
| namespace polo { |
| namespace pairing { |
| |
| class PairingSession : public message::MessageListener { |
| public: |
| // The state of the Polo pairing session. |
| enum ProtocolState { |
| // The Polo session has not yet been initialized. |
| kUninitialized, |
| |
| // The session is initializing. |
| kInitializing, |
| |
| // The configuration options are being negotiated with the peer. |
| kConfiguring, |
| |
| // The local device is being paired with the peer. |
| kPairing, |
| |
| // Waiting for the secret challenge messsage or response from the peer. |
| kWaitingForSecret, |
| |
| // The pairing completely successfully. |
| kSuccess, |
| |
| // There was an error pairing. |
| kFailure, |
| }; |
| |
| // Creates a new pairing session. The given wire adapter will be used for |
| // sending and receiving protocol messages. The given context contains the |
| // local and peer SSL certificates from the establishment of the SSL |
| // connection. No ownership is taken of the given pointers. |
| PairingSession(wire::PoloWireAdapter* wire, |
| PairingContext* context, |
| PoloChallengeResponse* challenge); |
| |
| virtual ~PairingSession(); |
| |
| // Adds a supported input encoding. This must be called before the session is |
| // started. |
| void AddInputEncoding(const encoding::EncodingOption& encoding); |
| |
| // Adds a supported output encoding. This must be called before the session is |
| // started. |
| void AddOutputEncoding(const encoding::EncodingOption& encoding); |
| |
| // Starts the pairing session. The given listener will be invoked during the |
| // pairing session. |
| void DoPair(PairingListener* listener); |
| |
| // Sets the secret entered by the user. This must be invoked when, and only |
| // when, OnPerformInputDeviceRole has been called on the listener. |
| // @return Whether the secret was successfully set. If the given secret is |
| // invalid or fails the local check, this will return false. |
| bool SetSecret(const Gamma& secret); |
| |
| // Gets the encoder used for encoding and decoding the secret challenge. This |
| // should only be invoked after OnPerformInputDeviceRole or |
| // OnPerformOutputDeviceRole has been called on the listener. |
| const encoding::SecretEncoder* encoder() const { return encoder_; } |
| |
| protected: |
| // Starts the pairing process. |
| void DoPairingPhase(); |
| |
| // Performs the initialization phase of the pairing process. |
| virtual void DoInitializationPhase() = 0; |
| |
| // Performs the configuration phase of the pairing process. |
| virtual void DoConfigurationPhase() = 0; |
| |
| // Sets the configuration once it has been negotiated. This must be called |
| // by implementations during the configuration phase. Returns true if the |
| // configuration was valid and false otherwise. If the configuration was |
| // invalid the pairing process can not continue. |
| bool SetConfiguration(const message::ConfigurationMessage& message); |
| |
| const message::ConfigurationMessage* configuration() const { |
| return configuration_; |
| } |
| |
| // @override |
| virtual void OnSecretMessage(const message::SecretMessage& message); |
| |
| // @override |
| virtual void OnSecretAckMessage(const message::SecretAckMessage& message); |
| |
| // @override |
| virtual void OnError(pairing::PoloError error); |
| |
| // Determines whether this device is acting as the input device. |
| bool IsInputDevice() const; |
| |
| // Gets the local device role or kUnknown if the configuration has not been |
| // established yet. |
| message::OptionsMessage::ProtocolRole GetLocalRole() const; |
| |
| // Set the current protocol state. |
| void set_state(ProtocolState state); |
| |
| // Gets the current state of the pairing process. |
| ProtocolState state() const { return state_; } |
| |
| // Sets the service name. |
| void set_service_name(const std::string& service_name) { |
| service_name_.assign(service_name); |
| } |
| |
| // Sets the peer name. |
| void set_peer_name(const std::string& peer_name) { |
| peer_name_.assign(peer_name); |
| } |
| |
| // Gets the service name. |
| std::string service_name() const { return service_name_; } |
| |
| // Gets the peer name. |
| std::string peer_name() const { return peer_name_; } |
| |
| // Gets the local options. |
| const message::OptionsMessage& local_options() const { |
| return local_options_; |
| } |
| |
| // Gets the wire adapter used to send and receive Polo messages. |
| wire::PoloWireAdapter* wire() const { return wire_; } |
| |
| // Gets the listener that will be notified of pairing events. |
| PairingListener* listener() const { return listener_; } |
| |
| // Gets the challenge response. |
| const PoloChallengeResponse& challenge() const { return *challenge_; } |
| |
| // Gets the nonce value. |
| const Nonce* nonce() const { return nonce_; } |
| |
| private: |
| // Performs pairing as the input device. |
| void DoInputPairing(); |
| |
| // Performs pairing as the output device. |
| void DoOutputPairing(); |
| |
| // Determines whether the given encoding option is valid. |
| bool IsValidEncodingOption(const encoding::EncodingOption& option) const; |
| |
| // Verifies that the given secret is correct. |
| bool VerifySecret(const Alpha& secret) const; |
| |
| enum { |
| // Whether to verify the secret ack. This is not currently required since |
| // the ack means the peer already verified the secret. |
| kVerifySecretAck = false, |
| |
| // The time to wait for a secret. |
| kSecretPollTimeoutMs = 500 |
| }; |
| |
| ProtocolState state_; |
| wire::PoloWireAdapter* wire_; |
| PairingContext* context_; |
| message::OptionsMessage local_options_; |
| PoloChallengeResponse* challenge_; |
| PairingListener* listener_; |
| message::ConfigurationMessage* configuration_; |
| encoding::SecretEncoder* encoder_; |
| Nonce* nonce_; |
| Gamma* secret_; |
| std::string service_name_; |
| std::string peer_name_; |
| }; |
| |
| } // namespace pairing |
| } // namespace polo |
| |
| #endif // POLO_PAIRING_PAIRINGSESSION_H_ |