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