From ab335ccf1bf43cd49da6eb93e541f0af3b88f72a Mon Sep 17 00:00:00 2001 From: zhupengfei Date: Sat, 27 Oct 2018 15:40:15 +0800 Subject: [PATCH] core, web_service: Changes to announce service Separated registering and updating to correspond to the new announce API endpoint. Also added a verify_UID for JWT audience verification. --- src/common/announce_multiplayer_room.h | 40 ++++++++----- src/core/announce_multiplayer_session.cpp | 53 +++++++++++++----- src/core/announce_multiplayer_session.h | 11 ++++ src/web_service/announce_room_json.cpp | 68 +++++++++++++++++------ src/web_service/announce_room_json.h | 12 ++-- 5 files changed, 135 insertions(+), 49 deletions(-) diff --git a/src/common/announce_multiplayer_room.h b/src/common/announce_multiplayer_room.h index 21f8c5a08..f0cf79386 100644 --- a/src/common/announce_multiplayer_room.h +++ b/src/common/announce_multiplayer_room.h @@ -17,14 +17,17 @@ using MacAddress = std::array; struct Room { struct Member { - std::string name; + std::string username; + std::string nickname; + std::string avatar_url; MacAddress mac_address; std::string game_name; u64 game_id; }; + std::string id; + std::string verify_UID; ///< UID used for verification std::string name; std::string description; - std::string UID; std::string owner; std::string ip; u16 port; @@ -57,9 +60,8 @@ public: * @param preferred_game The preferred game of the room * @param preferred_game_id The title id of the preferred game */ - virtual void SetRoomInformation(const std::string& uid, const std::string& name, - const std::string& description, const u16 port, - const u32 max_player, const u32 net_version, + virtual void SetRoomInformation(const std::string& name, const std::string& description, + const u16 port, const u32 max_player, const u32 net_version, const bool has_password, const std::string& preferred_game, const u64 preferred_game_id) = 0; /** @@ -69,14 +71,21 @@ public: * @param game_id The title id of the game the player plays * @param game_name The name of the game the player plays */ - virtual void AddPlayer(const std::string& nickname, const MacAddress& mac_address, + virtual void AddPlayer(const std::string& username, const std::string& nickname, + const std::string& avatar_url, const MacAddress& mac_address, const u64 game_id, const std::string& game_name) = 0; /** - * Send the data to the announce service - * @result The result of the announce attempt + * Updates the data in the announce service. Re-register the room when required. + * @result The result of the update attempt */ - virtual Common::WebResult Announce() = 0; + virtual Common::WebResult Update() = 0; + + /** + * Registers the data in the announce service + * @result A global Guid of the room which may be used for verification + */ + virtual std::string Register() = 0; /** * Empties the stored players @@ -102,16 +111,19 @@ public: class NullBackend : public Backend { public: ~NullBackend() = default; - void SetRoomInformation(const std::string& /*uid*/, const std::string& /*name*/, - const std::string& /*description*/, const u16 /*port*/, - const u32 /*max_player*/, const u32 /*net_version*/, + void SetRoomInformation(const std::string& /*name*/, const std::string& /*description*/, + const u16 /*port*/, const u32 /*max_player*/, const u32 /*net_version*/, const bool /*has_password*/, const std::string& /*preferred_game*/, const u64 /*preferred_game_id*/) override {} - void AddPlayer(const std::string& /*nickname*/, const MacAddress& /*mac_address*/, + void AddPlayer(const std::string& /*username*/, const std::string& /*nickname*/, + const std::string& /*avatar_url*/, const MacAddress& /*mac_address*/, const u64 /*game_id*/, const std::string& /*game_name*/) override {} - Common::WebResult Announce() override { + Common::WebResult Update() override { return Common::WebResult{Common::WebResult::Code::NoWebservice, "WebService is missing"}; } + std::string Register() override { + return ""; + } void ClearPlayers() override {} RoomList GetRoomList() override { return RoomList{}; diff --git a/src/core/announce_multiplayer_session.cpp b/src/core/announce_multiplayer_session.cpp index 3d2301e0f..e255581f9 100644 --- a/src/core/announce_multiplayer_session.cpp +++ b/src/core/announce_multiplayer_session.cpp @@ -29,6 +29,21 @@ AnnounceMultiplayerSession::AnnounceMultiplayerSession() { #endif } +void AnnounceMultiplayerSession::Register() { + std::shared_ptr room = Network::GetRoom().lock(); + if (!room) { + return; + } + if (room->GetState() != Network::Room::State::Open) { + return; + } + UpdateBackendData(room); + std::string result = backend->Register(); + LOG_INFO(WebService, "Room has been registered"); + room->SetVerifyUID(result); + registered = true; +} + void AnnounceMultiplayerSession::Start() { if (announce_multiplayer_thread) { Stop(); @@ -44,6 +59,7 @@ void AnnounceMultiplayerSession::Stop() { announce_multiplayer_thread->join(); announce_multiplayer_thread.reset(); backend->Delete(); + registered = false; } } @@ -64,7 +80,24 @@ AnnounceMultiplayerSession::~AnnounceMultiplayerSession() { Stop(); } +void AnnounceMultiplayerSession::UpdateBackendData(std::shared_ptr room) { + Network::RoomInformation room_information = room->GetRoomInformation(); + std::vector memberlist = room->GetRoomMemberList(); + backend->SetRoomInformation( + room_information.name, room_information.description, room_information.port, + room_information.member_slots, Network::network_version, room->HasPassword(), + room_information.preferred_game, room_information.preferred_game_id); + backend->ClearPlayers(); + for (const auto& member : memberlist) { + backend->AddPlayer(member.username, member.nickname, member.avatar_url, member.mac_address, + member.game_info.id, member.game_info.name); + } +} + void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() { + if (!registered) { + Register(); + } auto update_time = std::chrono::steady_clock::now(); std::future future; while (!shutdown_event.WaitUntil(update_time)) { @@ -76,25 +109,19 @@ void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() { if (room->GetState() != Network::Room::State::Open) { break; } - Network::RoomInformation room_information = room->GetRoomInformation(); - std::vector memberlist = room->GetRoomMemberList(); - backend->SetRoomInformation(room_information.uid, room_information.name, - room_information.description, room_information.port, - room_information.member_slots, Network::network_version, - room->HasPassword(), room_information.preferred_game, - room_information.preferred_game_id); - backend->ClearPlayers(); - for (const auto& member : memberlist) { - backend->AddPlayer(member.nickname, member.mac_address, member.game_info.id, - member.game_info.name); - } - Common::WebResult result = backend->Announce(); + UpdateBackendData(room); + Common::WebResult result = backend->Update(); if (result.result_code != Common::WebResult::Code::Success) { std::lock_guard lock(callback_mutex); for (auto callback : error_callbacks) { (*callback)(result); } } + if (result.result_string == "404") { + registered = false; + // Needs to register the room again + Register(); + } } } diff --git a/src/core/announce_multiplayer_session.h b/src/core/announce_multiplayer_session.h index b9ba4c48a..79b30fb24 100644 --- a/src/core/announce_multiplayer_session.h +++ b/src/core/announce_multiplayer_session.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -13,6 +14,10 @@ #include "common/common_types.h" #include "common/thread.h" +namespace Network { +class Room; +} + namespace Core { /** @@ -39,6 +44,9 @@ public: */ void UnbindErrorCallback(CallbackHandle handle); + /// Registers a room to web services + void Register(); + /** * Starts the announce of a room to web services */ @@ -65,6 +73,9 @@ private: /// Backend interface that logs fields std::unique_ptr backend; + std::atomic_bool registered = false; ///< Whether the room has been registered + + void UpdateBackendData(std::shared_ptr room); void AnnounceMultiplayerLoop(); }; diff --git a/src/web_service/announce_room_json.cpp b/src/web_service/announce_room_json.cpp index 970c5e0b6..f1a690443 100644 --- a/src/web_service/announce_room_json.cpp +++ b/src/web_service/announce_room_json.cpp @@ -12,22 +12,36 @@ namespace AnnounceMultiplayerRoom { void to_json(nlohmann::json& json, const Room::Member& member) { - json["name"] = member.name; + if (!member.username.empty()) { + json["username"] = member.username; + } + json["nickname"] = member.nickname; + if (!member.avatar_url.empty()) { + json["avatarUrl"] = member.avatar_url; + } json["gameName"] = member.game_name; json["gameId"] = member.game_id; } void from_json(const nlohmann::json& json, Room::Member& member) { - member.name = json.at("name").get(); + member.nickname = json.at("nickname").get(); member.game_name = json.at("gameName").get(); member.game_id = json.at("gameId").get(); + try { + member.username = json.at("username").get(); + member.avatar_url = json.at("avatarUrl").get(); + } catch (const nlohmann::detail::out_of_range& e) { + member.username = member.avatar_url = ""; + LOG_DEBUG(Network, "Member \'{}\' isn't authenticated", member.nickname); + } } void to_json(nlohmann::json& json, const Room& room) { - json["id"] = room.UID; json["port"] = room.port; json["name"] = room.name; - json["description"] = room.description; + if (!room.description.empty()) { + json["description"] = room.description; + } json["preferredGameName"] = room.preferred_game; json["preferredGameId"] = room.preferred_game_id; json["maxPlayers"] = room.max_player; @@ -40,6 +54,7 @@ void to_json(nlohmann::json& json, const Room& room) { } void from_json(const nlohmann::json& json, Room& room) { + room.verify_UID = json.at("externalGuid").get(); room.ip = json.at("address").get(); room.name = json.at("name").get(); try { @@ -66,14 +81,12 @@ void from_json(const nlohmann::json& json, Room& room) { namespace WebService { -void RoomJson::SetRoomInformation(const std::string& uid, const std::string& name, - const std::string& description, const u16 port, - const u32 max_player, const u32 net_version, +void RoomJson::SetRoomInformation(const std::string& name, const std::string& description, + const u16 port, const u32 max_player, const u32 net_version, const bool has_password, const std::string& preferred_game, const u64 preferred_game_id) { room.name = name; room.description = description; - room.UID = uid; room.port = port; room.max_player = max_player; room.net_version = net_version; @@ -81,20 +94,39 @@ void RoomJson::SetRoomInformation(const std::string& uid, const std::string& nam room.preferred_game = preferred_game; room.preferred_game_id = preferred_game_id; } -void RoomJson::AddPlayer(const std::string& nickname, +void RoomJson::AddPlayer(const std::string& username, const std::string& nickname, + const std::string& avatar_url, const AnnounceMultiplayerRoom::MacAddress& mac_address, const u64 game_id, const std::string& game_name) { AnnounceMultiplayerRoom::Room::Member member; - member.name = nickname; + member.username = username; + member.nickname = nickname; + member.avatar_url = avatar_url; member.mac_address = mac_address; member.game_id = game_id; member.game_name = game_name; room.members.push_back(member); } -Common::WebResult RoomJson::Announce() { +Common::WebResult RoomJson::Update() { + if (room_id.empty()) { + LOG_ERROR(WebService, "Room must be registered to be updated"); + return Common::WebResult{Common::WebResult::Code::LibError, "Room is not registered"}; + } + nlohmann::json json{{"players", room.members}}; + return client.PostJson(fmt::format("/lobby2/{}", room_id), json.dump(), false); +} + +std::string RoomJson::Register() { nlohmann::json json = room; - return client.PostJson("/lobby", json.dump(), false); + auto reply = client.PostJson("/lobby2", json.dump(), false).returned_data; + if (reply.empty()) { + return ""; + } + auto reply_json = nlohmann::json::parse(reply); + room = reply_json.get(); + room_id = reply_json.at("id").get(); + return room.verify_UID; } void RoomJson::ClearPlayers() { @@ -102,7 +134,7 @@ void RoomJson::ClearPlayers() { } AnnounceMultiplayerRoom::RoomList RoomJson::GetRoomList() { - auto reply = client.GetJson("/lobby", true).returned_data; + auto reply = client.GetJson("/lobby2", true).returned_data; if (reply.empty()) { return {}; } @@ -110,12 +142,14 @@ AnnounceMultiplayerRoom::RoomList RoomJson::GetRoomList() { } void RoomJson::Delete() { - nlohmann::json json; - json["id"] = room.UID; + if (room_id.empty()) { + LOG_ERROR(WebService, "Room must be registered to be deleted"); + return; + } Common::DetachedTasks::AddTask( - [host{this->host}, username{this->username}, token{this->token}, content{json.dump()}]() { + [host{this->host}, username{this->username}, token{this->token}, room_id{this->room_id}]() { // create a new client here because the this->client might be destroyed. - Client{host, username, token}.DeleteJson("/lobby", content, false); + Client{host, username, token}.DeleteJson(fmt::format("/lobby2/{}", room_id), "", false); }); } diff --git a/src/web_service/announce_room_json.h b/src/web_service/announce_room_json.h index 57152c243..16d630863 100644 --- a/src/web_service/announce_room_json.h +++ b/src/web_service/announce_room_json.h @@ -20,15 +20,16 @@ public: RoomJson(const std::string& host, const std::string& username, const std::string& token) : client(host, username, token), host(host), username(username), token(token) {} ~RoomJson() = default; - void SetRoomInformation(const std::string& uid, const std::string& name, - const std::string& description, const u16 port, const u32 max_player, - const u32 net_version, const bool has_password, + void SetRoomInformation(const std::string& name, const std::string& description, const u16 port, + const u32 max_player, const u32 net_version, const bool has_password, const std::string& preferred_game, const u64 preferred_game_id) override; - void AddPlayer(const std::string& nickname, + void AddPlayer(const std::string& username, const std::string& nickname, + const std::string& avatar_url, const AnnounceMultiplayerRoom::MacAddress& mac_address, const u64 game_id, const std::string& game_name) override; - Common::WebResult Announce() override; + Common::WebResult Update() override; + std::string Register() override; void ClearPlayers() override; AnnounceMultiplayerRoom::RoomList GetRoomList() override; void Delete() override; @@ -39,6 +40,7 @@ private: std::string host; std::string username; std::string token; + std::string room_id; }; } // namespace WebService