3
0
Fork 0
forked from suyu/suyu

common: Extract UUID to its own class

Since the Mii database uses UUIDs very similar to the Accounts database, it makes no sense to not share code between them.
This commit is contained in:
Zach Hilman 2018-12-18 09:07:25 -05:00
parent 78574e7a47
commit ca5638a142
6 changed files with 108 additions and 78 deletions

View file

@ -123,6 +123,8 @@ add_library(common STATIC
timer.h timer.h
uint128.cpp uint128.cpp
uint128.h uint128.h
uuid.cpp
uuid.h
vector_math.h vector_math.h
web_result.h web_result.h
zstd_compression.cpp zstd_compression.cpp

33
src/common/uuid.cpp Normal file
View file

@ -0,0 +1,33 @@
// Copyright 2018 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <random>
#include <fmt/format.h>
#include "common/uuid.h"
namespace Common {
UUID UUID::Generate() {
std::random_device device;
std::mt19937 gen(device());
std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
return UUID{distribution(gen), distribution(gen)};
}
std::string UUID::Format() const {
return fmt::format("0x{:016X}{:016X}", uuid[1], uuid[0]);
}
std::string UUID::FormatSwitch() const {
std::array<u8, 16> s{};
std::memcpy(s.data(), uuid.data(), sizeof(u128));
return fmt::format("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{"
":02x}{:02x}{:02x}{:02x}{:02x}",
s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], s[10], s[11],
s[12], s[13], s[14], s[15]);
}
} // namespace Common

45
src/common/uuid.h Normal file
View file

@ -0,0 +1,45 @@
// Copyright 2018 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common/common_types.h"
namespace Common {
constexpr u128 INVALID_UUID{{0, 0}};
struct UUID {
// UUIDs which are 0 are considered invalid!
u128 uuid = INVALID_UUID;
constexpr UUID() = default;
constexpr explicit UUID(const u128& id) : uuid{id} {}
constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {}
explicit operator bool() const {
return uuid != INVALID_UUID;
}
bool operator==(const UUID& rhs) const {
return uuid == rhs.uuid;
}
bool operator!=(const UUID& rhs) const {
return !operator==(rhs);
}
// TODO(ogniK): Properly generate uuids based on RFC-4122
static UUID Generate();
// Set the UUID to {0,0} to be considered an invalid user
void Invalidate() {
uuid = INVALID_UUID;
}
std::string Format() const;
std::string FormatSwitch() const;
};
static_assert(sizeof(UUID) == 16, "UUID is an invalid size!");
} // namespace Common

View file

@ -34,7 +34,7 @@ constexpr std::array<u8, backup_jpeg_size> backup_jpeg{{
0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9, 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
}}; }};
static std::string GetImagePath(UUID uuid) { static std::string GetImagePath(Common::UUID uuid) {
return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
"/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg";
} }
@ -46,7 +46,7 @@ static constexpr u32 SanitizeJPEGSize(std::size_t size) {
class IProfile final : public ServiceFramework<IProfile> { class IProfile final : public ServiceFramework<IProfile> {
public: public:
explicit IProfile(UUID user_id, ProfileManager& profile_manager) explicit IProfile(Common::UUID user_id, ProfileManager& profile_manager)
: ServiceFramework("IProfile"), profile_manager(profile_manager), user_id(user_id) { : ServiceFramework("IProfile"), profile_manager(profile_manager), user_id(user_id) {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &IProfile::Get, "Get"}, {0, &IProfile::Get, "Get"},
@ -131,7 +131,7 @@ private:
} }
const ProfileManager& profile_manager; const ProfileManager& profile_manager;
UUID user_id; ///< The user id this profile refers to. Common::UUID user_id; ///< The user id this profile refers to.
}; };
class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
@ -179,7 +179,7 @@ void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) {
void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
UUID user_id = rp.PopRaw<UUID>(); Common::UUID user_id = rp.PopRaw<Common::UUID>();
LOG_INFO(Service_ACC, "called user_id={}", user_id.Format()); LOG_INFO(Service_ACC, "called user_id={}", user_id.Format());
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
@ -205,12 +205,12 @@ void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) {
LOG_INFO(Service_ACC, "called"); LOG_INFO(Service_ACC, "called");
IPC::ResponseBuilder rb{ctx, 6}; IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushRaw<UUID>(profile_manager->GetLastOpenedUser()); rb.PushRaw<Common::UUID>(profile_manager->GetLastOpenedUser());
} }
void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) { void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
UUID user_id = rp.PopRaw<UUID>(); Common::UUID user_id = rp.PopRaw<Common::UUID>();
LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format()); LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format());
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@ -245,15 +245,15 @@ void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContex
IPC::ResponseBuilder rb{ctx, 6}; IPC::ResponseBuilder rb{ctx, 6};
if (profile_manager->GetUserCount() != 1) { if (profile_manager->GetUserCount() != 1) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushRaw<u128>(INVALID_UUID); rb.PushRaw<u128>(Common::INVALID_UUID);
return; return;
} }
const auto user_list = profile_manager->GetAllUsers(); const auto user_list = profile_manager->GetAllUsers();
if (std::all_of(user_list.begin(), user_list.end(), if (std::all_of(user_list.begin(), user_list.end(),
[](const auto& user) { return user.uuid == INVALID_UUID; })) { [](const auto& user) { return user.uuid == Common::INVALID_UUID; })) {
rb.Push(ResultCode(-1)); // TODO(ogniK): Find the correct error code rb.Push(ResultCode(-1)); // TODO(ogniK): Find the correct error code
rb.PushRaw<u128>(INVALID_UUID); rb.PushRaw<u128>(Common::INVALID_UUID);
return; return;
} }

View file

@ -13,6 +13,8 @@
namespace Service::Account { namespace Service::Account {
using namespace Common;
struct UserRaw { struct UserRaw {
UUID uuid; UUID uuid;
UUID uuid2; UUID uuid2;
@ -35,26 +37,6 @@ constexpr ResultCode ERROR_ARGUMENT_IS_NULL(ErrorModule::Account, 20);
constexpr char ACC_SAVE_AVATORS_BASE_PATH[] = "/system/save/8000000000000010/su/avators/"; constexpr char ACC_SAVE_AVATORS_BASE_PATH[] = "/system/save/8000000000000010/su/avators/";
UUID UUID::Generate() {
std::random_device device;
std::mt19937 gen(device());
std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
return UUID{distribution(gen), distribution(gen)};
}
std::string UUID::Format() const {
return fmt::format("0x{:016X}{:016X}", uuid[1], uuid[0]);
}
std::string UUID::FormatSwitch() const {
std::array<u8, 16> s{};
std::memcpy(s.data(), uuid.data(), sizeof(u128));
return fmt::format("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{"
":02x}{:02x}{:02x}{:02x}{:02x}",
s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], s[10], s[11],
s[12], s[13], s[14], s[15]);
}
ProfileManager::ProfileManager() { ProfileManager::ProfileManager() {
ParseUserSaveFile(); ParseUserSaveFile();

View file

@ -9,47 +9,15 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/swap.h" #include "common/swap.h"
#include "common/uuid.h"
#include "core/hle/result.h" #include "core/hle/result.h"
namespace Service::Account { namespace Service::Account {
constexpr std::size_t MAX_USERS = 8; constexpr std::size_t MAX_USERS = 8;
constexpr u128 INVALID_UUID{{0, 0}};
struct UUID {
// UUIDs which are 0 are considered invalid!
u128 uuid = INVALID_UUID;
UUID() = default;
explicit UUID(const u128& id) : uuid{id} {}
explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {}
explicit operator bool() const {
return uuid != INVALID_UUID;
}
bool operator==(const UUID& rhs) const {
return uuid == rhs.uuid;
}
bool operator!=(const UUID& rhs) const {
return !operator==(rhs);
}
// TODO(ogniK): Properly generate uuids based on RFC-4122
static UUID Generate();
// Set the UUID to {0,0} to be considered an invalid user
void Invalidate() {
uuid = INVALID_UUID;
}
std::string Format() const;
std::string FormatSwitch() const;
};
static_assert(sizeof(UUID) == 16, "UUID is an invalid size!");
constexpr std::size_t profile_username_size = 32; constexpr std::size_t profile_username_size = 32;
using ProfileUsername = std::array<u8, profile_username_size>; using ProfileUsername = std::array<u8, profile_username_size>;
using UserIDArray = std::array<UUID, MAX_USERS>; using UserIDArray = std::array<Common::UUID, MAX_USERS>;
/// Contains extra data related to a user. /// Contains extra data related to a user.
/// TODO: RE this structure /// TODO: RE this structure
@ -66,7 +34,7 @@ static_assert(sizeof(ProfileData) == 0x80, "ProfileData structure has incorrect
/// This holds general information about a users profile. This is where we store all the information /// This holds general information about a users profile. This is where we store all the information
/// based on a specific user /// based on a specific user
struct ProfileInfo { struct ProfileInfo {
UUID user_uuid; Common::UUID user_uuid;
ProfileUsername username; ProfileUsername username;
u64 creation_time; u64 creation_time;
ProfileData data; // TODO(ognik): Work out what this is ProfileData data; // TODO(ognik): Work out what this is
@ -74,7 +42,7 @@ struct ProfileInfo {
}; };
struct ProfileBase { struct ProfileBase {
UUID user_uuid; Common::UUID user_uuid;
u64_le timestamp; u64_le timestamp;
ProfileUsername username; ProfileUsername username;
@ -96,33 +64,33 @@ public:
~ProfileManager(); ~ProfileManager();
ResultCode AddUser(const ProfileInfo& user); ResultCode AddUser(const ProfileInfo& user);
ResultCode CreateNewUser(UUID uuid, const ProfileUsername& username); ResultCode CreateNewUser(Common::UUID uuid, const ProfileUsername& username);
ResultCode CreateNewUser(UUID uuid, const std::string& username); ResultCode CreateNewUser(Common::UUID uuid, const std::string& username);
std::optional<UUID> GetUser(std::size_t index) const; std::optional<Common::UUID> GetUser(std::size_t index) const;
std::optional<std::size_t> GetUserIndex(const UUID& uuid) const; std::optional<std::size_t> GetUserIndex(const Common::UUID& uuid) const;
std::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const; std::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const;
bool GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const; bool GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const;
bool GetProfileBase(UUID uuid, ProfileBase& profile) const; bool GetProfileBase(Common::UUID uuid, ProfileBase& profile) const;
bool GetProfileBase(const ProfileInfo& user, ProfileBase& profile) const; bool GetProfileBase(const ProfileInfo& user, ProfileBase& profile) const;
bool GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile, bool GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,
ProfileData& data) const; ProfileData& data) const;
bool GetProfileBaseAndData(UUID uuid, ProfileBase& profile, ProfileData& data) const; bool GetProfileBaseAndData(Common::UUID uuid, ProfileBase& profile, ProfileData& data) const;
bool GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile, bool GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile,
ProfileData& data) const; ProfileData& data) const;
std::size_t GetUserCount() const; std::size_t GetUserCount() const;
std::size_t GetOpenUserCount() const; std::size_t GetOpenUserCount() const;
bool UserExists(UUID uuid) const; bool UserExists(Common::UUID uuid) const;
bool UserExistsIndex(std::size_t index) const; bool UserExistsIndex(std::size_t index) const;
void OpenUser(UUID uuid); void OpenUser(Common::UUID uuid);
void CloseUser(UUID uuid); void CloseUser(Common::UUID uuid);
UserIDArray GetOpenUsers() const; UserIDArray GetOpenUsers() const;
UserIDArray GetAllUsers() const; UserIDArray GetAllUsers() const;
UUID GetLastOpenedUser() const; Common::UUID GetLastOpenedUser() const;
bool CanSystemRegisterUser() const; bool CanSystemRegisterUser() const;
bool RemoveUser(UUID uuid); bool RemoveUser(Common::UUID uuid);
bool SetProfileBase(UUID uuid, const ProfileBase& profile_new); bool SetProfileBase(Common::UUID uuid, const ProfileBase& profile_new);
private: private:
void ParseUserSaveFile(); void ParseUserSaveFile();
@ -132,7 +100,7 @@ private:
std::array<ProfileInfo, MAX_USERS> profiles{}; std::array<ProfileInfo, MAX_USERS> profiles{};
std::size_t user_count = 0; std::size_t user_count = 0;
UUID last_opened_user{INVALID_UUID}; Common::UUID last_opened_user{Common::INVALID_UUID};
}; };
}; // namespace Service::Account }; // namespace Service::Account