Browse Source

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.
pull/15/merge
Zach Hilman 7 years ago
parent
commit
ca5638a142
  1. 2
      src/common/CMakeLists.txt
  2. 33
      src/common/uuid.cpp
  3. 45
      src/common/uuid.h
  4. 18
      src/core/hle/service/acc/acc.cpp
  5. 22
      src/core/hle/service/acc/profile_manager.cpp
  6. 66
      src/core/hle/service/acc/profile_manager.h

2
src/common/CMakeLists.txt

@ -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

@ -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

@ -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

18
src/core/hle/service/acc/acc.cpp

@ -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;
} }

22
src/core/hle/service/acc/profile_manager.cpp

@ -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();

66
src/core/hle/service/acc/profile_manager.h

@ -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(UUID uuid, const std::string& username);
std::optional<UUID> GetUser(std::size_t index) const;
std::optional<std::size_t> GetUserIndex(const UUID& uuid) const;
ResultCode CreateNewUser(Common::UUID uuid, const ProfileUsername& username);
ResultCode CreateNewUser(Common::UUID uuid, const std::string& username);
std::optional<Common::UUID> GetUser(std::size_t index) 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 CloseUser(UUID uuid);
void OpenUser(Common::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 SetProfileBase(UUID uuid, const ProfileBase& profile_new);
bool RemoveUser(Common::UUID uuid);
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
Loading…
Cancel
Save