178 lines
5.6 KiB
C++
178 lines
5.6 KiB
C++
//
|
|
// Copyright (C) 2015 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#include "shill/wifi/tdls_manager.h"
|
|
|
|
#include <base/bind.h>
|
|
#if defined(__ANDROID__)
|
|
#include <dbus/service_constants.h>
|
|
#else
|
|
#include <chromeos/dbus/service_constants.h>
|
|
#endif // __ANDROID__
|
|
|
|
#include "shill/error.h"
|
|
#include "shill/event_dispatcher.h"
|
|
#include "shill/logging.h"
|
|
#include "shill/supplicant/supplicant_interface_proxy_interface.h"
|
|
#include "shill/supplicant/wpa_supplicant.h"
|
|
|
|
using base::Bind;
|
|
using std::string;
|
|
|
|
namespace shill {
|
|
|
|
namespace Logging {
|
|
static auto kModuleLogScope = ScopeLogger::kWiFi;
|
|
static string ObjectID(const TDLSManager* c) {
|
|
return "(" + c->interface_name() + "-tdlsmanager)";
|
|
}
|
|
}
|
|
|
|
const int TDLSManager::kPeerDiscoveryCleanupTimeoutSeconds = 30;
|
|
|
|
TDLSManager::TDLSManager(
|
|
EventDispatcher* dispatcher,
|
|
SupplicantInterfaceProxyInterface* supplicant_interface_proxy,
|
|
const string& interface_name)
|
|
: dispatcher_(dispatcher),
|
|
supplicant_interface_proxy_(supplicant_interface_proxy),
|
|
interface_name_(interface_name) {}
|
|
|
|
TDLSManager::~TDLSManager() {}
|
|
|
|
string TDLSManager::PerformOperation(const string& peer_mac_address,
|
|
const string& operation,
|
|
Error* error) {
|
|
CHECK(supplicant_interface_proxy_);
|
|
|
|
SLOG(this, 2) << "Processing TDLS command: " << operation
|
|
<< " for peer " << peer_mac_address;
|
|
|
|
bool success = false;
|
|
if (operation == kTDLSDiscoverOperation) {
|
|
success = DiscoverPeer(peer_mac_address);
|
|
} else if (operation == kTDLSSetupOperation) {
|
|
success = SetupPeer(peer_mac_address);
|
|
} else if (operation == kTDLSStatusOperation) {
|
|
string supplicant_status = PeerStatus(peer_mac_address);
|
|
SLOG(this, 2) << "TDLS status returned: " << supplicant_status;
|
|
if (!supplicant_status.empty()) {
|
|
if (supplicant_status == WPASupplicant::kTDLSStateConnected) {
|
|
return kTDLSConnectedState;
|
|
} else if (supplicant_status == WPASupplicant::kTDLSStateDisabled) {
|
|
return kTDLSDisabledState;
|
|
} else if (supplicant_status ==
|
|
WPASupplicant::kTDLSStatePeerDoesNotExist) {
|
|
if (CheckDiscoveryState(peer_mac_address) ==
|
|
PeerDiscoveryState::kResponseReceived) {
|
|
return kTDLSDisconnectedState;
|
|
} else {
|
|
return kTDLSNonexistentState;
|
|
}
|
|
} else if (supplicant_status ==
|
|
WPASupplicant::kTDLSStatePeerNotConnected) {
|
|
return kTDLSDisconnectedState;
|
|
} else {
|
|
return kTDLSUnknownState;
|
|
}
|
|
}
|
|
} else if (operation == kTDLSTeardownOperation) {
|
|
success = TearDownPeer(peer_mac_address);
|
|
} else {
|
|
error->Populate(Error::kInvalidArguments, "Unknown operation");
|
|
return "";
|
|
}
|
|
|
|
if (!success) {
|
|
Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
|
|
"TDLS operation failed");
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
void TDLSManager::OnDiscoverResponseReceived(const string& peer_mac_address) {
|
|
if (CheckDiscoveryState(peer_mac_address) ==
|
|
PeerDiscoveryState::kRequestSent) {
|
|
peer_discovery_state_[peer_mac_address] =
|
|
PeerDiscoveryState::kResponseReceived;
|
|
}
|
|
}
|
|
|
|
bool TDLSManager::DiscoverPeer(const string& peer_mac_address) {
|
|
if (!supplicant_interface_proxy_->TDLSDiscover(peer_mac_address)) {
|
|
LOG(ERROR) << "Failed to perform TDLS discover";
|
|
return false;
|
|
}
|
|
peer_discovery_state_[peer_mac_address] = PeerDiscoveryState::kRequestSent;
|
|
StartPeerDiscoveryCleanupTimer();
|
|
return true;
|
|
}
|
|
|
|
bool TDLSManager::SetupPeer(const string& peer_mac_address) {
|
|
if (!supplicant_interface_proxy_->TDLSSetup(peer_mac_address)) {
|
|
LOG(ERROR) << "Failed to perform TDLS setup";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TDLSManager::TearDownPeer(const string& peer_mac_address) {
|
|
if (!supplicant_interface_proxy_->TDLSTeardown(peer_mac_address)) {
|
|
LOG(ERROR) << "Failed to perform TDLS teardown";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
string TDLSManager::PeerStatus(const string& peer_mac_address) {
|
|
string status;
|
|
if (!supplicant_interface_proxy_->TDLSStatus(peer_mac_address, &status)) {
|
|
LOG(ERROR) << "Failed to perform TDLS status";
|
|
return "";
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void TDLSManager::StartPeerDiscoveryCleanupTimer() {
|
|
if (!peer_discovery_cleanup_callback_.IsCancelled()) {
|
|
LOG(INFO) << __func__ << " TDLS cleanup timer restarted.";
|
|
} else {
|
|
LOG(INFO) << __func__ << " TDLS cleanup timer started.";
|
|
}
|
|
peer_discovery_cleanup_callback_.Reset(
|
|
Bind(&TDLSManager::PeerDiscoveryCleanup, base::Unretained(this)));
|
|
dispatcher_->PostDelayedTask(peer_discovery_cleanup_callback_.callback(),
|
|
kPeerDiscoveryCleanupTimeoutSeconds * 1000);
|
|
}
|
|
|
|
void TDLSManager::PeerDiscoveryCleanup() {
|
|
LOG(INFO) << __func__ << " TDLS peer discovery map cleared.";
|
|
peer_discovery_state_.clear();
|
|
}
|
|
|
|
TDLSManager::PeerDiscoveryState TDLSManager::CheckDiscoveryState(
|
|
const string& peer_mac_address) {
|
|
auto iter = peer_discovery_state_.find(peer_mac_address);
|
|
if (iter == peer_discovery_state_.end()) {
|
|
return PeerDiscoveryState::kNone;
|
|
}
|
|
|
|
return iter->second;
|
|
}
|
|
|
|
|
|
} // namespace shill.
|