tdls_manager.cc revision 289a5a5e18bb1a676b3dfce111af4c2c00c7776e
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 32using base::Bind; 33using std::string; 34 35namespace shill { 36 37namespace Logging { 38static auto kModuleLogScope = ScopeLogger::kWiFi; 39static string ObjectID(const TDLSManager* c) { 40 return "(" + c->interface_name() + "-tdlsmanager)"; 41} 42} 43 44const int TDLSManager::kPeerDiscoveryCleanupTimeoutSeconds = 30; 45 46TDLSManager::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 54TDLSManager::~TDLSManager() {} 55 56string 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 107void 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 115bool 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 125bool 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 133bool 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 141string 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 150void 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 162void TDLSManager::PeerDiscoveryCleanup() { 163 LOG(INFO) << __func__ << " TDLS peer discovery map cleared."; 164 peer_discovery_state_.clear(); 165} 166 167TDLSManager::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