Home | History | Annotate | Download | only in wifi
      1 //
      2 // Copyright (C) 2015 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/wifi/tdls_manager.h"
     18 
     19 #include <base/bind.h>
     20 #if defined(__ANDROID__)
     21 #include <dbus/service_constants.h>
     22 #else
     23 #include <chromeos/dbus/service_constants.h>
     24 #endif  // __ANDROID__
     25 
     26 #include "shill/error.h"
     27 #include "shill/event_dispatcher.h"
     28 #include "shill/logging.h"
     29 #include "shill/supplicant/supplicant_interface_proxy_interface.h"
     30 #include "shill/supplicant/wpa_supplicant.h"
     31 
     32 using base::Bind;
     33 using std::string;
     34 
     35 namespace shill {
     36 
     37 namespace Logging {
     38 static auto kModuleLogScope = ScopeLogger::kWiFi;
     39 static string ObjectID(const TDLSManager* c) {
     40   return "(" + c->interface_name() + "-tdlsmanager)";
     41 }
     42 }
     43 
     44 const int TDLSManager::kPeerDiscoveryCleanupTimeoutSeconds = 30;
     45 
     46 TDLSManager::TDLSManager(
     47     EventDispatcher* dispatcher,
     48     SupplicantInterfaceProxyInterface* supplicant_interface_proxy,
     49     const string& interface_name)
     50     : dispatcher_(dispatcher),
     51       supplicant_interface_proxy_(supplicant_interface_proxy),
     52       interface_name_(interface_name) {}
     53 
     54 TDLSManager::~TDLSManager() {}
     55 
     56 string TDLSManager::PerformOperation(const string& peer_mac_address,
     57                                      const string& operation,
     58                                      Error* error) {
     59   CHECK(supplicant_interface_proxy_);
     60 
     61   SLOG(this, 2) << "Processing TDLS command: " << operation
     62                 << " for peer " << peer_mac_address;
     63 
     64   bool success = false;
     65   if (operation == kTDLSDiscoverOperation) {
     66     success = DiscoverPeer(peer_mac_address);
     67   } else if (operation == kTDLSSetupOperation) {
     68     success = SetupPeer(peer_mac_address);
     69   } else if (operation == kTDLSStatusOperation) {
     70     string supplicant_status = PeerStatus(peer_mac_address);
     71     SLOG(this, 2) << "TDLS status returned: " << supplicant_status;
     72     if (!supplicant_status.empty()) {
     73       if (supplicant_status == WPASupplicant::kTDLSStateConnected) {
     74         return kTDLSConnectedState;
     75       } else if (supplicant_status == WPASupplicant::kTDLSStateDisabled) {
     76         return kTDLSDisabledState;
     77       } else if (supplicant_status ==
     78                  WPASupplicant::kTDLSStatePeerDoesNotExist) {
     79         if (CheckDiscoveryState(peer_mac_address) ==
     80             PeerDiscoveryState::kResponseReceived) {
     81           return kTDLSDisconnectedState;
     82         } else {
     83           return kTDLSNonexistentState;
     84         }
     85       } else if (supplicant_status ==
     86                  WPASupplicant::kTDLSStatePeerNotConnected) {
     87         return kTDLSDisconnectedState;
     88       } else {
     89         return kTDLSUnknownState;
     90       }
     91     }
     92   } else if (operation == kTDLSTeardownOperation) {
     93     success = TearDownPeer(peer_mac_address);
     94   } else {
     95     error->Populate(Error::kInvalidArguments, "Unknown operation");
     96     return "";
     97   }
     98 
     99   if (!success) {
    100     Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
    101                           "TDLS operation failed");
    102   }
    103 
    104   return "";
    105 }
    106 
    107 void TDLSManager::OnDiscoverResponseReceived(const string& peer_mac_address) {
    108   if (CheckDiscoveryState(peer_mac_address) ==
    109       PeerDiscoveryState::kRequestSent) {
    110     peer_discovery_state_[peer_mac_address] =
    111         PeerDiscoveryState::kResponseReceived;
    112   }
    113 }
    114 
    115 bool TDLSManager::DiscoverPeer(const string& peer_mac_address) {
    116   if (!supplicant_interface_proxy_->TDLSDiscover(peer_mac_address)) {
    117     LOG(ERROR) << "Failed to perform TDLS discover";
    118     return false;
    119   }
    120   peer_discovery_state_[peer_mac_address] = PeerDiscoveryState::kRequestSent;
    121   StartPeerDiscoveryCleanupTimer();
    122   return true;
    123 }
    124 
    125 bool TDLSManager::SetupPeer(const string& peer_mac_address) {
    126   if (!supplicant_interface_proxy_->TDLSSetup(peer_mac_address)) {
    127     LOG(ERROR) << "Failed to perform TDLS setup";
    128     return false;
    129   }
    130   return true;
    131 }
    132 
    133 bool TDLSManager::TearDownPeer(const string& peer_mac_address) {
    134   if (!supplicant_interface_proxy_->TDLSTeardown(peer_mac_address)) {
    135     LOG(ERROR) << "Failed to perform TDLS teardown";
    136     return false;
    137   }
    138   return true;
    139 }
    140 
    141 string TDLSManager::PeerStatus(const string& peer_mac_address) {
    142   string status;
    143   if (!supplicant_interface_proxy_->TDLSStatus(peer_mac_address, &status)) {
    144     LOG(ERROR) << "Failed to perform TDLS status";
    145     return "";
    146   }
    147   return status;
    148 }
    149 
    150 void TDLSManager::StartPeerDiscoveryCleanupTimer() {
    151   if (!peer_discovery_cleanup_callback_.IsCancelled()) {
    152     LOG(INFO) << __func__ << " TDLS cleanup timer restarted.";
    153   } else {
    154     LOG(INFO) << __func__ << " TDLS cleanup timer started.";
    155   }
    156   peer_discovery_cleanup_callback_.Reset(
    157       Bind(&TDLSManager::PeerDiscoveryCleanup, base::Unretained(this)));
    158   dispatcher_->PostDelayedTask(peer_discovery_cleanup_callback_.callback(),
    159                                kPeerDiscoveryCleanupTimeoutSeconds * 1000);
    160 }
    161 
    162 void TDLSManager::PeerDiscoveryCleanup() {
    163   LOG(INFO) << __func__ << " TDLS peer discovery map cleared.";
    164   peer_discovery_state_.clear();
    165 }
    166 
    167 TDLSManager::PeerDiscoveryState TDLSManager::CheckDiscoveryState(
    168     const string& peer_mac_address) {
    169   auto iter = peer_discovery_state_.find(peer_mac_address);
    170   if (iter == peer_discovery_state_.end()) {
    171     return PeerDiscoveryState::kNone;
    172   }
    173 
    174   return iter->second;
    175 }
    176 
    177 
    178 }  // namespace shill.
    179