Files
op-pedal/NetworkManagerP2P/src/NMP2pSettings.cpp
T
Robin Davies 26ba5a4327 Build break.
2024-08-27 18:12:23 -04:00

266 lines
7.2 KiB
C++

#include "NMP2pSettings.hpp"
#include "WifiDirectConfigSettings.hpp"
#include "ServiceConfiguration.hpp"
#include <stdexcept>
#include "ss.hpp"
#include <fstream>
#include <random>
#include <stdexcept>
#include "WifiRegs.hpp"
#include "ChannelInfo.hpp"
#include "DBusLog.hpp"
#include <sys/stat.h>
using namespace pipedal;
P2pSettings::P2pSettings(const std::filesystem::path&configDirectoryPath, const std::filesystem::path&varDirectoryPath)
: configDirectoryPath(configDirectoryPath),
varDirectoryPath(varDirectoryPath)
{
}
static const char*hexDigits = "0123456789abcdef";
std::string MakeBssid()
{
// "de:a6:32:d4:a1:66"
std::random_device rDev;
std::uniform_int_distribution<uint8_t> dist(0,255);
uint8_t bssid[6];
for (size_t i = 0; i < 6; ++i)
{
bssid[i] = dist(rDev);
}
std::stringstream ss;
bool firstTime = true;
for (size_t i = 0; i < 6; ++i)
{
if (!firstTime)
{
ss << ':';
}
firstTime = false;
ss << hexDigits[(bssid[i] >> 4) & 0x0F];
ss << hexDigits[(bssid[i] >> 0) & 0x0F];
}
return ss.str();
}
void P2pSettings::Load()
{
bool configChanged = true;
// load our json config.
{
auto filename = config_filename();
if (std::filesystem::exists(filename))
{
try {
std::ifstream f;
f.open(filename);
if (!f)
{
throw std::runtime_error(SS("Can't open file."));
}
try {
json_reader reader{f};
reader.read(this);
configChanged = false;
} catch (const std::exception &e)
{
throw;
}
} catch (const std::exception &e)
{
throw std::runtime_error(SS(e.what() << " (" << filename.string() << ")"));
}
}
}
if (this->bssid_.length() == 0)
{
configChanged = true;
this->bssid_ = MakeBssid();
}
// copy UI settings into our settings.
WifiDirectConfigSettings wifiDirectSettings; // settings from the UI.
wifiDirectSettings.Load();
valid_ = false;
if (!wifiDirectSettings.valid_)
{
LogError("NMP2PSettings","Load","Wifi Direct Config Settings are not valid.");
return;
}
if (!wifiDirectSettings.enable_)
{
LogError("NMP2PSettings","Load","Wifi Direct service is not enabled.");
return;
}
valid_ = true;
bool updateRegClass = false;
if (this->country_ != wifiDirectSettings.countryCode_)
{
this->country_ = wifiDirectSettings.countryCode_;
configChanged = true;
updateRegClass = true;
}
{
int channel = 1;
std::stringstream ss(wifiDirectSettings.channel_);
ss >> channel;
if (this->op_channel_ != channel || this->listen_channel_ != channel)
{
updateRegClass = true;
configChanged = true;
}
this->op_channel_ = channel;
this->listen_channel_ = channel;
if (updateRegClass || this->listen_reg_class_ == 0 || this->op_reg_class_ == 0)
{
// todo: we currently ignore 80khz ac channels (which pi supports)
//
int32_t reg_class = 0;
if (channel == 0) // don't force a channel
{
reg_class = 0;
} else {
reg_class = getWifiRegClass(this->country_,channel,40);
if (reg_class == -1)
{
throw std::runtime_error(SS("Wifi Channel " << channel << " is not allowed in country " << this->country_));
}
}
configChanged |= this->op_reg_class_ != reg_class;
configChanged |= this->listen_reg_class_ != reg_class;
this->op_reg_class_ = reg_class;
this->listen_reg_class_ = reg_class;
}
}
if (updateRegClass)
{
}
if (wifiDirectSettings.hotspotName_ != this->device_name_)
{
configChanged = true;
this->device_name_ = wifiDirectSettings.hotspotName_;
this->auth_changed_ = true;
}
if (this->pin_ != wifiDirectSettings.pin_)
{
configChanged = true;
this->auth_changed_ = true;
this->pin_ = wifiDirectSettings.pin_;
}
if (this->wlan_ != wifiDirectSettings.wlan_)
{
configChanged = true;
this->auth_changed_ = true;
this->wlan_ = wifiDirectSettings.wlan_;
}
ServiceConfiguration serviceConfiguration;
serviceConfiguration.Load();
if ((int)serviceConfiguration.server_port != this->web_server_port_)
{
configChanged = true;
this->web_server_port_ = (int)serviceConfiguration.server_port;
}
if (this->service_uuid() != serviceConfiguration.uuid)
{
configChanged = true;
this->service_uuid_ = serviceConfiguration.uuid;
}
if (wifiDirectSettings.pinChanged_)
{
wifiDirectSettings.pinChanged_ = false;
wifiDirectSettings.Save();
}
if (configChanged)
{
Save();
}
}
static void openWithPerms(
std::ofstream &f,
const std::filesystem::path &path,
std::filesystem::perms perms =
std::filesystem::perms::owner_read | std::filesystem::perms::owner_write |
std::filesystem::perms::group_read | std::filesystem::perms::group_write)
{
auto directory = path.parent_path();
std::filesystem::create_directories(directory);
// open and close to make an existing empty file.
// close it.
{
std::ofstream f;
f.open(path);
f.close();
}
// set the perms.
std::filesystem::permissions(
path,
perms,
std::filesystem::perm_options::replace);
// open for re3al.
f.open(path);
}
void P2pSettings::Save()
{
auto filename = config_filename();
try {
std::ofstream f;
openWithPerms(f,filename);
if (!f.is_open())
{
throw std::runtime_error("Can't write to file.");
}
json_writer writer{f,false};
writer.write(this);
} catch (const std::exception &e)
{
throw std::runtime_error(SS(e.what() << " (" << filename.string() << ")"));
}
}
int32_t P2pSettings::op_frequency() const
{
return wifiChannelToFrequency(this->op_channel_);
}
JSON_MAP_BEGIN(P2pSettings)
JSON_MAP_REFERENCE(P2pSettings,wlan)
JSON_MAP_REFERENCE(P2pSettings,driver)
JSON_MAP_REFERENCE(P2pSettings,bssid)
JSON_MAP_REFERENCE(P2pSettings,country)
JSON_MAP_REFERENCE(P2pSettings,persistent_reconnect)
JSON_MAP_REFERENCE(P2pSettings,config_methods)
JSON_MAP_REFERENCE(P2pSettings,manufacturer)
JSON_MAP_REFERENCE(P2pSettings,model_name)
JSON_MAP_REFERENCE(P2pSettings,model_number)
JSON_MAP_REFERENCE(P2pSettings,serial_number)
JSON_MAP_REFERENCE(P2pSettings,pin)
JSON_MAP_REFERENCE(P2pSettings,service_uuid)
JSON_MAP_REFERENCE(P2pSettings,listen_channel)
JSON_MAP_REFERENCE(P2pSettings,listen_reg_class)
JSON_MAP_REFERENCE(P2pSettings,op_channel)
JSON_MAP_REFERENCE(P2pSettings,op_reg_class)
JSON_MAP_REFERENCE(P2pSettings,web_server_port)
JSON_MAP_REFERENCE(P2pSettings,device_name)
JSON_MAP_REFERENCE(P2pSettings,auth_changed)
JSON_MAP_END()