@ -3,6 +3,7 @@
// Refer to the license.txt file included.
# include <chrono>
# include <fstream>
# include <iostream>
# include <memory>
# include <regex>
@ -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! \n This should get set to load and save room ban "
" list. \n Set with --ban-list-file <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 < Network : : VerifyUser : : Backend > verify_backend ;
if ( announce ) {
# ifdef ENABLE_WEB_SERVICE
@ -199,8 +283,8 @@ int main(int argc, char** argv) {
Network : : Init ( ) ;
if ( std : : shared_ptr < Network : : Room > 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 ( ) ;