diff --git a/src/dedicated_room/citra-room.cpp b/src/dedicated_room/citra-room.cpp index 9246b5797..8e2938006 100644 --- a/src/dedicated_room/citra-room.cpp +++ b/src/dedicated_room/citra-room.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include #include #include @@ -27,10 +28,12 @@ #include "common/common_types.h" #include "common/detached_tasks.h" #include "common/scm_rev.h" +#include "common/string_util.h" #include "core/announce_multiplayer_session.h" #include "core/core.h" #include "core/settings.h" #include "network/network.h" +#include "network/room.h" #include "network/verify_user.h" #ifdef ENABLE_WEB_SERVICE @@ -50,6 +53,7 @@ static void PrintHelp(const char* argv0) { "--username The username used for announce\n" "--token The token used for announce\n" "--web-api-url Citra Web API url\n" + "--ban-list-file The file for storing the room ban list\n" "-h, --help Display this help and exit\n" "-v, --version Output version information and exit\n"; } @@ -59,6 +63,71 @@ static void PrintVersion() { << " Libnetwork: " << Network::network_version << std::endl; } +/// The magic text at the beginning of a citra-room ban list file. +static constexpr char BanListMagic[] = "CitraRoom-BanList-1"; + +static Network::Room::BanList LoadBanList(const std::string& path) { + std::ifstream file; + OpenFStream(file, path, std::ios_base::in); + if (!file || file.eof()) { + std::cout << "Could not open ban list!\n\n"; + return {}; + } + std::string magic; + std::getline(file, magic); + if (magic != BanListMagic) { + std::cout << "Ban list is not valid!\n\n"; + return {}; + } + + // false = username ban list, true = ip ban list + bool ban_list_type = false; + Network::Room::UsernameBanList username_ban_list; + Network::Room::IPBanList ip_ban_list; + while (!file.eof()) { + std::string line; + std::getline(file, line); + line.erase(std::remove(line.begin(), line.end(), '\0'), line.end()); + line = Common::StripSpaces(line); + if (line.empty()) { + // An empty line marks start of the IP ban list + ban_list_type = true; + continue; + } + if (ban_list_type) { + ip_ban_list.emplace_back(line); + } else { + username_ban_list.emplace_back(line); + } + } + + return {username_ban_list, ip_ban_list}; +} + +static void SaveBanList(const Network::Room::BanList& ban_list, const std::string& path) { + std::ofstream file; + OpenFStream(file, path, std::ios_base::out); + if (!file) { + std::cout << "Could not save ban list!\n\n"; + return; + } + + file << BanListMagic << "\n"; + + // Username ban list + for (const auto& username : ban_list.first) { + file << username << "\n"; + } + file << "\n"; + + // IP ban list + for (const auto& ip : ban_list.second) { + file << ip << "\n"; + } + + file.flush(); +} + /// Application entry point int main(int argc, char** argv) { Common::DetachedTasks detached_tasks; @@ -75,6 +144,7 @@ int main(int argc, char** argv) { std::string username; std::string token; std::string web_api_url; + std::string ban_list_file; u64 preferred_game_id = 0; u32 port = Network::DefaultRoomPort; u32 max_members = 16; @@ -90,6 +160,7 @@ int main(int argc, char** argv) { {"username", required_argument, 0, 'u'}, {"token", required_argument, 0, 't'}, {"web-api-url", required_argument, 0, 'a'}, + {"ban-list-file", required_argument, 0, 'b'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, {0, 0, 0, 0}, @@ -129,6 +200,9 @@ int main(int argc, char** argv) { case 'a': web_api_url.assign(optarg); break; + case 'b': + ban_list_file.assign(optarg); + break; case 'h': PrintHelp(argv[0]); return 0; @@ -164,6 +238,10 @@ int main(int argc, char** argv) { PrintHelp(argv[0]); return -1; } + if (ban_list_file.empty()) { + std::cout << "Ban list file not set!\nThis should get set to load and save room ban " + "list.\nSet with --ban-list-file \n\n"; + } bool announce = true; if (username.empty()) { announce = false; @@ -184,6 +262,12 @@ int main(int argc, char** argv) { Settings::values.citra_token = token; } + // Load the ban list + Network::Room::BanList ban_list; + if (!ban_list_file.empty()) { + ban_list = LoadBanList(ban_list_file); + } + std::unique_ptr verify_backend; if (announce) { #ifdef ENABLE_WEB_SERVICE @@ -199,8 +283,8 @@ int main(int argc, char** argv) { Network::Init(); if (std::shared_ptr room = Network::GetRoom().lock()) { - if (!room->Create(room_name, room_description, "", port, password, max_members, - preferred_game, preferred_game_id, std::move(verify_backend))) { + if (!room->Create(room_name, room_description, "", port, password, max_members, username, + preferred_game, preferred_game_id, std::move(verify_backend), ban_list)) { std::cout << "Failed to create room: \n\n"; return -1; } @@ -217,6 +301,10 @@ int main(int argc, char** argv) { announce_session->Stop(); } announce_session.reset(); + // Save the ban list + if (!ban_list_file.empty()) { + SaveBanList(room->GetBanList(), ban_list_file); + } room->Destroy(); Network::Shutdown(); return 0; @@ -227,6 +315,10 @@ int main(int argc, char** argv) { announce_session->Stop(); } announce_session.reset(); + // Save the ban list + if (!ban_list_file.empty()) { + SaveBanList(room->GetBanList(), ban_list_file); + } room->Destroy(); } Network::Shutdown();