// Copyright 2018 The Chromium OS 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 SHILL_WIFI_WIFI_SERVICE_H_
#define SHILL_WIFI_WIFI_SERVICE_H_

#include <memory>
#include <set>
#include <string>
#include <vector>

#include "shill/event_dispatcher.h"
#include "shill/key_value_store.h"
#include "shill/refptr_types.h"
#include "shill/service.h"

namespace shill {

class CertificateFile;
class Error;
class Manager;
class WiFiProvider;

class WiFiService : public Service {
 public:
  // TODO(pstew): Storage constants shouldn't need to be public
  // crbug.com/208736
  static const char kStorageCredentialPassphrase[];
  static const char kStorageHiddenSSID[];
  static const char kStorageMode[];
  static const char kStorageSecurityClass[];
  static const char kStorageSSID[];

  WiFiService(Manager* manager,
              WiFiProvider* provider,
              const std::vector<uint8_t>& ssid,
              const std::string& mode,
              const std::string& security_class,
              bool hidden_ssid);
  ~WiFiService();

  // Inherited from Service.
  bool Is8021x() const override;

  virtual void AddEndpoint(const WiFiEndpointConstRefPtr& endpoint);
  virtual void RemoveEndpoint(const WiFiEndpointConstRefPtr& endpoint);
  virtual int GetEndpointCount() const { return endpoints_.size(); }

  // Called to update the identity of the currently connected endpoint.
  // To indicate that there is no currently connect endpoint, call with
  // |endpoint| set to nullptr.
  virtual void NotifyCurrentEndpoint(const WiFiEndpointConstRefPtr& endpoint);
  // Called to inform of changes in the properties of an endpoint.
  // (Not necessarily the currently connected endpoint.)
  virtual void NotifyEndpointUpdated(const WiFiEndpointConstRefPtr& endpoint);

  // wifi_<MAC>_<BSSID>_<mode_string>_<security_string>
  std::string GetStorageIdentifier() const override;

  // Validate |mode| against all valid and supported service modes.
  static bool IsValidMode(const std::string& mode);

  // Validate |method| against all valid and supported security methods.
  static bool IsValidSecurityMethod(const std::string& method);

  // Validate |security_class| against all valid and supported
  // security classes.
  static bool IsValidSecurityClass(const std::string& security_class);

  const std::string& mode() const { return mode_; }
  const std::string& key_management() const { return GetEAPKeyManagement(); }
  const std::vector<uint8_t>& ssid() const { return ssid_; }
  const std::string& bssid() const { return bssid_; }
  const std::vector<uint16_t>& frequency_list() const {
    return frequency_list_;
  }
  uint16_t physical_mode() const { return physical_mode_; }
  uint16_t frequency() const { return frequency_; }
  const std::string& security() const { return security_; }
  std::string security_class() const { return ComputeSecurityClass(security_); }

  // WiFi services can load from profile entries other than their current
  // storage identifier.  Override the methods from the parent Service
  // class which pertain to whether this service may be loaded from |storage|.
  std::string GetLoadableStorageIdentifier(
      const StoreInterface& storage) const override;
  bool IsLoadableFrom(const StoreInterface& storage) const override;

  // Override Storage methods from parent Service class.  We will call
  // the parent method.
  bool Load(const StoreInterface* storage) override;
  void MigrateDeprecatedStorage(StoreInterface* storage) override;
  bool Save(StoreInterface* storage) override;
  bool Unload() override;

  // Override SetState from parent Service class.  We will call the
  // parent method.
  void SetState(ConnectState state) override;

  virtual bool HasEndpoints() const { return !endpoints_.empty(); }
  bool IsVisible() const override;
  bool IsSecurityMatch(const std::string& security) const;

  // Used by WiFi objects to indicate that the credentials for this network
  // have been called into question.  This method returns true if given this
  // suspicion, if it is probable that indeed these credentials are likely
  // to be incorrect.  Credentials that have never been used before are
  // considered suspect by default, while those which have been used
  // successfully in the past must have this method called a number of times
  // since the last time ResetSuspectedCredentialsFailures() was called.
  virtual bool AddSuspectedCredentialFailure();
  virtual void ResetSuspectedCredentialFailures();

  bool hidden_ssid() const { return hidden_ssid_; }

  void InitializeCustomMetrics() const;
  void SendPostReadyStateMetrics(
      int64_t time_resume_to_ready_milliseconds) const override;

  // Clear any cached credentials stored in wpa_supplicant related to |this|.
  // This will disconnect this service if it is currently connected.
  void ClearCachedCredentials();

  // Override from parent Service class to correctly update connectability
  // when the EAP credentials change for 802.1x networks.
  void OnEapCredentialsChanged(
      Service::UpdateCredentialsReason reason) override;

  // Called by WiFiService to reset state associated with prior success
  // of a connection with particular EAP credentials or a passphrase.
  void OnCredentialChange(Service::UpdateCredentialsReason reason);

  // Override from parent Service class to register hidden services once they
  // have been configured.
  void OnProfileConfigured() override;

  // Called by WiFiProvider to reset the WiFi device reference on shutdown.
  virtual void ResetWiFi();

  // Called by WiFi to retrieve configuration parameters for wpa_supplicant.
  virtual KeyValueStore GetSupplicantConfigurationParameters() const;

  // "wpa", "rsn" and "psk" are equivalent from a configuration perspective.
  // This function maps them all into "psk".
  static std::string ComputeSecurityClass(const std::string& security);

  bool IsAutoConnectable(const char** reason) const override;

  std::string GetWiFiPassphrase(Error* error) override;

  // Signal level in dBm.  If no current endpoint, returns
  // std::numeric_limits<int>::min().
  int16_t SignalLevel() const;

  void set_expecting_disconnect(bool val) { expecting_disconnect_ = val; }
  bool expecting_disconnect() const { return expecting_disconnect_; }

  void set_bgscan_string(const std::string& val) { bgscan_string_ = val; }
  std::string bgscan_string() const { return bgscan_string_; }

 protected:
  // Inherited from Service.
  void OnConnect(Error* error) override;
  void OnDisconnect(Error* error, const char* reason) override;
  bool IsDisconnectable(Error* error) const override;

  void SetEAPKeyManagement(const std::string& key_management) override;
  std::string GetTethering(Error* error) const override;

 private:
  friend class WiFiServiceSecurityTest;
  friend class WiFiServiceTest;                     // SetPassphrase
  friend class WiFiServiceUpdateFromEndpointsTest;  // SignalToStrength
  FRIEND_TEST(MetricsTest, WiFiServicePostReady);
  FRIEND_TEST(MetricsTest, WiFiServicePostReadyEAP);
  FRIEND_TEST(WiFiMainTest, CurrentBSSChangedUpdateServiceEndpoint);
  FRIEND_TEST(WiFiServiceTest, AutoConnect);
  FRIEND_TEST(WiFiServiceTest, ClearWriteOnlyDerivedProperty);  // passphrase_
  FRIEND_TEST(WiFiServiceTest, ComputeCipher8021x);
  FRIEND_TEST(WiFiServiceTest, ConnectTask8021x);
  FRIEND_TEST(WiFiServiceTest, ConnectTaskDynamicWEP);
  FRIEND_TEST(WiFiServiceTest, ConnectTaskPSK);
  FRIEND_TEST(WiFiServiceTest, ConnectTaskRawPMK);
  FRIEND_TEST(WiFiServiceTest, ConnectTaskWEP);
  FRIEND_TEST(WiFiServiceTest, ConnectTaskFT);
  FRIEND_TEST(WiFiServiceTest, GetTethering);
  FRIEND_TEST(WiFiServiceTest, IsAutoConnectable);
  FRIEND_TEST(WiFiServiceTest, LoadHidden);
  FRIEND_TEST(WiFiServiceTest, SetPassphraseForNonPassphraseService);
  FRIEND_TEST(WiFiServiceTest, LoadAndUnloadPassphrase);
  FRIEND_TEST(WiFiServiceTest, LoadPassphraseClearCredentials);
  FRIEND_TEST(WiFiServiceTest, SetPassphraseResetHasEverConnected);
  FRIEND_TEST(WiFiServiceTest, SetPassphraseRemovesCachedCredentials);
  FRIEND_TEST(WiFiServiceTest, SignalToStrength);  // SignalToStrength
  FRIEND_TEST(WiFiServiceTest, SuspectedCredentialFailure);
  FRIEND_TEST(WiFiServiceTest, UpdateSecurity);  // SetEAPKeyManagement
  FRIEND_TEST(WiFiServiceTest, ChooseDevice);

  static const char kAutoConnNoEndpoint[];
  static const char kAnyDeviceAddress[];
  static const int kSuspectedCredentialFailureThreshold;

  // Override the base clase implementation, because we need to allow
  // arguments that aren't base class methods.
  void HelpRegisterConstDerivedString(
      const std::string& name, std::string (WiFiService::*get)(Error* error));
  void HelpRegisterDerivedString(
      const std::string& name,
      std::string (WiFiService::*get)(Error* error),
      bool (WiFiService::*set)(const std::string& value, Error* error));
  void HelpRegisterWriteOnlyDerivedString(
      const std::string& name,
      bool (WiFiService::*set)(const std::string& value, Error* error),
      void (WiFiService::*clear)(Error* error),
      const std::string* default_value);
  void HelpRegisterDerivedUint16(const std::string& name,
                                 uint16_t (WiFiService::*get)(Error* error),
                                 bool (WiFiService::*set)(const uint16_t& value,
                                                          Error* error),
                                 void (WiFiService::*clear)(Error* error));

  RpcIdentifier GetDeviceRpcId(Error* error) const override;

  void ClearPassphrase(Error* error);
  void UpdateConnectable();
  void UpdateFromEndpoints();
  void UpdateSecurity();

  static CryptoAlgorithm ComputeCipher8021x(
      const std::set<WiFiEndpointConstRefPtr>& endpoints);
  static void ValidateWEPPassphrase(const std::string& passphrase,
                                    Error* error);
  static void ValidateWPAPassphrase(const std::string& passphrase,
                                    Error* error);
  static void ParseWEPPassphrase(const std::string& passphrase,
                                 int* key_index,
                                 std::vector<uint8_t>* password_bytes,
                                 Error* error);
  static void ParseWPAPassphrase(const std::string& passphrase,
                                 std::vector<uint8_t>* passphrase_bytes,
                                 Error* error);
  static bool CheckWEPIsHex(const std::string& passphrase, Error* error);
  static bool CheckWEPKeyIndex(const std::string& passphrase, Error* error);
  static bool CheckWEPPrefix(const std::string& passphrase, Error* error);

  // Maps a signal value, in dBm, to a "strength" value, from
  // |Service::kStrengthMin| to |Service:kStrengthMax|.
  static uint8_t SignalToStrength(int16_t signal_dbm);

  // Create a default group name for this WiFi service.
  std::string GetDefaultStorageIdentifier() const;

  // Return the security of this service.  If visible, the security
  // reported from the representative endpoint is returned.  Otherwise
  // the configured security for the service is returned.
  std::string GetSecurity(Error* error);

  // Return the security class of this service.  If visible, the
  // security class of the representative endpoint is returned.
  // Otherwise the configured security class for the service is
  // returned.
  //
  // See also: ComputeSecurityClass.
  std::string GetSecurityClass(Error* error);

  // Profile data for a WPA/RSN service can be stored under a number of
  // different security types.  These functions create different storage
  // property lists based on whether they are saved with their generic
  // "psk" name or if they use the (legacy) specific "wpa" or "rsn" names.
  KeyValueStore GetStorageProperties() const;

  // Called from DBus and during Load to validate and apply a passphrase for
  // this service.  If the passphrase is successfully changed, UpdateConnectable
  // and OnCredentialChange are both called and the method returns true.  This
  // method will return false if the passphrase cannot be set.  If the
  // passphrase is already set to the value of |passphrase|, this method will
  // return false.  If it is due to an error, |error| will be populated with the
  // appropriate information.
  bool SetPassphrase(const std::string& passphrase, Error* error);

  // Called by SetPassphrase and LoadPassphrase to perform the check on a
  // passphrase change.  |passphrase| is the new passphrase to be used for the
  // service.  If the new passphrase is not different from the existing
  // passphrase, SetPassphraseInternal will return false.  |reason| signals how
  // the SetPassphraseInternal method was triggered.  If the method was called
  // from Load, the has_ever_connected flag will not be reset.  If the method
  // was called from SetPassphrase, has_ever_connected will be set to false.
  bool SetPassphraseInternal(const std::string& passphrase,
                             Service::UpdateCredentialsReason reason);

  // Select a WiFi device (e.g, for connecting a hidden service with no
  // endpoints).
  WiFiRefPtr ChooseDevice();

  void SetWiFi(const WiFiRefPtr& new_wifi);

  // Properties
  std::string passphrase_;
  bool need_passphrase_;
  // The current security mode. May be updated based on detected BSS.
  // TODO(b/157935328): consider factoring this out into a class, to hide some
  // of the overlap (but not identical) nature of Security and SecurityClass.
  std::string security_;
  // TODO(cmasone): see if the below can be pulled from the endpoint associated
  // with this service instead.
  const std::string mode_;
  bool hidden_ssid_;
  bool ft_enabled_;
  uint16_t frequency_;
  std::vector<uint16_t> frequency_list_;
  uint16_t physical_mode_;
  // The raw dBm signal strength from the associated endpoint.
  int16_t raw_signal_strength_;
  std::string hex_ssid_;
  std::string storage_identifier_;
  std::string bssid_;
  Stringmap vendor_information_;
  // The country code reported by the current endpoint.
  std::string country_code_;
  // If |security_| == kSecurity8021x, the crypto algorithm being used.
  // (Otherwise, crypto algorithm is implied by |security_|.)
  CryptoAlgorithm cipher_8021x_;

  // Track the number of consecutive times our current credentials have
  // been called into question.
  int suspected_credential_failures_;

  // Track whether or not we've warned about large signal values.
  // Used to avoid spamming the log.
  static bool logged_signal_warning;

  WiFiRefPtr wifi_;
  std::set<WiFiEndpointConstRefPtr> endpoints_;
  WiFiEndpointConstRefPtr current_endpoint_;
  const std::vector<uint8_t> ssid_;
  // Flag indicating if service disconnect is initiated by user for
  // connecting to other service.
  bool expecting_disconnect_;
  // The background scan configuration parameters.
  std::string bgscan_string_;
  std::unique_ptr<CertificateFile> certificate_file_;
  // Bare pointer is safe because WiFi service instances are owned by
  // the WiFiProvider and are guaranteed to be deallocated by the time
  // the WiFiProvider is.
  WiFiProvider* provider_;

  DISALLOW_COPY_AND_ASSIGN(WiFiService);
};

}  // namespace shill

#endif  // SHILL_WIFI_WIFI_SERVICE_H_
