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