C++程序  |  203行  |  6.46 KB

// 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_