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;
ObjectID(const TDLSManager * c)39 static string ObjectID(const TDLSManager* c) {
40 return "(" + c->interface_name() + "-tdlsmanager)";
41 }
42 }
43
44 const int TDLSManager::kPeerDiscoveryCleanupTimeoutSeconds = 30;
45
TDLSManager(EventDispatcher * dispatcher,SupplicantInterfaceProxyInterface * supplicant_interface_proxy,const string & interface_name)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
~TDLSManager()54 TDLSManager::~TDLSManager() {}
55
PerformOperation(const string & peer_mac_address,const string & operation,Error * error)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
OnDiscoverResponseReceived(const string & peer_mac_address)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
DiscoverPeer(const string & peer_mac_address)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
SetupPeer(const string & peer_mac_address)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
TearDownPeer(const string & peer_mac_address)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
PeerStatus(const string & peer_mac_address)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
StartPeerDiscoveryCleanupTimer()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
PeerDiscoveryCleanup()162 void TDLSManager::PeerDiscoveryCleanup() {
163 LOG(INFO) << __func__ << " TDLS peer discovery map cleared.";
164 peer_discovery_state_.clear();
165 }
166
CheckDiscoveryState(const string & peer_mac_address)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