1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 The Android Open Source Project 3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License. 6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at 7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software 11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and 14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License. 15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 1699c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan 17c3d707d1ae4198d5538ff4deccd729a83f1bc805Ben Chan#include "shill/wimax/wimax.h" 1899c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan 198a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko#include <string> 208a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko 21912f0de92ca103568821e20412b7dc2529494f98Darin Petkov#include <base/bind.h> 22a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_util.h> 23a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/stringprintf.h> 24912f0de92ca103568821e20412b7dc2529494f98Darin Petkov 25608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu#include "shill/control_interface.h" 2625665aa52da9f6e08a23fc462b09c2ae63a8a5f2Darin Petkov#include "shill/key_value_store.h" 27b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h" 28912f0de92ca103568821e20412b7dc2529494f98Darin Petkov#include "shill/manager.h" 29c3d707d1ae4198d5538ff4deccd729a83f1bc805Ben Chan#include "shill/wimax/wimax_device_proxy_interface.h" 30c3d707d1ae4198d5538ff4deccd729a83f1bc805Ben Chan#include "shill/wimax/wimax_service.h" 31b72b62ec23d13c8e84a1499a04231b79d4bd74bbDarin Petkov 32912f0de92ca103568821e20412b7dc2529494f98Darin Petkovusing base::Bind; 33d1cd79736d7a9969c966a76a5906ea408bad3731Darin Petkovusing std::set; 3499c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chanusing std::string; 3599c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan 3699c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Channamespace shill { 3799c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan 38c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinnamespace Logging { 39c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinstatic auto kModuleLogScope = ScopeLogger::kWiMax; 4093d817916f4cac344b6985c867a85f65711a1486Paul Stewartstatic string ObjectID(WiMax* w) { return w->GetRpcIdentifier(); } 41c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein} 42c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein 4392ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Channamespace { 4492ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan 4593d817916f4cac344b6985c867a85f65711a1486Paul Stewartconst char* DeviceStatusToString(wimax_manager::DeviceStatus status) { 4692ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan switch (status) { 4792ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan case wimax_manager::kDeviceStatusUninitialized: 4892ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan return "Uninitialized"; 4992ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan case wimax_manager::kDeviceStatusDisabled: 5092ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan return "Disabled"; 5192ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan case wimax_manager::kDeviceStatusReady: 5292ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan return "Ready"; 5392ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan case wimax_manager::kDeviceStatusScanning: 5492ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan return "Scanning"; 5592ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan case wimax_manager::kDeviceStatusConnecting: 5692ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan return "Connecting"; 5792ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan case wimax_manager::kDeviceStatusConnected: 5892ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan return "Connected"; 5992ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan default: 6092ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan return "Unknown"; 6192ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan } 6292ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan} 6392ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan 6492ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan} // namespace 6592ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan 663a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkovconst int WiMax::kDefaultConnectTimeoutSeconds = 60; 673a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkovconst int WiMax::kDefaultRPCTimeoutSeconds = 30; 68912f0de92ca103568821e20412b7dc2529494f98Darin Petkov 6993d817916f4cac344b6985c867a85f65711a1486Paul StewartWiMax::WiMax(ControlInterface* control, 7093d817916f4cac344b6985c867a85f65711a1486Paul Stewart EventDispatcher* dispatcher, 7193d817916f4cac344b6985c867a85f65711a1486Paul Stewart Metrics* metrics, 7293d817916f4cac344b6985c867a85f65711a1486Paul Stewart Manager* manager, 7393d817916f4cac344b6985c867a85f65711a1486Paul Stewart const string& link_name, 7493d817916f4cac344b6985c867a85f65711a1486Paul Stewart const string& address, 75b72b62ec23d13c8e84a1499a04231b79d4bd74bbDarin Petkov int interface_index, 7693d817916f4cac344b6985c867a85f65711a1486Paul Stewart const RpcIdentifier& path) 774e64d2d72eed1947ab1d15e6ce25a47c37a9e10cBen Chan : Device(control, dispatcher, metrics, manager, link_name, address, 78b72b62ec23d13c8e84a1499a04231b79d4bd74bbDarin Petkov interface_index, Technology::kWiMax), 79b72b62ec23d13c8e84a1499a04231b79d4bd74bbDarin Petkov path_(path), 803a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov weak_ptr_factory_(this), 819893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov scanning_(false), 823a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov status_(wimax_manager::kDeviceStatusUninitialized), 833a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov connect_timeout_seconds_(kDefaultConnectTimeoutSeconds) { 84b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov LOG(INFO) << "WiMAX device created: " << link_name << " @ " << path; 8593d817916f4cac344b6985c867a85f65711a1486Paul Stewart PropertyStore* store = mutable_store(); 864276ccab7a3bdf1c2e2e69cf79b859733d7404a0Ben Chan store->RegisterConstBool(kScanningProperty, &scanning_); 87b72b62ec23d13c8e84a1499a04231b79d4bd74bbDarin Petkov} 8899c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan 89b72b62ec23d13c8e84a1499a04231b79d4bd74bbDarin PetkovWiMax::~WiMax() { 90b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov LOG(INFO) << "WiMAX device destroyed: " << link_name(); 91b72b62ec23d13c8e84a1499a04231b79d4bd74bbDarin Petkov} 9299c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan 9393d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::Start(Error* error, const EnabledStateChangedCallback& callback) { 94c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 959893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov scanning_ = false; 96608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu proxy_.reset(control_interface()->CreateWiMaxDeviceProxy(path_)); 979893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov proxy_->set_networks_changed_callback( 989893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov Bind(&WiMax::OnNetworksChanged, Unretained(this))); 998ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov proxy_->set_status_changed_callback( 1008ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov Bind(&WiMax::OnStatusChanged, Unretained(this))); 101912f0de92ca103568821e20412b7dc2529494f98Darin Petkov proxy_->Enable( 1023a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov error, Bind(&WiMax::OnEnableComplete, this, callback), 1033a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov kDefaultRPCTimeoutSeconds * 1000); 10499c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan} 10599c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan 10693d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::Stop(Error* error, const EnabledStateChangedCallback& callback) { 107c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 1083a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov StopConnectTimeout(); 1093a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov if (pending_service_) { 1103a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov pending_service_->SetState(Service::kStateIdle); 11153cc894f1ca677f930da7fce1564db44a7b02791Ben Chan pending_service_ = nullptr; 1123a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov } 113c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov if (selected_service()) { 114c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov Error error; 115c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov DisconnectFrom(selected_service(), &error); 116c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov } 117b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov scanning_ = false; 118d1cd79736d7a9969c966a76a5906ea408bad3731Darin Petkov networks_.clear(); 119c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov manager()->wimax_provider()->OnNetworksChanged(); 120b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov if (proxy_.get()) { 121b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov proxy_->Disable( 122b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov error, Bind(&WiMax::OnDisableComplete, this, callback), 1233a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov kDefaultRPCTimeoutSeconds * 1000); 124b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov } else { 125b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov OnDisableComplete(callback, Error()); 126b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov } 12799c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan} 12899c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan 12993d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::Scan(ScanType /*scan_type*/, Error* error, 13093d817916f4cac344b6985c867a85f65711a1486Paul Stewart const string& /*reason*/) { 131c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 1329893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov if (scanning_) { 1339893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov Error::PopulateAndLog( 13434f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart FROM_HERE, error, Error::kInProgress, "Scan already in progress."); 1359893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov return; 1369893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov } 1379893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov scanning_ = true; 1389893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov proxy_->ScanNetworks( 1393a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov error, Bind(&WiMax::OnScanNetworksComplete, this), 1403a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov kDefaultRPCTimeoutSeconds * 1000); 1419893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov if (error->IsFailure()) { 1429893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov OnScanNetworksComplete(*error); 1439893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov } 1449893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov} 1459893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov 14693d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::ConnectTo(const WiMaxServiceRefPtr& service, Error* error) { 147c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(" << service->GetStorageIdentifier() << ")"; 1489893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov if (pending_service_) { 1499893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov Error::PopulateAndLog( 15034f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart FROM_HERE, error, Error::kInProgress, 1519893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov base::StringPrintf( 152457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov "Pending connect to service %s, ignoring connect request to %s.", 153457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov pending_service_->unique_name().c_str(), 154c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov service->GetStorageIdentifier().c_str())); 1559893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov return; 1569893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov } 1579893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov service->SetState(Service::kStateAssociating); 1589893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov pending_service_ = service; 1594e5c1310a1c70445a473653bd37d06604c5d5f47Ben Chan 1603a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov // We use the RPC device status to determine the outcome of the connect 1613a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov // operation by listening for status updates in OnStatusChanged. A transition 1623a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov // to Connected means success. A transition to Connecting and then to a status 1633a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov // different than Connected means failure. Also, schedule a connect timeout to 1643a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov // guard against the RPC device never transitioning to a Connecting or a 1653a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov // Connected state. 1663a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov status_ = wimax_manager::kDeviceStatusUninitialized; 1673a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov StartConnectTimeout(); 1683a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov 16925665aa52da9f6e08a23fc462b09c2ae63a8a5f2Darin Petkov KeyValueStore parameters; 1704e5c1310a1c70445a473653bd37d06604c5d5f47Ben Chan service->GetConnectParameters(¶meters); 171912f0de92ca103568821e20412b7dc2529494f98Darin Petkov proxy_->Connect( 1724e5c1310a1c70445a473653bd37d06604c5d5f47Ben Chan service->GetNetworkObjectPath(), parameters, 1733a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov error, Bind(&WiMax::OnConnectComplete, this), 1743a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov kDefaultRPCTimeoutSeconds * 1000); 1759893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov if (error->IsFailure()) { 1769893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov OnConnectComplete(*error); 1779893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov } 17899c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan} 17999c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan 18093d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::DisconnectFrom(const ServiceRefPtr& service, Error* error) { 181c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 1829893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov if (pending_service_) { 1839893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov Error::PopulateAndLog( 18434f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart FROM_HERE, error, Error::kInProgress, 1859893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov base::StringPrintf( 186457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov "Pending connect to service %s, " 187457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov "ignoring disconnect request from %s.", 188457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov pending_service_->unique_name().c_str(), 189c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov service->GetStorageIdentifier().c_str())); 1909893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov return; 1919893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov } 1929893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov if (selected_service() && service != selected_service()) { 1939893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov Error::PopulateAndLog( 19434f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart FROM_HERE, error, Error::kNotConnected, 1959893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov base::StringPrintf( 196457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov "Current service is %s, ignoring disconnect request from %s.", 197457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov selected_service()->unique_name().c_str(), 198c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov service->GetStorageIdentifier().c_str())); 1999893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov return; 2009893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov } 201c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov DropConnection(); 202912f0de92ca103568821e20412b7dc2529494f98Darin Petkov proxy_->Disconnect( 2033a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov error, Bind(&WiMax::OnDisconnectComplete, this), 2043a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov kDefaultRPCTimeoutSeconds * 1000); 2059893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov if (error->IsFailure()) { 206c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov OnDisconnectComplete(*error); 207c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov } 208c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov} 209c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov 2106b9b2e18088f22b79ea5d87f575b67632fb5770aDarin Petkovbool WiMax::IsIdle() const { 2116b9b2e18088f22b79ea5d87f575b67632fb5770aDarin Petkov return !pending_service_ && !selected_service(); 2126b9b2e18088f22b79ea5d87f575b67632fb5770aDarin Petkov} 2136b9b2e18088f22b79ea5d87f575b67632fb5770aDarin Petkov 21493d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::OnServiceStopped(const WiMaxServiceRefPtr& service) { 215c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 216c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov if (service == selected_service()) { 217c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov DropConnection(); 218c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov } 219c1e5273c8c52bb3e5c20364d5c172d57417d3c4cDarin Petkov if (service == pending_service_) { 22053cc894f1ca677f930da7fce1564db44a7b02791Ben Chan pending_service_ = nullptr; 2219893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov } 2229893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov} 2239893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov 224b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkovvoid WiMax::OnDeviceVanished() { 225b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov LOG(INFO) << "WiMAX device vanished: " << link_name(); 226b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov proxy_.reset(); 227b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov DropService(Service::kStateIdle); 228b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov // Disable the device. This will also clear any relevant properties such as 229b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov // the live network set. 230b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov SetEnabled(false); 231b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov} 232b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov 23393d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::OnScanNetworksComplete(const Error& /*error*/) { 234c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 2359893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov scanning_ = false; 2369893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov // The networks are updated when the NetworksChanged signal is received. 237912f0de92ca103568821e20412b7dc2529494f98Darin Petkov} 238912f0de92ca103568821e20412b7dc2529494f98Darin Petkov 23993d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::OnConnectComplete(const Error& error) { 240c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 2418ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov if (error.IsSuccess()) { 2428ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov // Nothing to do -- the connection process is resumed on the StatusChanged 2438ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov // signal. 2449893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov return; 2459893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov } 246b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov DropService(Service::kStateFailure); 247912f0de92ca103568821e20412b7dc2529494f98Darin Petkov} 248912f0de92ca103568821e20412b7dc2529494f98Darin Petkov 24993d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::OnDisconnectComplete(const Error& /*error*/) { 250c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 251912f0de92ca103568821e20412b7dc2529494f98Darin Petkov} 252912f0de92ca103568821e20412b7dc2529494f98Darin Petkov 25393d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::OnEnableComplete(const EnabledStateChangedCallback& callback, 25493d817916f4cac344b6985c867a85f65711a1486Paul Stewart const Error& error) { 255c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 256912f0de92ca103568821e20412b7dc2529494f98Darin Petkov if (error.IsFailure()) { 257912f0de92ca103568821e20412b7dc2529494f98Darin Petkov proxy_.reset(); 258912f0de92ca103568821e20412b7dc2529494f98Darin Petkov } else { 25959f2d69a15abf0a1ceb4eff58adcf815f2a0ff92Darin Petkov LOG(INFO) << "WiMAX device " << link_name() << " enabled."; 26059f2d69a15abf0a1ceb4eff58adcf815f2a0ff92Darin Petkov // Updates the live networks based on the current WiMaxManager.Device 26159f2d69a15abf0a1ceb4eff58adcf815f2a0ff92Darin Petkov // networks. The RPC device will signal when the network set changes. 2629893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov Error e; 26359f2d69a15abf0a1ceb4eff58adcf815f2a0ff92Darin Petkov OnNetworksChanged(proxy_->Networks(&e)); 264912f0de92ca103568821e20412b7dc2529494f98Darin Petkov } 265912f0de92ca103568821e20412b7dc2529494f98Darin Petkov callback.Run(error); 266912f0de92ca103568821e20412b7dc2529494f98Darin Petkov} 267912f0de92ca103568821e20412b7dc2529494f98Darin Petkov 26893d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::OnDisableComplete(const EnabledStateChangedCallback& callback, 26993d817916f4cac344b6985c867a85f65711a1486Paul Stewart const Error& error) { 270b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov LOG(INFO) << "WiMAX device " << link_name() << " disabled."; 2719893d9c59f596e621463c8e97bb3933f8fa7edf6Darin Petkov proxy_.reset(); 272912f0de92ca103568821e20412b7dc2529494f98Darin Petkov callback.Run(error); 27399c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan} 27499c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan 27593d817916f4cac344b6985c867a85f65711a1486Paul Stewartvoid WiMax::OnNetworksChanged(const RpcIdentifiers& networks) { 276c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 277c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov networks_.clear(); 278c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov networks_.insert(networks.begin(), networks.end()); 279c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov manager()->wimax_provider()->OnNetworksChanged(); 280d1cd79736d7a9969c966a76a5906ea408bad3731Darin Petkov} 281d1cd79736d7a9969c966a76a5906ea408bad3731Darin Petkov 2828ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkovvoid WiMax::OnStatusChanged(wimax_manager::DeviceStatus status) { 283c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "WiMAX device " << link_name() 284c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << " status: " << DeviceStatusToString(status); 2853a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov wimax_manager::DeviceStatus old_status = status_; 2863a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov status_ = status; 2878ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov switch (status) { 2888ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov case wimax_manager::kDeviceStatusConnected: 2898ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov if (!pending_service_) { 2908ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov LOG(WARNING) << "Unexpected status change; ignored."; 2918ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov return; 2928ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov } 2933a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov // Stops the connect timeout -- the DHCP provider has a separate timeout. 2943a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov StopConnectTimeout(); 2958ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov if (AcquireIPConfig()) { 296b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov LOG(INFO) << "WiMAX device " << link_name() << " connected to " 2978ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov << pending_service_->GetStorageIdentifier(); 2988ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov SelectService(pending_service_); 29953cc894f1ca677f930da7fce1564db44a7b02791Ben Chan pending_service_ = nullptr; 3008ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov SetServiceState(Service::kStateConfiguring); 3018ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov } else { 302b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov DropService(Service::kStateFailure); 3038ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov } 3048ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov break; 3058ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov case wimax_manager::kDeviceStatusConnecting: 3063a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov LOG(INFO) << "WiMAX device " << link_name() << " connecting..."; 3078ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov // Nothing to do. 3088ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov break; 3098ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov default: 3103a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov // We may receive a queued up status update (e.g., to Scanning) before 3113a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov // receiving the status update to Connecting, so be careful to fail the 3123a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov // service only on the right status transition. 3133a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov if (old_status == wimax_manager::kDeviceStatusConnecting || 3143a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov old_status == wimax_manager::kDeviceStatusConnected) { 3153a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov LOG(INFO) << "WiMAX device " << link_name() 31692ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan << " status: " << DeviceStatusToString(old_status) 31792ca56c5f434beaf2ba4270e5beb8c1c551e401dBen Chan << " -> " << DeviceStatusToString(status); 318e494e313d474b91b4b5a5f6ad783e7d0bc343dc8Ben Chan // TODO(benchan): Investigate a method to determine if the connection 319e494e313d474b91b4b5a5f6ad783e7d0bc343dc8Ben Chan // failure is due to incorrect EAP credentials and indicate that via 320e494e313d474b91b4b5a5f6ad783e7d0bc343dc8Ben Chan // Service::kFailureBadPassphrase (crosbug.com/p/16324). 3213a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov DropService(Service::kStateFailure); 3228ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov } 3238ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov break; 3248ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov } 3258ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov} 3268ea0eaf6fb42aa7d959a131e43ea1d06635d6da2Darin Petkov 327b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkovvoid WiMax::DropService(Service::ConnectState state) { 328c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ 329c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << "(" << Service::ConnectStateToString(state) << ")"; 3303a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov StopConnectTimeout(); 331b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov if (pending_service_) { 332b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov LOG(WARNING) << "Unable to initiate connection to: " 333b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov << pending_service_->GetStorageIdentifier(); 334b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov pending_service_->SetState(state); 33553cc894f1ca677f930da7fce1564db44a7b02791Ben Chan pending_service_ = nullptr; 336b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov } 337b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov if (selected_service()) { 338b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov LOG(WARNING) << "Service disconnected: " 339b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov << selected_service()->GetStorageIdentifier(); 340b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov selected_service()->SetState(state); 341b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov DropConnection(); 342b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov } 343b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov} 344b96a4515c8cc4432a87c70cbae2865e1445eb86eDarin Petkov 3453a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkovvoid WiMax::StartConnectTimeout() { 346c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 3473a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov if (IsConnectTimeoutStarted()) { 3483a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov return; 3493a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov } 3503a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov connect_timeout_callback_.Reset( 3513a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov Bind(&WiMax::OnConnectTimeout, weak_ptr_factory_.GetWeakPtr())); 3523a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov dispatcher()->PostDelayedTask( 3533a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov connect_timeout_callback_.callback(), connect_timeout_seconds_ * 1000); 3543a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov} 3553a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov 3563a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkovvoid WiMax::StopConnectTimeout() { 357c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 3583a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov connect_timeout_callback_.Cancel(); 3593a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov} 3603a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov 3613a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkovbool WiMax::IsConnectTimeoutStarted() const { 3623a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov return !connect_timeout_callback_.IsCancelled(); 3633a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov} 3643a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov 3653a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkovvoid WiMax::OnConnectTimeout() { 3663a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov LOG(ERROR) << "WiMAX device " << link_name() << ": connect timeout."; 3673a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov StopConnectTimeout(); 3683a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov DropService(Service::kStateFailure); 3693a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov} 3703a4100c44c9676f17829de5bcb23e883bd970ef7Darin Petkov 37199c8a4d2e6b81b1c395b2e1054111b29c20a5189Ben Chan} // namespace shill 372