Wi-Fi Hotspot UI

This commit is contained in:
Robin Davies
2024-09-12 19:12:07 -04:00
parent 66e46b8d39
commit f34ca1f0da
22 changed files with 1155 additions and 530 deletions
+10 -12
View File
@@ -116,12 +116,6 @@ public:
static std::vector<std::unique_ptr<IDBusLogger>> loggers;
void SetDBusLogger(std::unique_ptr<IDBusLogger> && logger)
{
loggers.clear();
loggers.push_back(std::move(logger));
}
void SetDBusLogLevel(DBusLogLevel level)
{
@@ -231,11 +225,17 @@ void LogTrace(const std::string&path,const char*method,const std::string&message
}
}
void SetDBusLogger(std::unique_ptr<IDBusLogger> && logger)
{
loggers.clear();
loggers.push_back(std::move(logger));
}
void SetDBusConsoleLogger()
{
loggers.clear();
loggers.push_back(std::make_unique<ConsoleDBusLogger>());
SetDBusLogger(std::make_unique<ConsoleDBusLogger>());
}
void AddDBusConsoleLogger()
{
@@ -243,13 +243,11 @@ void AddDBusConsoleLogger()
}
void SetDBusSystemdLogger()
{
loggers.clear();
loggers.push_back(std::make_unique<SystemdDBusLogger>());
SetDBusLogger(std::make_unique<SystemdDBusLogger>());
}
void SetDBusFileLogger(const std::filesystem::path &path)
{
loggers.clear();
loggers.push_back(std::make_unique<FileDBusLogger>(path));
SetDBusLogger(std::make_unique<FileDBusLogger>(path));
}
+117 -45
View File
@@ -102,6 +102,8 @@ void WifiConfigSettings::Load()
reader.read(this);
}
this->countryCode_ = getWifiCountryCode();
this->enable_ = this->autoStartMode_ != (uint16_t)HotspotAutoStartMode::Never;
this->mdnsName_ = this->hotspotName_;
}
catch (const std::exception &e)
{
@@ -143,12 +145,27 @@ static void openWithPerms(
void WifiConfigSettings::Save()
{
WifiConfigSettings newSettings {*this};
// sync legacy settings, just in case i don't know what.
newSettings.mdnsName_ = newSettings.hotspotName_;
newSettings.enable_ = newSettings.IsEnabled();
// fill in the password, if required.
if (!newSettings.hasPassword_)
{
WifiConfigSettings oldSettings;
oldSettings.Load();
newSettings.hasPassword_ = oldSettings.hasPassword_;
newSettings.password_ = oldSettings.password_;
}
newSettings.hasSavedPassword_ = newSettings.hasPassword_;
try
{
ofstream_synced f;
openWithPerms(f,CONFIG_PATH);
json_writer writer(f);
writer.write(this);
writer.write(&newSettings);
}
catch (const std::exception &e)
{
@@ -398,6 +415,7 @@ namespace pipedal::priv
JSON_MAP_BEGIN(WifiConfigSettings)
// v0
JSON_MAP_REFERENCE(WifiConfigSettings, valid)
JSON_MAP_REFERENCE(WifiConfigSettings, wifiWarningGiven)
JSON_MAP_REFERENCE(WifiConfigSettings, rebootRequired)
@@ -408,8 +426,13 @@ JSON_MAP_REFERENCE(WifiConfigSettings, hasPassword)
JSON_MAP_REFERENCE(WifiConfigSettings, password)
JSON_MAP_REFERENCE(WifiConfigSettings, countryCode)
JSON_MAP_REFERENCE(WifiConfigSettings, channel)
JSON_MAP_REFERENCE(WifiConfigSettings, alwaysOn)
JSON_MAP_REFERENCE(WifiConfigSettings, homeNetworks)
// v1: Auto-hotspot
JSON_MAP_REFERENCE(WifiConfigSettings, autoStartMode)
JSON_MAP_REFERENCE(WifiConfigSettings, homeNetwork)
JSON_MAP_REFERENCE(WifiConfigSettings, hasSavedPassword)
JSON_MAP_END()
int32_t pipedal::ChannelToChannelNumber(const std::string &channel)
@@ -646,22 +669,33 @@ static std::vector<WifiConfigSettings::ssid_t> stringToSsidArray(const std::stri
return result;
}
void WifiConfigSettings::ParseArguments(const std::vector<std::string> &argv)
void WifiConfigSettings::ParseArguments(
const std::vector<std::string> &argv,
HotspotAutoStartMode startMode,
const std::string homeNetworkSsid
)
{
this->valid_ = false;
if (argv.size() < 4 || argv.size() > 6)
if (argv.size() != 4)
{
throw invalid_argument("Invalid number of arguments.");
}
this->enable_ = true;
WifiConfigSettings oldSettings;
oldSettings.Load();
this->valid_ = false;
this->autoStartMode_ = (int16_t)startMode;
this->enable_ = startMode != HotspotAutoStartMode::Never;
this->homeNetwork_ = homeNetworkSsid;
this->countryCode_ = argv[0];
this->hotspotName_ = argv[1];
this->mdnsName_ = this->hotspotName_;
this->password_ = argv[2];
this->channel_ = argv[3];
this->hasPassword_ = this->password_.length() != 0;
this->homeNetworks_ = std::vector<ssid_t>();
this->alwaysOn_ = false;
this->hasSavedPassword_ = oldSettings.hasSavedPassword_;
if (!ValidateCountryCode(this->countryCode_))
@@ -672,26 +706,20 @@ void WifiConfigSettings::ParseArguments(const std::vector<std::string> &argv)
throw invalid_argument("Hotspot name is too long.");
if (this->hotspotName_.length() < 1)
throw invalid_argument("Hotspot name is too short.");
if (this->password_.size() != 0 && this->password_.size() < 8)
throw invalid_argument("Passphrase must be at least 8 characters long.");
if (this->password_.size() == 0 && !this->hasSavedPassword_)
{
throw invalid_argument("Passphrase required.");
}
if (!ValidateChannel(this->countryCode_, this->channel_))
{
throw invalid_argument("Channel is not valid.");
}
if (argv.size() >= 5)
{
if (!TryStringToBool(argv[4],&this->alwaysOn_))
{
throw std::runtime_error(SS("Invalid boolean value: " << argv[4]));
}
}
if (argv.size() >= 6)
{
this->homeNetworks_ = stringToSsidArray(argv[5]);
}
// validate that the channel number is supported for the given country code.
this->valid_ = true;
@@ -701,15 +729,17 @@ bool WifiConfigSettings::ConfigurationChanged(const WifiConfigSettings&other) co
{
return !(
this->valid_ == other.valid_ &&
this->rebootRequired_ == other.rebootRequired_ &&
this->enable_ == other.enable_ &&
//this->rebootRequired_ == other.rebootRequired_ &&
//this->enable_ == other.enable_ &&
this->countryCode_ == other.countryCode_ &&
this->mdnsName_ == other.mdnsName_ &&
this->hotspotName_ == other.hotspotName_ &&
this->hasPassword_ == other.hasPassword_ &&
this->password_ == other.password_ &&
this->channel_ == other.channel_ &&
this->homeNetworks_ == other.homeNetworks_ &&
this->alwaysOn_ == other.alwaysOn_
this->homeNetwork_ == other.homeNetwork_ &&
this->autoStartMode_ == other.autoStartMode_ &&
this->hasSavedPassword_ == other.hasSavedPassword_
);
}
@@ -718,33 +748,75 @@ bool WifiConfigSettings::operator==(const WifiConfigSettings&other) const
return !ConfigurationChanged(other) && this->wifiWarningGiven_ == other.wifiWarningGiven_;
}
bool WifiConfigSettings::WantsHotspot(bool ethernetConnected, const std::vector<ssid_t> &availableNetworks)
static bool CanSeeHomeNetwork(const std::string&home, const std::vector<std::string>&availableNetworks)
{
if ((!this->valid_) || (!this->enable_))
return false;
if (ethernetConnected)
for (const auto &availableNetwork: availableNetworks)
{
return false;
}
if (!homeNetworks_.empty())
{
for (auto &network: availableNetworks)
if (availableNetwork == home)
{
for (auto&homeNetwork: homeNetworks_)
{
if (network == homeNetwork)
{
return false;
}
}
return true;
}
}
if (alwaysOn_)
return false;
}
bool WifiConfigSettings::WantsHotspot(
bool ethernetConnected,
const std::vector<std::string> &availableRememberedNetworks,
const std::vector<std::string> &availableNetworks)
{
if ((!this->valid_))
return false;
HotspotAutoStartMode autoStartMode = (HotspotAutoStartMode)this->autoStartMode_;
switch (autoStartMode)
{
return true;
case HotspotAutoStartMode::Never:
default:
return false;
case HotspotAutoStartMode::NoEthernetConnection:
return !ethernetConnected;
case HotspotAutoStartMode::NotAtHome:
return !CanSeeHomeNetwork(this->homeNetwork_, availableNetworks);
case HotspotAutoStartMode::NoRememberedWifiConections:
return availableRememberedNetworks.size() == 0;
case HotspotAutoStartMode::Always:
return true;
}
return availableNetworks.size() == 0;
}
std::string pipedal::ssidToString(const std::vector<uint8_t> &ssid)
{
std::stringstream s;
for (auto v: ssid)
{
if (v == 0) break; // breaks for some arguably legal ssids, but I can live with that.
s << (char)v;
}
return s.str();
}
std::vector<std::string> pipedal::ssidToStringVector(const std::vector<std::vector<uint8_t>> &ssids)
{
std::vector<std::string> result;
result.reserve(ssids.size());
for (const std::vector<uint8_t> &ssid: ssids)
{
result.push_back(ssidToString(ssid));
}
return result;
}
bool WifiConfigSettings::WantsHotspot(
bool ethernetConnected,
const std::vector<std::vector<uint8_t>> &availableRememberedNetworks, // remembered networks that are currently visible
const std::vector<std::vector<uint8_t>> &availableNetworks // all visible networks.
)
{
std::vector<std::string> sAvailableRememberedNetworks = ssidToStringVector(availableRememberedNetworks);
std::vector<std::string> sAvailableNetworks = ssidToStringVector(availableNetworks);
return WantsHotspot(ethernetConnected,sAvailableRememberedNetworks,sAvailableNetworks);
}
@@ -20,6 +20,8 @@
#pragma once
#include "json.hpp"
#include <vector>
#include <string>
#ifndef NEW_WIFI_CONFIG
@@ -39,12 +41,23 @@
#endif
namespace pipedal {
std::string ssidToString(const std::vector<uint8_t> &ssid);
std::vector<std::string> ssidToStringVector(const std::vector<std::vector<uint8_t>> &ssids);
uint32_t ChannelToWifiFrequency(const std::string &channel);
uint32_t ChannelToWifiFrequency(uint32_t channel);
int32_t ChannelToChannelNumber(const std::string&channel);
enum class HotspotAutoStartMode {
// saved to file. Do not remove or renumber enums.
Never = 0,
NoEthernetConnection = 1,
NotAtHome = 2,
NoRememberedWifiConections = 3,
Always = 4
};
class WifiConfigSettings {
public:
using ssid_t = std::vector<uint8_t>;
@@ -53,26 +66,45 @@ namespace pipedal {
void Load();
void Save();
bool valid_ = false;
bool wifiWarningGiven_ = false;
bool rebootRequired_ = false;
bool enable_ = false;
int16_t autoStartMode_ = 0; // see HotspotAutoStartMode
bool hasSavedPassword_ = false;
std::string homeNetwork_;
std::string countryCode_ = "US"; // iso 3661
std::string hotspotName_ = "pipedal";
std::string mdnsName_ = "pipedal";
std::vector<ssid_t> homeNetworks_;
bool hasPassword_ = false;
std::string password_;
std::string channel_ = "";
bool alwaysOn_ = false;
void ParseArguments(const std::vector<std::string> &arguments);
bool wifiWarningGiven_ = false; // Do not use. Present only for backward compatibility.
bool valid_ = false; // Do not use. Present only for backward compatibility.
private:
bool rebootRequired_ = false; // Do not use. Present only for backward compatibility.
std::string mdnsName_ = "pipedal";
bool enable_ = false; // Do not use. Present only for backward compatibility.
public:
bool IsEnabled() const { return autoStartMode_ != 0; }
// Initialize from commandline arguments (see ConfigMain.cpp)
void ParseArguments(
const std::vector<std::string> &argv,
HotspotAutoStartMode startMode,
const std::string homeNetworkSsid
);
static bool ValidateCountryCode(const std::string&value);
static bool ValidateChannel(const std::string&countryCode,const std::string&value);
bool operator==(const WifiConfigSettings&other) const;
bool ConfigurationChanged(const WifiConfigSettings&other) const;
bool WantsHotspot(bool ethernetConnected,const std::vector<ssid_t> &availableNetworks);
bool WantsHotspot(
bool ethernetConnected,
const std::vector<std::string> &availableRememberedNetworks, // remembered networks that are currently visible
const std::vector<std::string> &availableNetworks // all visible networks.
);
bool WantsHotspot(
bool ethernetConnected,
const std::vector<std::vector<uint8_t>> &availableRememberedNetworks, // remembered networks that are currently visible
const std::vector<std::vector<uint8_t>> &availableNetworks // all visible networks.
);
public:
DECLARE_JSON_MAP(WifiConfigSettings);
+24
View File
@@ -335,6 +335,14 @@ namespace pipedal
{
os << value;
}
void write(short value)
{
os << value;
}
void write(unsigned short value)
{
os << value;
}
void write(long long value)
{
os << value;
@@ -897,6 +905,22 @@ namespace pipedal
if (is_.fail())
throw JsonException("Invalid format.");
}
void read(short * value)
{
skip_whitespace();
is_ >> *value;
if (is_.fail())
throw JsonException("Invalid format.");
}
void read(unsigned short * value)
{
skip_whitespace();
is_ >> *value;
if (is_.fail())
throw JsonException("Invalid format.");
}
void read(int *value)
{
skip_whitespace();