1cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// Copyright 2015 The Android Open Source Project 2cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// 3cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// Licensed under the Apache License, Version 2.0 (the "License"); 4cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// you may not use this file except in compliance with the License. 5cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// You may obtain a copy of the License at 6cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// 7cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// http://www.apache.org/licenses/LICENSE-2.0 8cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// 9cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// Unless required by applicable law or agreed to in writing, software 10cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// distributed under the License is distributed on an "AS IS" BASIS, 11cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// See the License for the specific language governing permissions and 13cad20f0768bb6f2b5b647c7663e9bfc4e7ac3cb7Vitaly Buka// limitations under the License. 1458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 1558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka#include "buffet/shill_client.h" 1658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 1758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka#include <set> 1858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 1958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka#include <base/message_loop/message_loop.h> 2058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka#include <base/stl_util.h> 214170585fe75d99036883229081420f2972dd4ec1Alex Vakulenko#include <brillo/any.h> 224170585fe75d99036883229081420f2972dd4ec1Alex Vakulenko#include <brillo/errors/error.h> 2394f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko#include <brillo/variant_dictionary.h> 24786a90630feaa70b81e029edd4f6620e7ab3a211Peter Qiu#include <dbus/shill/dbus-constants.h> 25e2713aceb7b2fb9d2486cfdd983e44a1f8832ecbVitaly Buka#include <weave/enum_to_string.h> 2658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 273ef4fff987aa1da566262907f993cd3807c37a62Vitaly Buka#include "buffet/ap_manager_client.h" 28493f604eb1cb5bff0a4af86e6cb9e79983d543f6Vitaly Buka#include "buffet/socket_stream.h" 294f77153a124969f9bc48a498d37c943a82a82527Vitaly Buka#include "buffet/weave_error_conversion.h" 3058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 314170585fe75d99036883229081420f2972dd4ec1Alex Vakulenkousing brillo::Any; 324170585fe75d99036883229081420f2972dd4ec1Alex Vakulenkousing brillo::VariantDictionary; 3358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukausing dbus::ObjectPath; 3458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukausing org::chromium::flimflam::DeviceProxy; 3558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukausing org::chromium::flimflam::ServiceProxy; 3658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukausing std::map; 3758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukausing std::set; 3858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukausing std::string; 3958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukausing std::vector; 40e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenkousing weave::EnumToString; 41e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenkousing weave::provider::Network; 4258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 4358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukanamespace buffet { 4458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 4558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukanamespace { 4658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 4758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid IgnoreDetachEvent() {} 4858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 4958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukabool GetStateForService(ServiceProxy* service, string* state) { 5058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka CHECK(service) << "|service| was nullptr in GetStateForService()"; 5158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VariantDictionary properties; 5258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (!service->GetProperties(&properties, nullptr)) { 5358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(WARNING) << "Failed to read properties from service."; 5458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return false; 5558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 5658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka auto property_it = properties.find(shill::kStateProperty); 5758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (property_it == properties.end()) { 5858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(WARNING) << "No state found in service properties."; 5958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return false; 6058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 6158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka string new_state = property_it->second.TryGet<string>(); 6258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (new_state.empty()) { 6358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(WARNING) << "Invalid state value."; 6458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return false; 6558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 6658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka *state = new_state; 6758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return true; 6858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 6958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 70e32375bdf73d6e79a003a194e4c6931f38348520Alex VakulenkoNetwork::State ShillServiceStateToNetworkState(const string& state) { 7158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // TODO(wiley) What does "unconfigured" mean in a world with multiple sets 7258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // of WiFi credentials? 7358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // TODO(wiley) Detect disabled devices, update state appropriately. 7458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if ((state.compare(shill::kStateReady) == 0) || 7558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka (state.compare(shill::kStatePortal) == 0) || 7658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka (state.compare(shill::kStateOnline) == 0)) { 77be39e9339baa85af546344da40b0663a6aea1a97Alex Vakulenko return Network::State::kOnline; 7858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 7958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if ((state.compare(shill::kStateAssociation) == 0) || 8058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka (state.compare(shill::kStateConfiguration) == 0)) { 81e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko return Network::State::kConnecting; 8258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 8358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if ((state.compare(shill::kStateFailure) == 0) || 8458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka (state.compare(shill::kStateActivationFailure) == 0)) { 8558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // TODO(wiley) Get error information off the service object. 86be39e9339baa85af546344da40b0663a6aea1a97Alex Vakulenko return Network::State::kError; 8758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 8858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if ((state.compare(shill::kStateIdle) == 0) || 8958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka (state.compare(shill::kStateOffline) == 0) || 9058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka (state.compare(shill::kStateDisconnect) == 0)) { 91e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko return Network::State::kOffline; 9258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 9358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(WARNING) << "Unknown state found: '" << state << "'"; 94e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko return Network::State::kOffline; 9558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 9658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 9758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} // namespace 9858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 9958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly BukaShillClient::ShillClient(const scoped_refptr<dbus::Bus>& bus, 1000022b7523bca3bde23c0f982384f83a39791e88bAlex Vakulenko const set<string>& device_whitelist, 1010022b7523bca3bde23c0f982384f83a39791e88bAlex Vakulenko bool disable_xmpp) 10258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka : bus_{bus}, 103e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko manager_proxy_{bus_}, 1043ef4fff987aa1da566262907f993cd3807c37a62Vitaly Buka device_whitelist_{device_whitelist}, 1050022b7523bca3bde23c0f982384f83a39791e88bAlex Vakulenko disable_xmpp_{disable_xmpp}, 1063ef4fff987aa1da566262907f993cd3807c37a62Vitaly Buka ap_manager_client_{new ApManagerClient(bus)} { 10758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka manager_proxy_.RegisterPropertyChangedSignalHandler( 10858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka base::Bind(&ShillClient::OnManagerPropertyChange, 10958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka weak_factory_.GetWeakPtr()), 11058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka base::Bind(&ShillClient::OnManagerPropertyChangeRegistration, 11158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka weak_factory_.GetWeakPtr())); 11258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka auto owner_changed_cb = base::Bind(&ShillClient::OnShillServiceOwnerChange, 11358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka weak_factory_.GetWeakPtr()); 11458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka bus_->GetObjectProxy(shill::kFlimflamServiceName, ObjectPath{"/"}) 11558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka ->SetNameOwnerChangedCallback(owner_changed_cb); 1165d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka 1175d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka Init(); 11858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 11958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 1203ef4fff987aa1da566262907f993cd3807c37a62Vitaly BukaShillClient::~ShillClient() {} 1213ef4fff987aa1da566262907f993cd3807c37a62Vitaly Buka 12258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::Init() { 12358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(2) << "ShillClient::Init();"; 124e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko CleanupConnectingService(); 12558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka devices_.clear(); 126e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko connectivity_state_ = Network::State::kOffline; 12758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VariantDictionary properties; 12858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (!manager_proxy_.GetProperties(&properties, nullptr)) { 12958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(ERROR) << "Unable to get properties from Manager, waiting for " 13058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka "Manager to come back online."; 13158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 13258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 13358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka auto it = properties.find(shill::kDevicesProperty); 13458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka CHECK(it != properties.end()) << "shill should always publish a device list."; 13558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka OnManagerPropertyChange(shill::kDevicesProperty, it->second); 13658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 13758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 138e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenkovoid ShillClient::Connect(const string& ssid, 139e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko const string& passphrase, 14094f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko const weave::DoneCallback& callback) { 141685b2aeed879903b86448428dec1e88c9b6741b1Alex Vakulenko LOG(INFO) << "Connecting to WiFi network: " << ssid; 142e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (connecting_service_) { 143e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko weave::ErrorPtr error; 14434183c1b5b678a9726a955db9e05a361ed05eeacVitaly Buka weave::Error::AddTo(&error, FROM_HERE, "busy", 145e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko "Already connecting to WiFi network"); 146e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko base::MessageLoop::current()->PostTask( 14794f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko FROM_HERE, base::Bind(callback, base::Passed(&error))); 148e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko return; 1494f77153a124969f9bc48a498d37c943a82a82527Vitaly Buka } 150e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko CleanupConnectingService(); 15158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VariantDictionary service_properties; 15258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka service_properties[shill::kTypeProperty] = Any{string{shill::kTypeWifi}}; 15358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka service_properties[shill::kSSIDProperty] = Any{ssid}; 154e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (passphrase.empty()) { 155e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko service_properties[shill::kSecurityProperty] = Any{shill::kSecurityNone}; 156e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko } else { 157e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko service_properties[shill::kPassphraseProperty] = Any{passphrase}; 158e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko service_properties[shill::kSecurityProperty] = Any{shill::kSecurityPsk}; 159e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko } 16058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka service_properties[shill::kSaveCredentialsProperty] = Any{true}; 16158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka service_properties[shill::kAutoConnectProperty] = Any{true}; 16258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka ObjectPath service_path; 16394f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko brillo::ErrorPtr brillo_error; 16458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (!manager_proxy_.ConfigureService(service_properties, &service_path, 16594f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko &brillo_error) || 16694f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko !manager_proxy_.RequestScan(shill::kTypeWifi, &brillo_error)) { 167e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko weave::ErrorPtr weave_error; 16894f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko ConvertError(*brillo_error, &weave_error); 169e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko base::MessageLoop::current()->PostTask( 17094f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko FROM_HERE, base::Bind(callback, base::Passed(&weave_error))); 171e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko return; 17258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 17358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka connecting_service_.reset(new ServiceProxy{bus_, service_path}); 174e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko connecting_service_->Connect(nullptr); 17594f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko connect_done_callback_ = callback; 17658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka connecting_service_->RegisterPropertyChangedSignalHandler( 17758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka base::Bind(&ShillClient::OnServicePropertyChange, 17858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka weak_factory_.GetWeakPtr(), service_path), 17958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka base::Bind(&ShillClient::OnServicePropertyChangeRegistration, 18058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka weak_factory_.GetWeakPtr(), service_path)); 181e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko base::MessageLoop::current()->PostDelayedTask( 182e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko FROM_HERE, base::Bind(&ShillClient::ConnectToServiceError, 183e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko weak_factory_.GetWeakPtr(), connecting_service_), 184e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko base::TimeDelta::FromMinutes(1)); 18558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 18658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 187e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenkovoid ShillClient::ConnectToServiceError( 188e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko std::shared_ptr<org::chromium::flimflam::ServiceProxy> connecting_service) { 189e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (connecting_service != connecting_service_ || 19094f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko connect_done_callback_.is_null()) { 191e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko return; 192e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko } 193e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko std::string error = have_called_connect_ ? connecting_service_error_ 194e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko : shill::kErrorOutOfRange; 195e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (error.empty()) 196e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko error = shill::kErrorInternal; 197e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko OnErrorChangeForConnectingService(error); 198e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko} 199e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko 200e32375bdf73d6e79a003a194e4c6931f38348520Alex VakulenkoNetwork::State ShillClient::GetConnectionState() const { 20158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return connectivity_state_; 20258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 20358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 204e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenkovoid ShillClient::StartAccessPoint(const std::string& ssid) { 205685b2aeed879903b86448428dec1e88c9b6741b1Alex Vakulenko LOG(INFO) << "Starting Soft AP: " << ssid; 2063ef4fff987aa1da566262907f993cd3807c37a62Vitaly Buka ap_manager_client_->Start(ssid); 2073ef4fff987aa1da566262907f993cd3807c37a62Vitaly Buka} 2083ef4fff987aa1da566262907f993cd3807c37a62Vitaly Buka 209e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenkovoid ShillClient::StopAccessPoint() { 210685b2aeed879903b86448428dec1e88c9b6741b1Alex Vakulenko LOG(INFO) << "Stopping Soft AP"; 2113ef4fff987aa1da566262907f993cd3807c37a62Vitaly Buka ap_manager_client_->Stop(); 2123ef4fff987aa1da566262907f993cd3807c37a62Vitaly Buka} 2133ef4fff987aa1da566262907f993cd3807c37a62Vitaly Buka 214e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenkovoid ShillClient::AddConnectionChangedCallback( 215e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko const ConnectionChangedCallback& listener) { 21658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka connectivity_listeners_.push_back(listener); 21758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 21858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 21958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukabool ShillClient::IsMonitoredDevice(DeviceProxy* device) { 22058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (device_whitelist_.empty()) { 22158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return true; 22258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 22358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VariantDictionary device_properties; 22458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (!device->GetProperties(&device_properties, nullptr)) { 22558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(ERROR) << "Devices without properties aren't whitelisted."; 22658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return false; 22758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 22858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka auto it = device_properties.find(shill::kInterfaceProperty); 22958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (it == device_properties.end()) { 23058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(ERROR) << "Failed to find interface property in device properties."; 23158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return false; 23258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 23358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return ContainsKey(device_whitelist_, it->second.TryGet<string>()); 23458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 23558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 23658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::OnShillServiceOwnerChange(const string& old_owner, 23758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const string& new_owner) { 23858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(1) << "Shill service owner name changed to '" << new_owner << "'"; 23958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (new_owner.empty()) { 240e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko CleanupConnectingService(); 24158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka devices_.clear(); 242e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko connectivity_state_ = Network::State::kOffline; 24358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } else { 24458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka Init(); // New service owner means shill reset! 24558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 24658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 24758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 24858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::OnManagerPropertyChangeRegistration(const string& interface, 24958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const string& signal_name, 25058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka bool success) { 25158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "Registered ManagerPropertyChange handler."; 25258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka CHECK(success) << "privetd requires Manager signals."; 25358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VariantDictionary properties; 25458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (!manager_proxy_.GetProperties(&properties, nullptr)) { 25558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(ERROR) << "Unable to get properties from Manager, waiting for " 25658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka "Manager to come back online."; 25758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 25858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 25958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka auto it = properties.find(shill::kDevicesProperty); 26058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka CHECK(it != properties.end()) << "Shill should always publish a device list."; 26158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka OnManagerPropertyChange(shill::kDevicesProperty, it->second); 26258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 26358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 26458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::OnManagerPropertyChange(const string& property_name, 26558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const Any& property_value) { 26658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (property_name != shill::kDevicesProperty) { 26758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 26858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 2695d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka bool update_connectivity = false; 27058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "Manager's device list has changed."; 27158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // We're going to remove every device we haven't seen in the update. 27258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka set<ObjectPath> device_paths_to_remove; 27358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka for (const auto& kv : devices_) { 27458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka device_paths_to_remove.insert(kv.first); 27558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 27658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka for (const auto& device_path : property_value.TryGet<vector<ObjectPath>>()) { 27758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (!device_path.IsValid()) { 27858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(ERROR) << "Ignoring invalid device path in Manager's device list."; 27958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 28058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 28158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka auto it = devices_.find(device_path); 28258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (it != devices_.end()) { 28358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // Found an existing proxy. Since the whitelist never changes, 28458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // this still a valid device. 28558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka device_paths_to_remove.erase(device_path); 28658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka continue; 28758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 28858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka std::unique_ptr<DeviceProxy> device{new DeviceProxy{bus_, device_path}}; 28958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (!IsMonitoredDevice(device.get())) { 29058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka continue; 29158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 2925d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka VLOG(3) << "Creating device proxy at " << device_path.value(); 2935d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka devices_[device_path].device = std::move(device); 2945d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka update_connectivity = true; 2955d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka devices_[device_path].device->RegisterPropertyChangedSignalHandler( 29658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka base::Bind(&ShillClient::OnDevicePropertyChange, 29758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka weak_factory_.GetWeakPtr(), device_path), 29858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka base::Bind(&ShillClient::OnDevicePropertyChangeRegistration, 29958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka weak_factory_.GetWeakPtr(), device_path)); 30058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 30158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // Clean up devices/services related to removed devices. 3025d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka for (const ObjectPath& device_path : device_paths_to_remove) { 3035d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka devices_.erase(device_path); 3045d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka update_connectivity = true; 30558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 3065d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka 3075d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka if (update_connectivity) 3085d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka UpdateConnectivityState(); 30958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 31058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 31158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::OnDevicePropertyChangeRegistration( 31258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const ObjectPath& device_path, 31358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const string& interface, 31458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const string& signal_name, 31558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka bool success) { 31658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "Registered DevicePropertyChange handler."; 31758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka auto it = devices_.find(device_path); 31858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (it == devices_.end()) { 31958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 32058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 32158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka CHECK(success) << "Failed to subscribe to Device property changes."; 32258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka DeviceProxy* device = it->second.device.get(); 32358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VariantDictionary properties; 32458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (!device->GetProperties(&properties, nullptr)) { 32558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(WARNING) << "Failed to get device properties?"; 32658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 32758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 32858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka auto prop_it = properties.find(shill::kSelectedServiceProperty); 32958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (prop_it == properties.end()) { 33058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(WARNING) << "Failed to get device's selected service?"; 33158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 33258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 33358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka OnDevicePropertyChange(device_path, shill::kSelectedServiceProperty, 33458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka prop_it->second); 33558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 33658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 33758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::OnDevicePropertyChange(const ObjectPath& device_path, 33858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const string& property_name, 33958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const Any& property_value) { 34058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // We only care about selected services anyway. 34158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (property_name != shill::kSelectedServiceProperty) { 34258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 34358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 34458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // If the device isn't our list of whitelisted devices, ignore it. 34558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka auto it = devices_.find(device_path); 34658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (it == devices_.end()) { 34758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 34858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 34958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka DeviceState& device_state = it->second; 35058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka ObjectPath service_path{property_value.TryGet<ObjectPath>()}; 35158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (!service_path.IsValid()) { 35258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(ERROR) << "Device at " << device_path.value() 35358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka << " selected invalid service path."; 35458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 35558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 35658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "Device at " << it->first.value() << " has selected service at " 35758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka << service_path.value(); 35858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka bool removed_old_service{false}; 35958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (device_state.selected_service) { 36058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (device_state.selected_service->GetObjectPath() == service_path) { 36158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; // Spurious update? 36258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 36358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka device_state.selected_service.reset(); 364e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko device_state.service_state = Network::State::kOffline; 36558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka removed_old_service = true; 36658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 36758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const bool reuse_connecting_service = 36858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka service_path.value() != "/" && connecting_service_ && 36958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka connecting_service_->GetObjectPath() == service_path; 37058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (reuse_connecting_service) { 3715d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka device_state.selected_service = connecting_service_; 37258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // When we reuse the connecting service, we need to make sure that our 37358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // cached state is correct. Normally, we do this by relying reading the 37458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // state when our signal handlers finish registering, but this may have 37558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // happened long in the past for the connecting service. 37658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka string state; 3775d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka if (GetStateForService(connecting_service_.get(), &state)) { 37858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka device_state.service_state = ShillServiceStateToNetworkState(state); 37958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } else { 38058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka LOG(WARNING) << "Failed to read properties from existing service " 38158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka "on selection."; 38258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 38358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } else if (service_path.value() != "/") { 38458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // The device has selected a new service we haven't see before. 3855d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka device_state.selected_service = 3865d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka std::make_shared<ServiceProxy>(bus_, service_path); 3875d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka device_state.selected_service->RegisterPropertyChangedSignalHandler( 38858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka base::Bind(&ShillClient::OnServicePropertyChange, 38958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka weak_factory_.GetWeakPtr(), service_path), 39058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka base::Bind(&ShillClient::OnServicePropertyChangeRegistration, 39158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka weak_factory_.GetWeakPtr(), service_path)); 39258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 3935d14dca2905a70a814a15044fff0f555d7e333c1Vitaly Buka 39458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (reuse_connecting_service || removed_old_service) { 39558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka UpdateConnectivityState(); 39658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 39758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 39858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 39958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::OnServicePropertyChangeRegistration(const ObjectPath& path, 40058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const string& interface, 40158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const string& signal_name, 40258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka bool success) { 40358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "OnServicePropertyChangeRegistration(" << path.value() << ");"; 40458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka ServiceProxy* service{nullptr}; 40558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (connecting_service_ && connecting_service_->GetObjectPath() == path) { 40658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // Note that the connecting service might also be a selected service. 40758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka service = connecting_service_.get(); 408e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (!success) 409e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko CleanupConnectingService(); 41058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } else { 41158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka for (const auto& kv : devices_) { 41258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (kv.second.selected_service && 41358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka kv.second.selected_service->GetObjectPath() == path) { 41458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka service = kv.second.selected_service.get(); 41558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka break; 41658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 41758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 41858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 41958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (service == nullptr || !success) { 42058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; // A failure or success for a proxy we no longer care about. 42158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 42258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VariantDictionary properties; 42358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (!service->GetProperties(&properties, nullptr)) { 42458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 42558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 42658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // Give ourselves property changed signals for the initial property 42758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // values. 428e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko for (auto name : {shill::kStateProperty, shill::kSignalStrengthProperty, 429e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko shill::kErrorProperty}) { 430e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko auto it = properties.find(name); 431e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (it != properties.end()) 432e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko OnServicePropertyChange(path, name, it->second); 43358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 43458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 43558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 43658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::OnServicePropertyChange(const ObjectPath& service_path, 43758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const string& property_name, 43858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const Any& property_value) { 43958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "ServicePropertyChange(" << service_path.value() << ", " 44058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka << property_name << ", ...);"; 441e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko 442e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko bool is_connecting_service = 443e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko connecting_service_ && 444e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko connecting_service_->GetObjectPath() == service_path; 44558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (property_name == shill::kStateProperty) { 44658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const string state{property_value.TryGet<string>()}; 44758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (state.empty()) { 44858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "Invalid service state update."; 44958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 45058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 45158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "New service state=" << state; 45258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka OnStateChangeForSelectedService(service_path, state); 453e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (is_connecting_service) 454e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko OnStateChangeForConnectingService(state); 45558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } else if (property_name == shill::kSignalStrengthProperty) { 456e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko VLOG(3) << "Signal strength=" << property_value.TryGet<uint8_t>(); 457e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (is_connecting_service) 458e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko OnStrengthChangeForConnectingService(property_value.TryGet<uint8_t>()); 459e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko } else if (property_name == shill::kErrorProperty) { 460e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko VLOG(3) << "Error=" << property_value.TryGet<std::string>(); 461e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (is_connecting_service) 462e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko connecting_service_error_ = property_value.TryGet<std::string>(); 46358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 46458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 46558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 466e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenkovoid ShillClient::OnStateChangeForConnectingService(const string& state) { 467e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko switch (ShillServiceStateToNetworkState(state)) { 468be39e9339baa85af546344da40b0663a6aea1a97Alex Vakulenko case Network::State::kOnline: { 46994f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko auto callback = connect_done_callback_; 47094f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko connect_done_callback_.Reset(); 471e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko CleanupConnectingService(); 472e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko 473e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (!callback.is_null()) 47494f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko callback.Run(nullptr); 475e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko break; 476e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko } 477be39e9339baa85af546344da40b0663a6aea1a97Alex Vakulenko case Network::State::kError: { 478e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko ConnectToServiceError(connecting_service_); 479e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko break; 480e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko } 481e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko case Network::State::kOffline: 482e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko case Network::State::kConnecting: 483e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko break; 48458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 485e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko} 486e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko 487e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenkovoid ShillClient::OnErrorChangeForConnectingService(const std::string& error) { 488e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (error.empty()) 489e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko return; 490e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko 49194f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko auto callback = connect_done_callback_; 492e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko CleanupConnectingService(); 493e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko 494e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko weave::ErrorPtr weave_error; 49534183c1b5b678a9726a955db9e05a361ed05eeacVitaly Buka weave::Error::AddTo(&weave_error, FROM_HERE, error, 496e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko "Failed to connect to WiFi network"); 497e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko 498e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (!callback.is_null()) 499297114c6c820d71bba206d1b2d38c98abc8540d9Alex Vakulenko callback.Run(std::move(weave_error)); 50058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 50158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 50258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::OnStrengthChangeForConnectingService( 50358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka uint8_t signal_strength) { 504e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (signal_strength == 0 || have_called_connect_) { 50558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 50658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 50758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(1) << "Connecting service has signal. Calling Connect()."; 50858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka have_called_connect_ = true; 50958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // Failures here indicate that we've already connected, 51058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // or are connecting, or some other very unexciting thing. 51158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // Ignore all that, and rely on state changes to detect 51258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // connectivity. 51358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka connecting_service_->Connect(nullptr); 51458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 51558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 51658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::OnStateChangeForSelectedService( 51758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const ObjectPath& service_path, 51858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka const string& state) { 51958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // Find the device/service pair responsible for this update 52058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "State for potentially selected service " << service_path.value() 52158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka << " have changed to " << state; 52258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka for (auto& kv : devices_) { 52358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (kv.second.selected_service && 52458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka kv.second.selected_service->GetObjectPath() == service_path) { 52558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "Updated cached connection state for selected service."; 52658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka kv.second.service_state = ShillServiceStateToNetworkState(state); 52758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka UpdateConnectivityState(); 52858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka return; 52958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 53058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 53158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 53258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 53358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::UpdateConnectivityState() { 53458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // Update the connectivity state of the device by picking the 53558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // state of the currently most connected selected service. 536e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko Network::State new_connectivity_state{Network::State::kOffline}; 53758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka for (const auto& kv : devices_) { 53858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (kv.second.service_state > new_connectivity_state) { 53958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka new_connectivity_state = kv.second.service_state; 54058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 54158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 54258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(1) << "Connectivity changed: " << EnumToString(connectivity_state_) 54358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka << " -> " << EnumToString(new_connectivity_state); 54458a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // Notify listeners even if state changed to the same value. Listeners may 54558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // want to handle this event. 54658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka connectivity_state_ = new_connectivity_state; 54758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // We may call UpdateConnectivityState whenever we mutate a data structure 54858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // such that our connectivity status could change. However, we don't want 54958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // to allow people to call into ShillClient while some other operation is 55058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // underway. Therefore, call our callbacks later, when we're in a good 55158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka // state. 55258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka base::MessageLoop::current()->PostTask( 553297114c6c820d71bba206d1b2d38c98abc8540d9Alex Vakulenko FROM_HERE, base::Bind(&ShillClient::NotifyConnectivityListeners, 554297114c6c820d71bba206d1b2d38c98abc8540d9Alex Vakulenko weak_factory_.GetWeakPtr(), 555297114c6c820d71bba206d1b2d38c98abc8540d9Alex Vakulenko GetConnectionState() == Network::State::kOnline)); 55658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 55758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 55858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Bukavoid ShillClient::NotifyConnectivityListeners(bool am_online) { 55958a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka VLOG(3) << "Notifying connectivity listeners that online=" << am_online; 560e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko for (const auto& listener : connectivity_listeners_) 561e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko listener.Run(); 56258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 56358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 564e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenkovoid ShillClient::CleanupConnectingService() { 56558a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka if (connecting_service_) { 56658a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka connecting_service_->ReleaseObjectProxy(base::Bind(&IgnoreDetachEvent)); 56758a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka connecting_service_.reset(); 56858a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka } 56994f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko connect_done_callback_.Reset(); 57058a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka have_called_connect_ = false; 57158a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} 57258a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka 57394f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenkovoid ShillClient::OpenSslSocket(const std::string& host, 57494f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko uint16_t port, 57594f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko const OpenSslSocketCallback& callback) { 5760022b7523bca3bde23c0f982384f83a39791e88bAlex Vakulenko if (disable_xmpp_) 5770022b7523bca3bde23c0f982384f83a39791e88bAlex Vakulenko return; 578e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko std::unique_ptr<weave::Stream> raw_stream{ 579e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko SocketStream::ConnectBlocking(host, port)}; 580e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko if (!raw_stream) { 5814170585fe75d99036883229081420f2972dd4ec1Alex Vakulenko brillo::ErrorPtr error; 5824170585fe75d99036883229081420f2972dd4ec1Alex Vakulenko brillo::errors::system::AddSystemError(&error, FROM_HERE, errno); 583e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko weave::ErrorPtr weave_error; 584e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko ConvertError(*error.get(), &weave_error); 585e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko base::MessageLoop::current()->PostTask( 58694f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko FROM_HERE, base::Bind(callback, nullptr, base::Passed(&weave_error))); 587e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko return; 588e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko } 589e32375bdf73d6e79a003a194e4c6931f38348520Alex Vakulenko 59094f8eba2f71f0d73e15bfd5b1c28bb0ed682706dAlex Vakulenko SocketStream::TlsConnect(std::move(raw_stream), host, callback); 591493f604eb1cb5bff0a4af86e6cb9e79983d543f6Vitaly Buka} 592493f604eb1cb5bff0a4af86e6cb9e79983d543f6Vitaly Buka 59358a288b5b10aec975c7bc4fbfdcbcb80d5899c12Vitaly Buka} // namespace buffet 594