| // Copyright 2017 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef COMPONENTS_CRYPTAUTH_SECURE_CHANNEL_H_ | 
 | #define COMPONENTS_CRYPTAUTH_SECURE_CHANNEL_H_ | 
 |  | 
 | #include "base/containers/queue.h" | 
 | #include "base/macros.h" | 
 | #include "base/memory/weak_ptr.h" | 
 | #include "components/cryptauth/authenticator.h" | 
 | #include "components/cryptauth/connection.h" | 
 | #include "components/cryptauth/connection_observer.h" | 
 | #include "components/cryptauth/device_to_device_authenticator.h" | 
 | #include "components/cryptauth/remote_device.h" | 
 | #include "components/cryptauth/secure_context.h" | 
 | #include "components/cryptauth/secure_message_delegate.h" | 
 |  | 
 | namespace cryptauth { | 
 |  | 
 | class CryptAuthService; | 
 |  | 
 | // An authenticated bi-directional channel for exchanging messages with remote | 
 | // devices. |SecureChannel| manages a |Connection| by initializing it and | 
 | // authenticating it via a security handshake once the connection has occurred. | 
 | // Once the channel has been authenticated, messages sent are automatically | 
 | // encrypted and messages received are automatically decrypted. | 
 | class SecureChannel : public ConnectionObserver { | 
 |  public: | 
 |   // Enumeration of possible states of connecting to a remote device. | 
 |   //   DISCONNECTED: There is no connection to the device, nor is there a | 
 |   //       pending connection attempt. | 
 |   //   CONNECTING: There is an ongoing connection attempt. | 
 |   //   CONNECTED: There is a Bluetooth connection to the device, but the | 
 |   //       connection has not yet been authenticated. | 
 |   //   AUTHENTICATING: There is an active connection that is currently in the | 
 |   //       process of authenticating via a 3-message authentication handshake. | 
 |   //   AUTHENTICATED: The connection has been authenticated, and arbitrary | 
 |   //       messages can be sent/received to/from the device. | 
 |   enum class Status { | 
 |     DISCONNECTED, | 
 |     CONNECTING, | 
 |     CONNECTED, | 
 |     AUTHENTICATING, | 
 |     AUTHENTICATED, | 
 |   }; | 
 |  | 
 |   static std::string StatusToString(const Status& status); | 
 |  | 
 |   class Observer { | 
 |    public: | 
 |     virtual void OnSecureChannelStatusChanged( | 
 |         SecureChannel* secure_channel, | 
 |         const Status& old_status, | 
 |         const Status& new_status) = 0; | 
 |  | 
 |     virtual void OnMessageReceived( | 
 |         SecureChannel* secure_channel, | 
 |         const std::string& feature, | 
 |         const std::string& payload) = 0; | 
 |  | 
 |     // Called when a message has been sent successfully; |sequence_number| | 
 |     // corresponds to the value returned by an earlier call to SendMessage(). | 
 |     virtual void OnMessageSent(SecureChannel* secure_channel, | 
 |                                int sequence_number) {} | 
 |  | 
 |     // Called when GATT characteristics are not available. This observer | 
 |     // function is a temporary work-around (see crbug.com/784968). | 
 |     // TODO(khorimoto): This observer function is specific to only one | 
 |     //     SecureChannel implementation, so it is hacky to include it as part of | 
 |     //     the observer for SecureChannel. Remove this work-around when it is no | 
 |     //     longer necessary. | 
 |     virtual void OnGattCharacteristicsNotAvailable() {} | 
 |   }; | 
 |  | 
 |   class Factory { | 
 |    public: | 
 |     static std::unique_ptr<SecureChannel> NewInstance( | 
 |         std::unique_ptr<Connection> connection, | 
 |         CryptAuthService* cryptauth_service); | 
 |  | 
 |     static void SetInstanceForTesting(Factory* factory); | 
 |  | 
 |    protected: | 
 |     virtual std::unique_ptr<SecureChannel> BuildInstance( | 
 |         std::unique_ptr<Connection> connection, | 
 |         CryptAuthService* cryptauth_service); | 
 |  | 
 |    private: | 
 |     static Factory* factory_instance_; | 
 |   }; | 
 |  | 
 |   ~SecureChannel() override; | 
 |  | 
 |   virtual void Initialize(); | 
 |  | 
 |   // Sends a message over the connection and returns a sequence number. If the | 
 |   // message is successfully sent, observers will be notified that the message | 
 |   // has been sent and will be provided this sequence number. | 
 |   virtual int SendMessage(const std::string& feature, | 
 |                           const std::string& payload); | 
 |  | 
 |   virtual void Disconnect(); | 
 |  | 
 |   virtual void AddObserver(Observer* observer); | 
 |   virtual void RemoveObserver(Observer* observer); | 
 |  | 
 |   Status status() const { | 
 |     return status_; | 
 |   } | 
 |  | 
 |   // ConnectionObserver: | 
 |   void OnConnectionStatusChanged(Connection* connection, | 
 |                                  Connection::Status old_status, | 
 |                                  Connection::Status new_status) override; | 
 |   void OnMessageReceived(const Connection& connection, | 
 |                          const WireMessage& wire_message) override; | 
 |   void OnSendCompleted(const cryptauth::Connection& connection, | 
 |                        const cryptauth::WireMessage& wire_message, | 
 |                        bool success) override; | 
 |   void OnGattCharacteristicsNotAvailable() override; | 
 |  | 
 |  protected: | 
 |   SecureChannel(std::unique_ptr<Connection> connection, | 
 |                 CryptAuthService* cryptauth_service); | 
 |  | 
 |   void NotifyGattCharacteristicsNotAvailable(); | 
 |  | 
 |   Status status_; | 
 |  | 
 |  private: | 
 |   friend class CryptAuthSecureChannelTest; | 
 |  | 
 |   // Message waiting to be sent. Note that this is *not* the message that will | 
 |   // end up being sent over the wire; before that can be done, the payload must | 
 |   // be encrypted. | 
 |   struct PendingMessage { | 
 |     PendingMessage(const std::string& feature, | 
 |                    const std::string& payload, | 
 |                    int sequence_number); | 
 |     virtual ~PendingMessage(); | 
 |  | 
 |     const std::string feature; | 
 |     const std::string payload; | 
 |     const int sequence_number; | 
 |   }; | 
 |  | 
 |   void TransitionToStatus(const Status& new_status); | 
 |   void Authenticate(); | 
 |   void ProcessMessageQueue(); | 
 |   void OnMessageEncoded(const std::string& feature, | 
 |                         int sequence_number, | 
 |                         const std::string& encoded_message); | 
 |   void OnMessageDecoded( | 
 |       const std::string& feature, const std::string& decoded_message); | 
 |   void OnAuthenticationResult( | 
 |       Authenticator::Result result, | 
 |       std::unique_ptr<SecureContext> secure_context); | 
 |  | 
 |   std::unique_ptr<Connection> connection_; | 
 |   CryptAuthService* cryptauth_service_;  // Outlives this instance. | 
 |   std::unique_ptr<Authenticator> authenticator_; | 
 |   std::unique_ptr<SecureContext> secure_context_; | 
 |   base::queue<std::unique_ptr<PendingMessage>> queued_messages_; | 
 |   std::unique_ptr<PendingMessage> pending_message_; | 
 |   int next_sequence_number_ = 0; | 
 |   base::ObserverList<Observer> observer_list_; | 
 |   base::WeakPtrFactory<SecureChannel> weak_ptr_factory_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(SecureChannel); | 
 | }; | 
 |  | 
 | }  // namespace cryptauth | 
 |  | 
 | #endif  // COMPONENTS_CRYPTAUTH_SECURE_CHANNEL_H_ |