1// Copyright 2015 The Weave Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/privet/wifi_ssid_generator.h" 6 7#include <bitset> 8 9#include <base/bind.h> 10#include <base/rand_util.h> 11#include <base/strings/string_number_conversions.h> 12#include <base/strings/stringprintf.h> 13 14#include "src/privet/cloud_delegate.h" 15#include "src/privet/device_delegate.h" 16#include "src/privet/wifi_delegate.h" 17 18namespace weave { 19namespace privet { 20 21namespace { 22 23const int kDeviceNameSize = 20; 24// [DeviceName+Idx <= 20].[modelID == 5][flags == 2]prv 25const char kSsidFormat[] = "%s %s.%5.5s%2.2sprv"; 26 27const char base64chars[] = 28 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 29 30bool IsSetupNeeded(const ConnectionState& state) { 31 if (state.error()) 32 return true; 33 switch (state.status()) { 34 case ConnectionState::kUnconfigured: 35 return true; 36 case ConnectionState::kDisabled: 37 case ConnectionState::kConnecting: 38 case ConnectionState::kOnline: 39 case ConnectionState::kOffline: 40 return false; 41 } 42 CHECK(false); 43 return false; 44} 45 46} // namespace 47 48WifiSsidGenerator::WifiSsidGenerator(const CloudDelegate* cloud, 49 const WifiDelegate* wifi) 50 : gcd_(cloud), wifi_(wifi), get_random_(base::Bind(&base::RandInt, 0, 99)) { 51 CHECK(gcd_); 52} 53 54std::string WifiSsidGenerator::GenerateFlags() const { 55 return GenerateFlagsInternal(); 56} 57 58std::string WifiSsidGenerator::GenerateFlagsInternal() const { 59 std::bitset<6> flags1; 60 // Device needs WiFi configuration. 61 flags1[0] = wifi_ && IsSetupNeeded(wifi_->GetConnectionState()); 62 63 // Device needs GCD registration. 64 flags1[1] = IsSetupNeeded(gcd_->GetConnectionState()); 65 66 std::bitset<6> flags2; 67 68 if (wifi_) { 69 std::set<WifiType> types = wifi_->GetTypes(); 70 // Device supports 2.4Ghz WiFi networks. 71 flags2[0] = types.find(WifiType::kWifi24) != types.end(); 72 73 // Device supports 5.0Ghz WiFi networks. 74 flags2[1] = types.find(WifiType::kWifi50) != types.end(); 75 } 76 77 std::string result{2, base64chars[0]}; 78 result[0] = base64chars[flags1.to_ulong()]; 79 result[1] = base64chars[flags2.to_ulong()]; 80 return result; 81} 82 83std::string WifiSsidGenerator::GenerateSsid() const { 84 std::string name = gcd_->GetName(); 85 std::string model_id = gcd_->GetModelId(); 86 std::string idx = base::IntToString(get_random_.Run()); 87 name = name.substr(0, kDeviceNameSize - idx.size() - 1); 88 CHECK_EQ(5u, model_id.size()); 89 90 std::string result = 91 base::StringPrintf(kSsidFormat, name.c_str(), idx.c_str(), 92 model_id.c_str(), GenerateFlagsInternal().c_str()); 93 CHECK_EQ(result[result.size() - 11], '.'); 94 return result; 95} 96 97void WifiSsidGenerator::SetRandomForTests(int n) { 98 get_random_ = base::Bind(&base::RandInt, n, n); 99} 100 101} // namespace privet 102} // namespace weave 103