// Copyright 2015 The Weave 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 "src/privet/wifi_ssid_generator.h" #include <bitset> #include <base/bind.h> #include <base/rand_util.h> #include <base/strings/string_number_conversions.h> #include <base/strings/stringprintf.h> #include "src/privet/cloud_delegate.h" #include "src/privet/device_delegate.h" #include "src/privet/wifi_delegate.h" namespace weave { namespace privet { namespace { const int kDeviceNameSize = 20; // [DeviceName+Idx <= 20].[modelID == 5][flags == 2]prv const char kSsidFormat[] = "%s %s.%5.5s%2.2sprv"; const char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; bool IsSetupNeeded(const ConnectionState& state) { if (state.error()) return true; switch (state.status()) { case ConnectionState::kUnconfigured: return true; case ConnectionState::kDisabled: case ConnectionState::kConnecting: case ConnectionState::kOnline: case ConnectionState::kOffline: return false; } CHECK(false); return false; } } // namespace WifiSsidGenerator::WifiSsidGenerator(const CloudDelegate* cloud, const WifiDelegate* wifi) : gcd_(cloud), wifi_(wifi), get_random_(base::Bind(&base::RandInt, 0, 99)) { CHECK(gcd_); } std::string WifiSsidGenerator::GenerateFlags() const { return GenerateFlagsInternal(); } std::string WifiSsidGenerator::GenerateFlagsInternal() const { std::bitset<6> flags1; // Device needs WiFi configuration. flags1[0] = wifi_ && IsSetupNeeded(wifi_->GetConnectionState()); // Device needs GCD registration. flags1[1] = IsSetupNeeded(gcd_->GetConnectionState()); std::bitset<6> flags2; if (wifi_) { std::set<WifiType> types = wifi_->GetTypes(); // Device supports 2.4Ghz WiFi networks. flags2[0] = types.find(WifiType::kWifi24) != types.end(); // Device supports 5.0Ghz WiFi networks. flags2[1] = types.find(WifiType::kWifi50) != types.end(); } std::string result{2, base64chars[0]}; result[0] = base64chars[flags1.to_ulong()]; result[1] = base64chars[flags2.to_ulong()]; return result; } std::string WifiSsidGenerator::GenerateSsid() const { std::string name = gcd_->GetName(); std::string model_id = gcd_->GetModelId(); std::string idx = base::IntToString(get_random_.Run()); name = name.substr(0, kDeviceNameSize - idx.size() - 1); CHECK_EQ(5u, model_id.size()); std::string result = base::StringPrintf(kSsidFormat, name.c_str(), idx.c_str(), model_id.c_str(), GenerateFlagsInternal().c_str()); CHECK_EQ(result[result.size() - 11], '.'); return result; } void WifiSsidGenerator::SetRandomForTests(int n) { get_random_ = base::Bind(&base::RandInt, n, n); } } // namespace privet } // namespace weave