blob: f3856d21fdd6054664f8b367968e1655e5eae12f [file] [log] [blame]
// Copyright 2022 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include <set>
#include <vector>
#include "shill/tethering_manager.h"
#include <chromeos/dbus/shill/dbus-constants.h>
#include "shill/error.h"
#include "shill/manager.h"
#include "shill/store/property_accessor.h"
#include "shill/technology.h"
namespace shill {
TetheringManager::TetheringManager(Manager* manager)
: manager_(manager),
allowed_(false),
state_(TetheringState::kTetheringIdle) {}
TetheringManager::~TetheringManager() = default;
void TetheringManager::InitPropertyStore(PropertyStore* store) {
store->RegisterBool(kTetheringAllowedProperty, &allowed_);
store->RegisterDerivedKeyValueStore(
kTetheringConfigProperty,
KeyValueStoreAccessor(new CustomAccessor<TetheringManager, KeyValueStore>(
this, &TetheringManager::GetConfig, &TetheringManager::SetConfig)));
store->RegisterDerivedKeyValueStore(
kTetheringCapabilitiesProperty,
KeyValueStoreAccessor(new CustomAccessor<TetheringManager, KeyValueStore>(
this, &TetheringManager::GetCapabilities, nullptr)));
store->RegisterDerivedKeyValueStore(
kTetheringStatusProperty,
KeyValueStoreAccessor(new CustomAccessor<TetheringManager, KeyValueStore>(
this, &TetheringManager::GetStatus, nullptr)));
}
KeyValueStore TetheringManager::GetConfig(Error* /*error*/) {
return config_;
}
bool TetheringManager::SetConfig(const KeyValueStore& config, Error* error) {
if (!allowed_) {
Error::PopulateAndLog(FROM_HERE, error, Error::kPermissionDenied,
"Tethering is not allowed");
return false;
}
return true;
}
KeyValueStore TetheringManager::GetCapabilities(Error* /* error */) {
KeyValueStore caps;
std::vector<std::string> upstream_technologies;
std::vector<std::string> downstream_technologies;
if (manager_->GetProviderWithTechnology(Technology::kEthernet))
upstream_technologies.push_back(TechnologyName(Technology::kEthernet));
// TODO(b/244334719): add a check with the CellularProvider to see if
// tethering is enabled for the given SIM card and modem.
if (manager_->GetProviderWithTechnology(Technology::kCellular))
upstream_technologies.push_back(TechnologyName(Technology::kCellular));
if (manager_->GetProviderWithTechnology(Technology::kWiFi)) {
// TODO(b/244335143): This should be based on static SoC capability
// information. Need to revisit this when Shill has a SoC capability
// database.
const auto wifi_devices = manager_->FilterByTechnology(Technology::kWiFi);
if (!wifi_devices.empty()) {
WiFi* wifi_device = static_cast<WiFi*>(wifi_devices.front().get());
if (wifi_device->SupportAP()) {
downstream_technologies.push_back(TechnologyName(Technology::kWiFi));
// Wi-Fi specific tethering capabilities.
std::vector<std::string> security = {kSecurityWpa2};
if (wifi_device->SupportsWPA3()) {
security.push_back(kSecurityWpa3);
security.push_back(kSecurityWpa2Wpa3);
}
caps.Set<Strings>(kTetheringCapSecurityProperty, security);
}
}
}
caps.Set<Strings>(kTetheringCapUpstreamProperty, upstream_technologies);
caps.Set<Strings>(kTetheringCapDownstreamProperty, downstream_technologies);
return caps;
}
KeyValueStore TetheringManager::GetStatus(Error* /* error */) {
KeyValueStore status;
status.Set<std::string>(kTetheringStatusStateProperty,
TetheringStateToString(state_));
return status;
}
// static
const char* TetheringManager::TetheringStateToString(
const TetheringState& state) {
switch (state) {
case TetheringState::kTetheringIdle:
return kTetheringStateIdle;
case TetheringState::kTetheringStarting:
return kTetheringStateStarting;
case TetheringState::kTetheringActive:
return kTetheringStateActive;
case TetheringState::kTetheringStopping:
return kTetheringStateStopping;
case TetheringState::kTetheringFailure:
return kTetheringStateFailure;
default:
NOTREACHED() << "Unhandled tethering state " << static_cast<int>(state);
return "Invalid";
}
}
void TetheringManager::Start() {
}
void TetheringManager::Stop() {}
bool TetheringManager::SetEnabled(bool enabled, Error* error) {
if (!allowed_) {
Error::PopulateAndLog(FROM_HERE, error, Error::kPermissionDenied,
"Tethering is not allowed");
return false;
}
return true;
}
std::string TetheringManager::TetheringManager::CheckReadiness(Error* error) {
if (!allowed_) {
Error::PopulateAndLog(FROM_HERE, error, Error::kPermissionDenied,
"Tethering is not allowed");
return kTetheringReadinessNotAllowed;
}
// TODO(b/235762746): Stub method handler always return "ready". Add more
// status code later.
return kTetheringReadinessReady;
}
} // namespace shill