NetPlayServer.cpp 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502
  1. // Copyright 2010 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "Core/NetPlayServer.h"
  4. #include <algorithm>
  5. #include <chrono>
  6. #include <cstddef>
  7. #include <cstdio>
  8. #include <memory>
  9. #include <mutex>
  10. #include <optional>
  11. #include <string>
  12. #include <thread>
  13. #include <type_traits>
  14. #include <unordered_set>
  15. #include <utility>
  16. #include <vector>
  17. #include <fmt/format.h>
  18. #include <fmt/ranges.h>
  19. #include "Common/CommonPaths.h"
  20. #include "Common/ENet.h"
  21. #include "Common/FileUtil.h"
  22. #include "Common/HttpRequest.h"
  23. #include "Common/Logging/Log.h"
  24. #include "Common/MsgHandler.h"
  25. #include "Common/SFMLHelper.h"
  26. #include "Common/StringUtil.h"
  27. #include "Common/UPnP.h"
  28. #include "Common/Version.h"
  29. #include "Core/ActionReplay.h"
  30. #include "Core/Boot/Boot.h"
  31. #include "Core/Config/GraphicsSettings.h"
  32. #include "Core/Config/MainSettings.h"
  33. #include "Core/Config/NetplaySettings.h"
  34. #include "Core/Config/SYSCONFSettings.h"
  35. #include "Core/Config/SessionSettings.h"
  36. #include "Core/ConfigLoaders/GameConfigLoader.h"
  37. #include "Core/ConfigManager.h"
  38. #include "Core/GeckoCode.h"
  39. #include "Core/GeckoCodeConfig.h"
  40. #include "Core/HW/EXI/EXI.h"
  41. #include "Core/HW/EXI/EXI_Device.h"
  42. #ifdef HAS_LIBMGBA
  43. #include "Core/HW/GBACore.h"
  44. #endif
  45. #include "Core/HW/GCMemcard/GCMemcard.h"
  46. #include "Core/HW/GCMemcard/GCMemcardDirectory.h"
  47. #include "Core/HW/GCMemcard/GCMemcardRaw.h"
  48. #include "Core/HW/Sram.h"
  49. #include "Core/HW/WiiSave.h"
  50. #include "Core/HW/WiiSaveStructs.h"
  51. #include "Core/HW/WiimoteEmu/DesiredWiimoteState.h"
  52. #include "Core/HW/WiimoteEmu/WiimoteEmu.h"
  53. #include "Core/HW/WiimoteReal/WiimoteReal.h"
  54. #include "Core/IOS/ES/ES.h"
  55. #include "Core/IOS/FS/FileSystem.h"
  56. #include "Core/IOS/IOS.h"
  57. #include "Core/IOS/Uids.h"
  58. #include "Core/NetPlayClient.h" //for NetPlayUI
  59. #include "Core/NetPlayCommon.h"
  60. #include "Core/SyncIdentifier.h"
  61. #include "DiscIO/Enums.h"
  62. #include "DiscIO/RiivolutionPatcher.h"
  63. #include "InputCommon/ControllerEmu/ControlGroup/Attachments.h"
  64. #include "InputCommon/GCPadStatus.h"
  65. #include "InputCommon/InputConfig.h"
  66. #include "UICommon/GameFile.h"
  67. #if !defined(_WIN32)
  68. #include <sys/socket.h>
  69. #include <sys/types.h>
  70. #ifdef __HAIKU__
  71. #define _BSD_SOURCE
  72. #include <bsd/ifaddrs.h>
  73. #elif !defined ANDROID
  74. #include <ifaddrs.h>
  75. #endif
  76. #include <arpa/inet.h>
  77. #endif
  78. namespace NetPlay
  79. {
  80. NetPlayServer::~NetPlayServer()
  81. {
  82. if (is_connected)
  83. {
  84. m_do_loop = false;
  85. m_chunked_data_event.Set();
  86. m_chunked_data_complete_event.Set();
  87. if (m_chunked_data_thread.joinable())
  88. m_chunked_data_thread.join();
  89. m_thread.join();
  90. enet_host_destroy(m_server);
  91. if (Common::g_MainNetHost.get() == m_server)
  92. {
  93. Common::g_MainNetHost.release();
  94. }
  95. if (m_traversal_client)
  96. {
  97. Common::g_TraversalClient->m_Client = nullptr;
  98. Common::ReleaseTraversalClient();
  99. }
  100. }
  101. #ifdef USE_UPNP
  102. Common::UPnP::StopPortmapping();
  103. #endif
  104. }
  105. // called from ---GUI--- thread
  106. NetPlayServer::NetPlayServer(const u16 port, const bool forward_port, NetPlayUI* dialog,
  107. const NetTraversalConfig& traversal_config)
  108. : m_dialog(dialog)
  109. {
  110. //--use server time
  111. if (enet_initialize() != 0)
  112. {
  113. PanicAlertFmtT("Enet Didn't Initialize");
  114. }
  115. m_pad_map.fill(0);
  116. m_gba_config.fill({});
  117. m_wiimote_map.fill(0);
  118. if (traversal_config.use_traversal)
  119. {
  120. if (!Common::EnsureTraversalClient(traversal_config.traversal_host,
  121. traversal_config.traversal_port,
  122. traversal_config.traversal_port_alt, port))
  123. {
  124. return;
  125. }
  126. Common::g_TraversalClient->m_Client = this;
  127. m_traversal_client = Common::g_TraversalClient.get();
  128. m_server = Common::g_MainNetHost.get();
  129. if (Common::g_TraversalClient->HasFailed())
  130. Common::g_TraversalClient->ReconnectToServer();
  131. }
  132. else
  133. {
  134. ENetAddress serverAddr;
  135. serverAddr.host = ENET_HOST_ANY;
  136. serverAddr.port = port;
  137. m_server = enet_host_create(&serverAddr, 10, CHANNEL_COUNT, 0, 0);
  138. if (m_server != nullptr)
  139. {
  140. m_server->mtu = std::min(m_server->mtu, NetPlay::MAX_ENET_MTU);
  141. m_server->intercept = Common::ENet::InterceptCallback;
  142. }
  143. SetupIndex();
  144. }
  145. if (m_server != nullptr)
  146. {
  147. is_connected = true;
  148. m_do_loop = true;
  149. m_thread = std::thread(&NetPlayServer::ThreadFunc, this);
  150. m_target_buffer_size = 5;
  151. m_chunked_data_thread = std::thread(&NetPlayServer::ChunkedDataThreadFunc, this);
  152. #ifdef USE_UPNP
  153. if (forward_port && !traversal_config.use_traversal)
  154. Common::UPnP::TryPortmapping(port);
  155. #endif
  156. }
  157. }
  158. static PlayerId* PeerPlayerId(ENetPeer* peer)
  159. {
  160. return static_cast<PlayerId*>(peer->data);
  161. }
  162. static void ClearPeerPlayerId(ENetPeer* peer)
  163. {
  164. if (peer->data)
  165. {
  166. delete PeerPlayerId(peer);
  167. peer->data = nullptr;
  168. }
  169. }
  170. void NetPlayServer::SetupIndex()
  171. {
  172. if (!Config::Get(Config::NETPLAY_USE_INDEX) || Config::Get(Config::NETPLAY_INDEX_NAME).empty() ||
  173. Config::Get(Config::NETPLAY_INDEX_REGION).empty())
  174. {
  175. return;
  176. }
  177. NetPlaySession session;
  178. session.name = Config::Get(Config::NETPLAY_INDEX_NAME);
  179. session.region = Config::Get(Config::NETPLAY_INDEX_REGION);
  180. session.has_password = !Config::Get(Config::NETPLAY_INDEX_PASSWORD).empty();
  181. session.method = m_traversal_client ? "traversal" : "direct";
  182. session.game_id = m_selected_game_name.empty() ? "UNKNOWN" : m_selected_game_name;
  183. session.player_count = static_cast<int>(m_players.size());
  184. session.in_game = m_is_running;
  185. session.port = GetPort();
  186. if (m_traversal_client)
  187. {
  188. if (!m_traversal_client->IsConnected())
  189. return;
  190. session.server_id = std::string(Common::g_TraversalClient->GetHostID().data(), 8);
  191. }
  192. else
  193. {
  194. Common::HttpRequest request;
  195. // ENet does not support IPv6, so IPv4 has to be used
  196. request.UseIPv4();
  197. Common::HttpRequest::Response response =
  198. request.Get("https://ip.dolphin-emu.org/", {{"X-Is-Dolphin", "1"}});
  199. if (!response.has_value())
  200. return;
  201. session.server_id = std::string(response->begin(), response->end());
  202. }
  203. session.EncryptID(Config::Get(Config::NETPLAY_INDEX_PASSWORD));
  204. bool success = m_index.Add(session);
  205. if (m_dialog != nullptr)
  206. m_dialog->OnIndexAdded(success, success ? "" : m_index.GetLastError());
  207. m_index.SetErrorCallback([this] {
  208. if (m_dialog != nullptr)
  209. m_dialog->OnIndexRefreshFailed(m_index.GetLastError());
  210. });
  211. }
  212. // called from ---NETPLAY--- thread
  213. void NetPlayServer::ThreadFunc()
  214. {
  215. INFO_LOG_FMT(NETPLAY, "NetPlayServer starting.");
  216. while (m_do_loop)
  217. {
  218. // update pings every so many seconds
  219. if ((m_ping_timer.ElapsedMs() > 1000) || m_update_pings)
  220. {
  221. // only used as an identifier, not time value, so truncation is fine
  222. m_ping_key = static_cast<u32>(Common::Timer::NowMs());
  223. sf::Packet spac;
  224. spac << MessageID::Ping;
  225. spac << m_ping_key;
  226. m_ping_timer.Start();
  227. SendToClients(spac);
  228. m_index.SetPlayerCount(static_cast<int>(m_players.size()));
  229. m_index.SetGame(m_selected_game_name);
  230. m_index.SetInGame(m_is_running);
  231. m_update_pings = false;
  232. }
  233. ENetEvent netEvent;
  234. int net;
  235. if (m_traversal_client)
  236. m_traversal_client->HandleResends();
  237. net = enet_host_service(m_server, &netEvent, 1000);
  238. while (!m_async_queue.Empty())
  239. {
  240. INFO_LOG_FMT(NETPLAY, "Processing async queue event.");
  241. {
  242. std::lock_guard lkp(m_crit.players);
  243. INFO_LOG_FMT(NETPLAY, "Locked player mutex.");
  244. auto& e = m_async_queue.Front();
  245. if (e.target_mode == TargetMode::Only)
  246. {
  247. if (m_players.contains(e.target_pid))
  248. Send(m_players.at(e.target_pid).socket, e.packet, e.channel_id);
  249. }
  250. else
  251. {
  252. SendToClients(e.packet, e.target_pid, e.channel_id);
  253. }
  254. }
  255. INFO_LOG_FMT(NETPLAY, "Processing async queue event done.");
  256. m_async_queue.Pop();
  257. }
  258. if (net > 0)
  259. {
  260. switch (netEvent.type)
  261. {
  262. case ENET_EVENT_TYPE_CONNECT:
  263. {
  264. // Actual client initialization is deferred to the receive event, so here
  265. // we'll just log the new connection.
  266. INFO_LOG_FMT(NETPLAY, "Peer connected from: {:x}:{}", netEvent.peer->address.host,
  267. netEvent.peer->address.port);
  268. }
  269. break;
  270. case ENET_EVENT_TYPE_RECEIVE:
  271. {
  272. INFO_LOG_FMT(NETPLAY, "enet_host_service: receive event");
  273. sf::Packet rpac;
  274. rpac.append(netEvent.packet->data, netEvent.packet->dataLength);
  275. if (!netEvent.peer->data)
  276. {
  277. // uninitialized client, we'll assume this is their initialization packet
  278. ConnectionError error;
  279. {
  280. INFO_LOG_FMT(NETPLAY, "Initializing peer {:x}:{}", netEvent.peer->address.host,
  281. netEvent.peer->address.port);
  282. std::lock_guard lkg(m_crit.game);
  283. error = OnConnect(netEvent.peer, rpac);
  284. }
  285. if (error != ConnectionError::NoError)
  286. {
  287. INFO_LOG_FMT(NETPLAY, "Error {} initializing peer {:x}:{}", u8(error),
  288. netEvent.peer->address.host, netEvent.peer->address.port);
  289. sf::Packet spac;
  290. spac << error;
  291. // don't need to lock, this client isn't in the client map
  292. Send(netEvent.peer, spac);
  293. ClearPeerPlayerId(netEvent.peer);
  294. enet_peer_disconnect_later(netEvent.peer, 0);
  295. }
  296. }
  297. else
  298. {
  299. auto it = m_players.find(*PeerPlayerId(netEvent.peer));
  300. Client& client = it->second;
  301. if (OnData(rpac, client) != 0)
  302. {
  303. INFO_LOG_FMT(NETPLAY, "Invalid packet from client {}, disconnecting.", client.pid);
  304. // if a bad packet is received, disconnect the client
  305. std::lock_guard lkg(m_crit.game);
  306. OnDisconnect(client);
  307. ClearPeerPlayerId(netEvent.peer);
  308. }
  309. else
  310. {
  311. INFO_LOG_FMT(NETPLAY, "successfully handled packet from client {}", client.pid);
  312. }
  313. }
  314. enet_packet_destroy(netEvent.packet);
  315. }
  316. break;
  317. case ENET_EVENT_TYPE_DISCONNECT:
  318. {
  319. INFO_LOG_FMT(NETPLAY, "enet_host_service: disconnect event");
  320. std::lock_guard lkg(m_crit.game);
  321. if (!netEvent.peer->data)
  322. {
  323. ERROR_LOG_FMT(NETPLAY, "enet_host_service: no peer data");
  324. break;
  325. }
  326. const auto player_id = *PeerPlayerId(netEvent.peer);
  327. auto it = m_players.find(player_id);
  328. if (it != m_players.end())
  329. {
  330. Client& client = it->second;
  331. INFO_LOG_FMT(NETPLAY, "Disconnecting client {}.", client.pid);
  332. OnDisconnect(client);
  333. ClearPeerPlayerId(netEvent.peer);
  334. }
  335. else
  336. {
  337. ERROR_LOG_FMT(NETPLAY, "Invalid player {} to disconnect.", player_id);
  338. }
  339. }
  340. break;
  341. default:
  342. // not a valid switch case due to not technically being part of the enum
  343. if (static_cast<int>(netEvent.type) == Common::ENet::SKIPPABLE_EVENT)
  344. INFO_LOG_FMT(NETPLAY, "enet_host_service: skippable packet event");
  345. else
  346. ERROR_LOG_FMT(NETPLAY, "enet_host_service: unknown event type: {}", int(netEvent.type));
  347. break;
  348. }
  349. }
  350. else if (net == 0)
  351. {
  352. INFO_LOG_FMT(NETPLAY, "enet_host_service: no event occurred");
  353. }
  354. else
  355. {
  356. ERROR_LOG_FMT(NETPLAY, "enet_host_service error: {}", net);
  357. }
  358. }
  359. INFO_LOG_FMT(NETPLAY, "NetPlayServer shutting down.");
  360. // close listening socket and client sockets
  361. for (auto& player_entry : m_players)
  362. {
  363. ClearPeerPlayerId(player_entry.second.socket);
  364. enet_peer_disconnect(player_entry.second.socket, 0);
  365. }
  366. m_players.clear();
  367. }
  368. static void SendSyncIdentifier(sf::Packet& spac, const SyncIdentifier& sync_identifier)
  369. {
  370. // We cast here due to a potential long vs long long mismatch
  371. spac << static_cast<sf::Uint64>(sync_identifier.dol_elf_size);
  372. spac << sync_identifier.game_id;
  373. spac << sync_identifier.revision;
  374. spac << sync_identifier.disc_number;
  375. spac << sync_identifier.is_datel;
  376. for (const u8& x : sync_identifier.sync_hash)
  377. spac << x;
  378. }
  379. // called from ---NETPLAY--- thread
  380. ConnectionError NetPlayServer::OnConnect(ENetPeer* incoming_connection, sf::Packet& received_packet)
  381. {
  382. std::string netplay_version;
  383. received_packet >> netplay_version;
  384. if (netplay_version != Common::GetScmRevGitStr())
  385. return ConnectionError::VersionMismatch;
  386. if (m_is_running || m_start_pending)
  387. return ConnectionError::GameRunning;
  388. if (m_players.size() >= 255)
  389. return ConnectionError::ServerFull;
  390. Client new_player{};
  391. new_player.pid = GiveFirstAvailableIDTo(incoming_connection);
  392. new_player.socket = incoming_connection;
  393. received_packet >> new_player.revision;
  394. received_packet >> new_player.name;
  395. if (StringUTF8CodePointCount(new_player.name) > MAX_NAME_LENGTH)
  396. return ConnectionError::NameTooLong;
  397. // Update time in milliseconds of no acknoledgment of
  398. // sent packets before a connection is deemed disconnected
  399. enet_peer_timeout(incoming_connection, 0, PEER_TIMEOUT.count(), PEER_TIMEOUT.count());
  400. // force a ping on first netplay loop
  401. m_update_pings = true;
  402. AssignNewUserAPad(new_player);
  403. // tell other players a new player joined
  404. SendResponseToAllPlayers(MessageID::PlayerJoin, new_player.pid, new_player.name,
  405. new_player.revision);
  406. // tell new client they connected and their ID
  407. SendResponseToPlayer(new_player, MessageID::ConnectionSuccessful, new_player.pid);
  408. // tell new client the selected game
  409. if (!m_selected_game_name.empty())
  410. {
  411. sf::Packet send_packet;
  412. send_packet << MessageID::ChangeGame;
  413. SendSyncIdentifier(send_packet, m_selected_game_identifier);
  414. send_packet << m_selected_game_name;
  415. Send(new_player.socket, send_packet);
  416. }
  417. if (!m_host_input_authority)
  418. SendResponseToPlayer(new_player, MessageID::PadBuffer, m_target_buffer_size);
  419. SendResponseToPlayer(new_player, MessageID::HostInputAuthority, m_host_input_authority);
  420. for (const auto& existing_player : m_players)
  421. {
  422. SendResponseToPlayer(new_player, MessageID::PlayerJoin, existing_player.second.pid,
  423. existing_player.second.name, existing_player.second.revision);
  424. SendResponseToPlayer(new_player, MessageID::GameStatus, existing_player.second.pid,
  425. static_cast<u8>(existing_player.second.game_status));
  426. }
  427. if (Config::Get(Config::NETPLAY_ENABLE_QOS))
  428. new_player.qos_session = Common::QoSSession(new_player.socket);
  429. {
  430. std::lock_guard lkp(m_crit.players);
  431. // add new player to list of players
  432. m_players.emplace(*PeerPlayerId(new_player.socket), std::move(new_player));
  433. // sync pad mappings with everyone
  434. UpdatePadMapping();
  435. UpdateGBAConfig();
  436. UpdateWiimoteMapping();
  437. }
  438. return ConnectionError::NoError;
  439. }
  440. // called from ---NETPLAY--- thread
  441. unsigned int NetPlayServer::OnDisconnect(const Client& player)
  442. {
  443. const PlayerId pid = player.pid;
  444. if (m_is_running)
  445. {
  446. for (PlayerId& mapping : m_pad_map)
  447. {
  448. if (mapping == pid && pid != 1)
  449. {
  450. std::lock_guard lkg(m_crit.game);
  451. m_is_running = false;
  452. sf::Packet spac;
  453. spac << MessageID::DisableGame;
  454. // this thread doesn't need players lock
  455. SendToClients(spac);
  456. break;
  457. }
  458. }
  459. }
  460. if (m_start_pending)
  461. {
  462. ChunkedDataAbort();
  463. m_dialog->OnGameStartAborted();
  464. m_start_pending = false;
  465. }
  466. sf::Packet spac;
  467. spac << MessageID::PlayerLeave;
  468. spac << pid;
  469. enet_peer_disconnect(player.socket, 0);
  470. std::lock_guard lkp(m_crit.players);
  471. auto it = m_players.find(player.pid);
  472. if (it != m_players.end())
  473. m_players.erase(it);
  474. // alert other players of disconnect
  475. SendToClients(spac);
  476. for (size_t i = 0; i < m_pad_map.size(); ++i)
  477. {
  478. if (m_pad_map[i] == pid)
  479. {
  480. m_pad_map[i] = 0;
  481. m_gba_config[i].enabled = false;
  482. UpdatePadMapping();
  483. UpdateGBAConfig();
  484. }
  485. }
  486. for (PlayerId& mapping : m_wiimote_map)
  487. {
  488. if (mapping == pid)
  489. {
  490. mapping = 0;
  491. UpdateWiimoteMapping();
  492. }
  493. }
  494. return 0;
  495. }
  496. // called from ---GUI--- thread
  497. PadMappingArray NetPlayServer::GetPadMapping() const
  498. {
  499. return m_pad_map;
  500. }
  501. GBAConfigArray NetPlayServer::GetGBAConfig() const
  502. {
  503. return m_gba_config;
  504. }
  505. PadMappingArray NetPlayServer::GetWiimoteMapping() const
  506. {
  507. return m_wiimote_map;
  508. }
  509. // called from ---GUI--- thread
  510. void NetPlayServer::SetPadMapping(const PadMappingArray& mappings)
  511. {
  512. m_pad_map = mappings;
  513. UpdatePadMapping();
  514. }
  515. // called from ---GUI--- thread
  516. void NetPlayServer::SetGBAConfig(const GBAConfigArray& mappings, bool update_rom)
  517. {
  518. #ifdef HAS_LIBMGBA
  519. m_gba_config = mappings;
  520. if (update_rom)
  521. {
  522. for (size_t i = 0; i < m_gba_config.size(); ++i)
  523. {
  524. auto& config = m_gba_config[i];
  525. if (!config.enabled)
  526. continue;
  527. std::string rom_path = Config::Get(Config::MAIN_GBA_ROM_PATHS[i]);
  528. config.has_rom = HW::GBA::Core::GetRomInfo(rom_path.c_str(), config.hash, config.title);
  529. }
  530. }
  531. #endif
  532. UpdateGBAConfig();
  533. }
  534. // called from ---GUI--- thread
  535. void NetPlayServer::SetWiimoteMapping(const PadMappingArray& mappings)
  536. {
  537. m_wiimote_map = mappings;
  538. UpdateWiimoteMapping();
  539. }
  540. // called from ---GUI--- thread and ---NETPLAY--- thread
  541. void NetPlayServer::UpdatePadMapping()
  542. {
  543. sf::Packet spac;
  544. spac << MessageID::PadMapping;
  545. for (PlayerId mapping : m_pad_map)
  546. {
  547. spac << mapping;
  548. }
  549. SendToClients(spac);
  550. }
  551. // called from ---GUI--- thread and ---NETPLAY--- thread
  552. void NetPlayServer::UpdateGBAConfig()
  553. {
  554. sf::Packet spac;
  555. spac << MessageID::GBAConfig;
  556. for (const auto& config : m_gba_config)
  557. {
  558. spac << config.enabled << config.has_rom << config.title;
  559. for (auto& data : config.hash)
  560. spac << data;
  561. }
  562. SendToClients(spac);
  563. }
  564. // called from ---NETPLAY--- thread
  565. void NetPlayServer::UpdateWiimoteMapping()
  566. {
  567. sf::Packet spac;
  568. spac << MessageID::WiimoteMapping;
  569. for (PlayerId mapping : m_wiimote_map)
  570. {
  571. spac << mapping;
  572. }
  573. SendToClients(spac);
  574. }
  575. // called from ---GUI--- thread and ---NETPLAY--- thread
  576. void NetPlayServer::AdjustPadBufferSize(unsigned int size)
  577. {
  578. std::lock_guard lkg(m_crit.game);
  579. m_target_buffer_size = size;
  580. // not needed on clients with host input authority
  581. if (!m_host_input_authority)
  582. {
  583. // tell clients to change buffer size
  584. sf::Packet spac;
  585. spac << MessageID::PadBuffer;
  586. spac << m_target_buffer_size;
  587. SendAsyncToClients(std::move(spac));
  588. }
  589. }
  590. void NetPlayServer::SetHostInputAuthority(const bool enable)
  591. {
  592. std::lock_guard lkg(m_crit.game);
  593. m_host_input_authority = enable;
  594. // tell clients about the new value
  595. sf::Packet spac;
  596. spac << MessageID::HostInputAuthority;
  597. spac << m_host_input_authority;
  598. SendAsyncToClients(std::move(spac));
  599. // resend pad buffer to clients when disabled
  600. if (!m_host_input_authority)
  601. AdjustPadBufferSize(m_target_buffer_size);
  602. }
  603. void NetPlayServer::SendAsync(sf::Packet&& packet, const PlayerId pid, const u8 channel_id)
  604. {
  605. {
  606. std::lock_guard lkq(m_crit.async_queue_write);
  607. m_async_queue.Push(AsyncQueueEntry{std::move(packet), pid, TargetMode::Only, channel_id});
  608. }
  609. Common::ENet::WakeupThread(m_server);
  610. }
  611. void NetPlayServer::SendAsyncToClients(sf::Packet&& packet, const PlayerId skip_pid,
  612. const u8 channel_id)
  613. {
  614. {
  615. std::lock_guard lkq(m_crit.async_queue_write);
  616. m_async_queue.Push(
  617. AsyncQueueEntry{std::move(packet), skip_pid, TargetMode::AllExcept, channel_id});
  618. }
  619. Common::ENet::WakeupThread(m_server);
  620. }
  621. void NetPlayServer::SendChunked(sf::Packet&& packet, const PlayerId pid, const std::string& title)
  622. {
  623. {
  624. std::lock_guard lkq(m_crit.chunked_data_queue_write);
  625. m_chunked_data_queue.Push(
  626. ChunkedDataQueueEntry{std::move(packet), pid, TargetMode::Only, title});
  627. }
  628. m_chunked_data_event.Set();
  629. }
  630. void NetPlayServer::SendChunkedToClients(sf::Packet&& packet, const PlayerId skip_pid,
  631. const std::string& title)
  632. {
  633. {
  634. std::lock_guard lkq(m_crit.chunked_data_queue_write);
  635. m_chunked_data_queue.Push(
  636. ChunkedDataQueueEntry{std::move(packet), skip_pid, TargetMode::AllExcept, title});
  637. }
  638. m_chunked_data_event.Set();
  639. }
  640. // called from ---NETPLAY--- thread
  641. unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
  642. {
  643. MessageID mid;
  644. packet >> mid;
  645. INFO_LOG_FMT(NETPLAY, "Got client message: {:x} from client {}", static_cast<u8>(mid),
  646. player.pid);
  647. // don't need lock because this is the only thread that modifies the players
  648. // only need locks for writes to m_players in this thread
  649. switch (mid)
  650. {
  651. case MessageID::ChatMessage:
  652. {
  653. std::string msg;
  654. packet >> msg;
  655. // send msg to other clients
  656. sf::Packet spac;
  657. spac << MessageID::ChatMessage;
  658. spac << player.pid;
  659. spac << msg;
  660. SendToClients(spac, player.pid);
  661. }
  662. break;
  663. case MessageID::ChunkedDataProgress:
  664. {
  665. u32 cid;
  666. packet >> cid;
  667. u64 progress = Common::PacketReadU64(packet);
  668. m_dialog->SetChunkedProgress(player.pid, progress);
  669. }
  670. break;
  671. case MessageID::ChunkedDataComplete:
  672. {
  673. u32 cid;
  674. packet >> cid;
  675. if (m_chunked_data_complete_count.contains(cid))
  676. {
  677. m_chunked_data_complete_count[cid]++;
  678. m_chunked_data_complete_event.Set();
  679. }
  680. }
  681. break;
  682. case MessageID::PadData:
  683. {
  684. // if this is pad data from the last game still being received, ignore it
  685. if (player.current_game != m_current_game)
  686. break;
  687. sf::Packet spac;
  688. spac << (m_host_input_authority ? MessageID::PadHostData : MessageID::PadData);
  689. while (!packet.endOfPacket())
  690. {
  691. PadIndex map;
  692. packet >> map;
  693. // If the data is not from the correct player,
  694. // then disconnect them.
  695. if (m_pad_map.at(map) != player.pid)
  696. {
  697. return 1;
  698. }
  699. GCPadStatus pad;
  700. packet >> pad.button;
  701. spac << map << pad.button;
  702. if (!m_gba_config.at(map).enabled)
  703. {
  704. packet >> pad.analogA >> pad.analogB >> pad.stickX >> pad.stickY >> pad.substickX >>
  705. pad.substickY >> pad.triggerLeft >> pad.triggerRight >> pad.isConnected;
  706. spac << pad.analogA << pad.analogB << pad.stickX << pad.stickY << pad.substickX
  707. << pad.substickY << pad.triggerLeft << pad.triggerRight << pad.isConnected;
  708. }
  709. }
  710. if (m_host_input_authority)
  711. {
  712. // Prevent crash before game stop if the golfer disconnects
  713. if (m_current_golfer != 0 && m_players.contains(m_current_golfer))
  714. Send(m_players.at(m_current_golfer).socket, spac);
  715. }
  716. else
  717. {
  718. SendToClients(spac, player.pid);
  719. }
  720. }
  721. break;
  722. case MessageID::PadHostData:
  723. {
  724. // Kick player if they're not the golfer.
  725. if (m_current_golfer != 0 && player.pid != m_current_golfer)
  726. return 1;
  727. sf::Packet spac;
  728. spac << MessageID::PadData;
  729. while (!packet.endOfPacket())
  730. {
  731. PadIndex map;
  732. packet >> map;
  733. GCPadStatus pad;
  734. packet >> pad.button;
  735. spac << map << pad.button;
  736. if (!m_gba_config.at(map).enabled)
  737. {
  738. packet >> pad.analogA >> pad.analogB >> pad.stickX >> pad.stickY >> pad.substickX >>
  739. pad.substickY >> pad.triggerLeft >> pad.triggerRight >> pad.isConnected;
  740. spac << pad.analogA << pad.analogB << pad.stickX << pad.stickY << pad.substickX
  741. << pad.substickY << pad.triggerLeft << pad.triggerRight << pad.isConnected;
  742. }
  743. }
  744. SendToClients(spac, player.pid);
  745. }
  746. break;
  747. case MessageID::WiimoteData:
  748. {
  749. // if this is Wiimote data from the last game still being received, ignore it
  750. if (player.current_game != m_current_game)
  751. break;
  752. sf::Packet spac;
  753. spac << MessageID::WiimoteData;
  754. while (!packet.endOfPacket())
  755. {
  756. PadIndex map;
  757. packet >> map;
  758. // If the data is not from the correct player,
  759. // then disconnect them.
  760. if (m_wiimote_map.at(map) != player.pid)
  761. {
  762. return 1;
  763. }
  764. WiimoteEmu::SerializedWiimoteState pad;
  765. packet >> pad.length;
  766. if (pad.length > pad.data.size())
  767. return 1;
  768. for (size_t i = 0; i < pad.length; ++i)
  769. packet >> pad.data[i];
  770. spac << map;
  771. spac << pad.length;
  772. for (size_t i = 0; i < pad.length; ++i)
  773. spac << pad.data[i];
  774. }
  775. SendToClients(spac, player.pid);
  776. }
  777. break;
  778. case MessageID::GolfRequest:
  779. {
  780. PlayerId pid;
  781. packet >> pid;
  782. // Check if player ID is valid and sender isn't a spectator
  783. if (!m_players.contains(pid) || !PlayerHasControllerMapped(player.pid))
  784. break;
  785. if (m_host_input_authority && m_settings.golf_mode && m_pending_golfer == 0 &&
  786. m_current_golfer != pid && PlayerHasControllerMapped(pid))
  787. {
  788. m_pending_golfer = pid;
  789. sf::Packet spac;
  790. spac << MessageID::GolfPrepare;
  791. Send(m_players[pid].socket, spac);
  792. }
  793. }
  794. break;
  795. case MessageID::GolfRelease:
  796. {
  797. if (m_pending_golfer == 0)
  798. break;
  799. sf::Packet spac;
  800. spac << MessageID::GolfSwitch;
  801. spac << m_pending_golfer;
  802. SendToClients(spac);
  803. }
  804. break;
  805. case MessageID::GolfAcquire:
  806. {
  807. if (m_pending_golfer == 0)
  808. break;
  809. m_current_golfer = m_pending_golfer;
  810. m_pending_golfer = 0;
  811. }
  812. break;
  813. case MessageID::GolfPrepare:
  814. {
  815. if (m_pending_golfer == 0)
  816. break;
  817. m_current_golfer = 0;
  818. sf::Packet spac;
  819. spac << MessageID::GolfSwitch;
  820. spac << PlayerId{0};
  821. SendToClients(spac);
  822. }
  823. break;
  824. case MessageID::Pong:
  825. {
  826. // truncation (> ~49 days elapsed) should never happen here
  827. const u32 ping = static_cast<u32>(m_ping_timer.ElapsedMs());
  828. u32 ping_key = 0;
  829. packet >> ping_key;
  830. if (m_ping_key == ping_key)
  831. {
  832. player.ping = ping;
  833. }
  834. sf::Packet spac;
  835. spac << MessageID::PlayerPingData;
  836. spac << player.pid;
  837. spac << player.ping;
  838. SendToClients(spac);
  839. }
  840. break;
  841. case MessageID::StartGame:
  842. {
  843. packet >> player.current_game;
  844. }
  845. break;
  846. case MessageID::StopGame:
  847. {
  848. if (!m_is_running)
  849. break;
  850. m_is_running = false;
  851. // tell clients to stop game
  852. sf::Packet spac;
  853. spac << MessageID::StopGame;
  854. std::lock_guard lkp(m_crit.players);
  855. SendToClients(spac);
  856. }
  857. break;
  858. case MessageID::GameStatus:
  859. {
  860. SyncIdentifierComparison status;
  861. packet >> status;
  862. m_players[player.pid].game_status = status;
  863. // send msg to other clients
  864. sf::Packet spac;
  865. spac << MessageID::GameStatus;
  866. spac << player.pid;
  867. spac << status;
  868. SendToClients(spac);
  869. }
  870. break;
  871. case MessageID::ClientCapabilities:
  872. {
  873. packet >> m_players[player.pid].has_ipl_dump;
  874. packet >> m_players[player.pid].has_hardware_fma;
  875. }
  876. break;
  877. case MessageID::PowerButton:
  878. {
  879. sf::Packet spac;
  880. spac << MessageID::PowerButton;
  881. SendToClients(spac, player.pid);
  882. }
  883. break;
  884. case MessageID::TimeBase:
  885. {
  886. u64 timebase = Common::PacketReadU64(packet);
  887. u32 frame;
  888. packet >> frame;
  889. if (m_desync_detected)
  890. break;
  891. std::vector<std::pair<PlayerId, u64>>& timebases = m_timebase_by_frame[frame];
  892. timebases.emplace_back(player.pid, timebase);
  893. if (timebases.size() >= m_players.size())
  894. {
  895. // we have all records for this frame
  896. if (!std::all_of(timebases.begin(), timebases.end(), [&](std::pair<PlayerId, u64> pair) {
  897. return pair.second == timebases[0].second;
  898. }))
  899. {
  900. int pid_to_blame = 0;
  901. for (auto pair : timebases)
  902. {
  903. if (std::all_of(timebases.begin(), timebases.end(), [&](std::pair<PlayerId, u64> other) {
  904. return other.first == pair.first || other.second != pair.second;
  905. }))
  906. {
  907. // we are the only outlier
  908. pid_to_blame = pair.first;
  909. break;
  910. }
  911. }
  912. sf::Packet spac;
  913. spac << MessageID::DesyncDetected;
  914. spac << pid_to_blame;
  915. spac << frame;
  916. SendToClients(spac);
  917. m_desync_detected = true;
  918. }
  919. m_timebase_by_frame.erase(frame);
  920. }
  921. }
  922. break;
  923. case MessageID::GameDigestProgress:
  924. {
  925. int progress;
  926. packet >> progress;
  927. sf::Packet spac;
  928. spac << MessageID::GameDigestProgress;
  929. spac << player.pid;
  930. spac << progress;
  931. SendToClients(spac);
  932. }
  933. break;
  934. case MessageID::GameDigestResult:
  935. {
  936. std::string result;
  937. packet >> result;
  938. sf::Packet spac;
  939. spac << MessageID::GameDigestResult;
  940. spac << player.pid;
  941. spac << result;
  942. SendToClients(spac);
  943. }
  944. break;
  945. case MessageID::GameDigestError:
  946. {
  947. std::string error;
  948. packet >> error;
  949. sf::Packet spac;
  950. spac << MessageID::GameDigestError;
  951. spac << player.pid;
  952. spac << error;
  953. SendToClients(spac);
  954. }
  955. break;
  956. case MessageID::SyncSaveData:
  957. {
  958. SyncSaveDataID sub_id;
  959. packet >> sub_id;
  960. INFO_LOG_FMT(NETPLAY, "Got client SyncSaveData message: {:x} from client {}", u8(sub_id),
  961. player.pid);
  962. switch (sub_id)
  963. {
  964. case SyncSaveDataID::Success:
  965. {
  966. if (m_start_pending)
  967. {
  968. m_save_data_synced_players++;
  969. if (m_save_data_synced_players >= m_players.size() - 1)
  970. {
  971. INFO_LOG_FMT(NETPLAY, "SyncSaveData: All players synchronized. ({} >= {})",
  972. m_save_data_synced_players, m_players.size() - 1);
  973. m_dialog->AppendChat(Common::GetStringT("All players' saves synchronized."));
  974. // Saves are synced, check if codes are as well and attempt to start the game
  975. m_saves_synced = true;
  976. CheckSyncAndStartGame();
  977. }
  978. else
  979. {
  980. INFO_LOG_FMT(NETPLAY, "SyncSaveData: Not all players synchronized. ({} < {})",
  981. m_save_data_synced_players, m_players.size() - 1);
  982. }
  983. }
  984. else
  985. {
  986. INFO_LOG_FMT(NETPLAY, "SyncSaveData: Start not pending.");
  987. }
  988. }
  989. break;
  990. case SyncSaveDataID::Failure:
  991. {
  992. m_dialog->AppendChat(Common::FmtFormatT("{0} failed to synchronize.", player.name));
  993. m_dialog->OnGameStartAborted();
  994. ChunkedDataAbort();
  995. m_start_pending = false;
  996. }
  997. break;
  998. default:
  999. PanicAlertFmtT(
  1000. "Unknown SYNC_SAVE_DATA message with id:{0} received from player:{1} Kicking player!",
  1001. static_cast<u8>(sub_id), player.pid);
  1002. return 1;
  1003. }
  1004. }
  1005. break;
  1006. case MessageID::SyncCodes:
  1007. {
  1008. // Receive Status of Code Sync
  1009. SyncCodeID sub_id;
  1010. packet >> sub_id;
  1011. INFO_LOG_FMT(NETPLAY, "Got client SyncCodes message: {:x} from client {}", u8(sub_id),
  1012. player.pid);
  1013. // Check If Code Sync was successful or not
  1014. switch (sub_id)
  1015. {
  1016. case SyncCodeID::Success:
  1017. {
  1018. if (m_start_pending)
  1019. {
  1020. if (++m_codes_synced_players >= m_players.size() - 1)
  1021. {
  1022. INFO_LOG_FMT(NETPLAY, "SyncCodes: All players synchronized. ({} >= {})",
  1023. m_codes_synced_players, m_players.size() - 1);
  1024. m_dialog->AppendChat(Common::GetStringT("All players' codes synchronized."));
  1025. // Codes are synced, check if saves are as well and attempt to start the game
  1026. m_codes_synced = true;
  1027. CheckSyncAndStartGame();
  1028. }
  1029. else
  1030. {
  1031. INFO_LOG_FMT(NETPLAY, "SyncCodes: Not all players synchronized. ({} < {})",
  1032. m_codes_synced_players, m_players.size() - 1);
  1033. }
  1034. }
  1035. else
  1036. {
  1037. INFO_LOG_FMT(NETPLAY, "SyncCodes: Start not pending.");
  1038. }
  1039. }
  1040. break;
  1041. case SyncCodeID::Failure:
  1042. {
  1043. m_dialog->AppendChat(Common::FmtFormatT("{0} failed to synchronize codes.", player.name));
  1044. m_dialog->OnGameStartAborted();
  1045. m_start_pending = false;
  1046. }
  1047. break;
  1048. default:
  1049. PanicAlertFmtT(
  1050. "Unknown SYNC_GECKO_CODES message with id:{0} received from player:{1} Kicking player!",
  1051. static_cast<u8>(sub_id), player.pid);
  1052. return 1;
  1053. }
  1054. }
  1055. break;
  1056. default:
  1057. PanicAlertFmtT("Unknown message with id:{0} received from player:{1} Kicking player!",
  1058. static_cast<u8>(mid), player.pid);
  1059. // unknown message, kick the client
  1060. return 1;
  1061. }
  1062. return 0;
  1063. }
  1064. void NetPlayServer::OnTraversalStateChanged()
  1065. {
  1066. const Common::TraversalClient::State state = m_traversal_client->GetState();
  1067. if (Common::g_TraversalClient->GetHostID()[0] != '\0')
  1068. SetupIndex();
  1069. if (!m_dialog)
  1070. return;
  1071. if (state == Common::TraversalClient::State::Failure)
  1072. m_dialog->OnTraversalError(m_traversal_client->GetFailureReason());
  1073. m_dialog->OnTraversalStateChanged(state);
  1074. }
  1075. void NetPlayServer::OnTtlDetermined(u8 ttl)
  1076. {
  1077. m_dialog->OnTtlDetermined(ttl);
  1078. }
  1079. // called from ---GUI--- thread
  1080. void NetPlayServer::SendChatMessage(const std::string& msg)
  1081. {
  1082. sf::Packet spac;
  1083. spac << MessageID::ChatMessage;
  1084. spac << PlayerId{0}; // server ID always 0
  1085. spac << msg;
  1086. SendAsyncToClients(std::move(spac));
  1087. }
  1088. // called from ---GUI--- thread
  1089. bool NetPlayServer::ChangeGame(const SyncIdentifier& sync_identifier,
  1090. const std::string& netplay_name)
  1091. {
  1092. std::lock_guard lkg(m_crit.game);
  1093. INFO_LOG_FMT(NETPLAY, "Changing game to {} ({:02x}).", netplay_name,
  1094. fmt::join(sync_identifier.sync_hash, ""));
  1095. m_selected_game_identifier = sync_identifier;
  1096. m_selected_game_name = netplay_name;
  1097. // send changed game to clients
  1098. sf::Packet spac;
  1099. spac << MessageID::ChangeGame;
  1100. SendSyncIdentifier(spac, m_selected_game_identifier);
  1101. spac << m_selected_game_name;
  1102. SendAsyncToClients(std::move(spac));
  1103. return true;
  1104. }
  1105. // called from ---GUI--- thread
  1106. bool NetPlayServer::ComputeGameDigest(const SyncIdentifier& sync_identifier)
  1107. {
  1108. sf::Packet spac;
  1109. spac << MessageID::ComputeGameDigest;
  1110. SendSyncIdentifier(spac, sync_identifier);
  1111. SendAsyncToClients(std::move(spac));
  1112. return true;
  1113. }
  1114. // called from ---GUI--- thread
  1115. bool NetPlayServer::AbortGameDigest()
  1116. {
  1117. sf::Packet spac;
  1118. spac << MessageID::GameDigestAbort;
  1119. SendAsyncToClients(std::move(spac));
  1120. return true;
  1121. }
  1122. // called from ---GUI--- thread
  1123. bool NetPlayServer::SetupNetSettings()
  1124. {
  1125. const auto game = m_dialog->FindGameFile(m_selected_game_identifier);
  1126. if (game == nullptr)
  1127. {
  1128. ERROR_LOG_FMT(NETPLAY, "Game {:02x} not found in game list.",
  1129. fmt::join(m_selected_game_identifier.sync_hash, ""));
  1130. PanicAlertFmtT("Selected game doesn't exist in game list!");
  1131. return false;
  1132. }
  1133. INFO_LOG_FMT(NETPLAY, "Loading game settings for {:02x}.",
  1134. fmt::join(m_selected_game_identifier.sync_hash, ""));
  1135. NetPlay::NetSettings settings;
  1136. // Load GameINI so we can sync the settings from it
  1137. Config::AddLayer(
  1138. ConfigLoaders::GenerateGlobalGameConfigLoader(game->GetGameID(), game->GetRevision()));
  1139. Config::AddLayer(
  1140. ConfigLoaders::GenerateLocalGameConfigLoader(game->GetGameID(), game->GetRevision()));
  1141. // Copy all relevant settings
  1142. settings.cpu_thread = Config::Get(Config::MAIN_CPU_THREAD);
  1143. settings.cpu_core = Config::Get(Config::MAIN_CPU_CORE);
  1144. settings.enable_cheats = Config::AreCheatsEnabled();
  1145. settings.selected_language = Config::Get(Config::MAIN_GC_LANGUAGE);
  1146. settings.override_region_settings = Config::Get(Config::MAIN_OVERRIDE_REGION_SETTINGS);
  1147. settings.dsp_hle = Config::Get(Config::MAIN_DSP_HLE);
  1148. settings.dsp_enable_jit = Config::Get(Config::MAIN_DSP_JIT);
  1149. settings.ram_override_enable = Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE);
  1150. settings.mem1_size = Config::Get(Config::MAIN_MEM1_SIZE);
  1151. settings.mem2_size = Config::Get(Config::MAIN_MEM2_SIZE);
  1152. settings.fallback_region = Config::Get(Config::MAIN_FALLBACK_REGION);
  1153. settings.allow_sd_writes = Config::Get(Config::MAIN_ALLOW_SD_WRITES);
  1154. settings.oc_enable = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
  1155. settings.oc_factor = Config::Get(Config::MAIN_OVERCLOCK);
  1156. for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
  1157. {
  1158. ExpansionInterface::EXIDeviceType device;
  1159. if (slot == ExpansionInterface::Slot::SP1)
  1160. {
  1161. // There's no way the BBA is going to sync, disable it
  1162. device = ExpansionInterface::EXIDeviceType::None;
  1163. }
  1164. else
  1165. {
  1166. device = Config::Get(Config::GetInfoForEXIDevice(slot));
  1167. }
  1168. settings.exi_device[slot] = device;
  1169. }
  1170. settings.memcard_size_override = Config::Get(Config::MAIN_MEMORY_CARD_SIZE);
  1171. for (size_t i = 0; i < Config::SYSCONF_SETTINGS.size(); ++i)
  1172. {
  1173. std::visit(
  1174. [&](auto* info) {
  1175. static_assert(sizeof(info->GetDefaultValue()) <= sizeof(u32));
  1176. settings.sysconf_settings[i] = static_cast<u32>(Config::Get(*info));
  1177. },
  1178. Config::SYSCONF_SETTINGS[i].config_info);
  1179. }
  1180. settings.efb_access_enable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE);
  1181. settings.bbox_enable = Config::Get(Config::GFX_HACK_BBOX_ENABLE);
  1182. settings.force_progressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE);
  1183. settings.efb_to_texture_enable = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);
  1184. settings.xfb_to_texture_enable = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM);
  1185. settings.disable_copy_to_vram = Config::Get(Config::GFX_HACK_DISABLE_COPY_TO_VRAM);
  1186. settings.immediate_xfb_enable = Config::Get(Config::GFX_HACK_IMMEDIATE_XFB);
  1187. settings.efb_emulate_format_changes = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES);
  1188. settings.safe_texture_cache_color_samples =
  1189. Config::Get(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES);
  1190. settings.perf_queries_enable = Config::Get(Config::GFX_PERF_QUERIES_ENABLE);
  1191. settings.float_exceptions = Config::Get(Config::MAIN_FLOAT_EXCEPTIONS);
  1192. settings.divide_by_zero_exceptions = Config::Get(Config::MAIN_DIVIDE_BY_ZERO_EXCEPTIONS);
  1193. settings.fprf = Config::Get(Config::MAIN_FPRF);
  1194. settings.accurate_nans = Config::Get(Config::MAIN_ACCURATE_NANS);
  1195. settings.disable_icache = Config::Get(Config::MAIN_DISABLE_ICACHE);
  1196. settings.sync_on_skip_idle = Config::Get(Config::MAIN_SYNC_ON_SKIP_IDLE);
  1197. settings.sync_gpu = Config::Get(Config::MAIN_SYNC_GPU);
  1198. settings.sync_gpu_max_distance = Config::Get(Config::MAIN_SYNC_GPU_MAX_DISTANCE);
  1199. settings.sync_gpu_min_distance = Config::Get(Config::MAIN_SYNC_GPU_MIN_DISTANCE);
  1200. settings.sync_gpu_overclock = Config::Get(Config::MAIN_SYNC_GPU_OVERCLOCK);
  1201. settings.jit_follow_branch = Config::Get(Config::MAIN_JIT_FOLLOW_BRANCH);
  1202. settings.fast_disc_speed = Config::Get(Config::MAIN_FAST_DISC_SPEED);
  1203. settings.mmu = Config::Get(Config::MAIN_MMU);
  1204. settings.fastmem = Config::Get(Config::MAIN_FASTMEM);
  1205. settings.skip_ipl = Config::Get(Config::MAIN_SKIP_IPL) || !DoAllPlayersHaveIPLDump();
  1206. settings.load_ipl_dump = Config::Get(Config::SESSION_LOAD_IPL_DUMP) && DoAllPlayersHaveIPLDump();
  1207. settings.vertex_rounding = Config::Get(Config::GFX_HACK_VERTEX_ROUNDING);
  1208. settings.internal_resolution = Config::Get(Config::GFX_EFB_SCALE);
  1209. settings.efb_scaled_copy = Config::Get(Config::GFX_HACK_COPY_EFB_SCALED);
  1210. settings.fast_depth_calc = Config::Get(Config::GFX_FAST_DEPTH_CALC);
  1211. settings.enable_pixel_lighting = Config::Get(Config::GFX_ENABLE_PIXEL_LIGHTING);
  1212. settings.widescreen_hack = Config::Get(Config::GFX_WIDESCREEN_HACK);
  1213. settings.force_texture_filtering = Config::Get(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING);
  1214. settings.max_anisotropy = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
  1215. settings.force_true_color = Config::Get(Config::GFX_ENHANCE_FORCE_TRUE_COLOR);
  1216. settings.disable_copy_filter = Config::Get(Config::GFX_ENHANCE_DISABLE_COPY_FILTER);
  1217. settings.disable_fog = Config::Get(Config::GFX_DISABLE_FOG);
  1218. settings.arbitrary_mipmap_detection = Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION);
  1219. settings.arbitrary_mipmap_detection_threshold =
  1220. Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION_THRESHOLD);
  1221. settings.enable_gpu_texture_decoding = Config::Get(Config::GFX_ENABLE_GPU_TEXTURE_DECODING);
  1222. settings.defer_efb_copies = Config::Get(Config::GFX_HACK_DEFER_EFB_COPIES);
  1223. settings.efb_access_tile_size = Config::Get(Config::GFX_HACK_EFB_ACCESS_TILE_SIZE);
  1224. settings.efb_access_defer_invalidation = Config::Get(Config::GFX_HACK_EFB_DEFER_INVALIDATION);
  1225. settings.savedata_load = Config::Get(Config::NETPLAY_SAVEDATA_LOAD);
  1226. settings.savedata_write = settings.savedata_load && Config::Get(Config::NETPLAY_SAVEDATA_WRITE);
  1227. settings.savedata_sync_all_wii =
  1228. settings.savedata_load && Config::Get(Config::NETPLAY_SAVEDATA_SYNC_ALL_WII);
  1229. settings.strict_settings_sync = Config::Get(Config::NETPLAY_STRICT_SETTINGS_SYNC);
  1230. settings.sync_codes = Config::Get(Config::NETPLAY_SYNC_CODES);
  1231. settings.golf_mode = Config::Get(Config::NETPLAY_NETWORK_MODE) == "golf";
  1232. settings.use_fma = DoAllPlayersHaveHardwareFMA();
  1233. settings.hide_remote_gbas = Config::Get(Config::NETPLAY_HIDE_REMOTE_GBAS);
  1234. // Unload GameINI to restore things to normal
  1235. Config::RemoveLayer(Config::LayerType::GlobalGame);
  1236. Config::RemoveLayer(Config::LayerType::LocalGame);
  1237. m_settings = settings;
  1238. return true;
  1239. }
  1240. bool NetPlayServer::DoAllPlayersHaveIPLDump() const
  1241. {
  1242. return std::all_of(m_players.begin(), m_players.end(),
  1243. [](const auto& p) { return p.second.has_ipl_dump; });
  1244. }
  1245. bool NetPlayServer::DoAllPlayersHaveHardwareFMA() const
  1246. {
  1247. return std::all_of(m_players.begin(), m_players.end(),
  1248. [](const auto& p) { return p.second.has_hardware_fma; });
  1249. }
  1250. struct SaveSyncInfo
  1251. {
  1252. u8 save_count = 0;
  1253. std::shared_ptr<const UICommon::GameFile> game;
  1254. bool has_wii_save = false;
  1255. std::unique_ptr<IOS::HLE::FS::FileSystem> configured_fs;
  1256. std::optional<std::vector<u8>> mii_data;
  1257. std::vector<std::pair<u64, WiiSave::StoragePointer>> wii_saves;
  1258. std::optional<DiscIO::Riivolution::SavegameRedirect> redirected_save;
  1259. };
  1260. // called from ---GUI--- thread
  1261. bool NetPlayServer::RequestStartGame()
  1262. {
  1263. INFO_LOG_FMT(NETPLAY, "Start Game requested.");
  1264. if (!SetupNetSettings())
  1265. return false;
  1266. bool start_now = true;
  1267. if (m_settings.savedata_load)
  1268. {
  1269. auto save_sync_info = CollectSaveSyncInfo();
  1270. if (!save_sync_info)
  1271. {
  1272. PanicAlertFmtT("Error collecting save data!");
  1273. m_start_pending = false;
  1274. return false;
  1275. }
  1276. if (save_sync_info->has_wii_save)
  1277. {
  1278. // Set titles for host-side loading in WiiRoot
  1279. std::vector<u64> titles;
  1280. for (const auto& [title_id, storage] : save_sync_info->wii_saves)
  1281. titles.push_back(title_id);
  1282. m_dialog->SetHostWiiSyncData(
  1283. std::move(titles),
  1284. save_sync_info->redirected_save ? save_sync_info->redirected_save->m_target_path : "");
  1285. }
  1286. if (m_players.size() > 1)
  1287. {
  1288. start_now = false;
  1289. m_start_pending = true;
  1290. if (!SyncSaveData(*save_sync_info))
  1291. {
  1292. PanicAlertFmtT("Error synchronizing save data!");
  1293. m_start_pending = false;
  1294. return false;
  1295. }
  1296. }
  1297. }
  1298. // Check To Send Codes to Clients
  1299. if (m_settings.sync_codes && m_players.size() > 1)
  1300. {
  1301. start_now = false;
  1302. m_start_pending = true;
  1303. if (!SyncCodes())
  1304. {
  1305. PanicAlertFmtT("Error synchronizing cheat codes!");
  1306. m_start_pending = false;
  1307. return false;
  1308. }
  1309. }
  1310. if (start_now)
  1311. {
  1312. return StartGame();
  1313. }
  1314. INFO_LOG_FMT(NETPLAY, "Waiting for data sync with clients.");
  1315. return true;
  1316. }
  1317. // called from multiple threads
  1318. bool NetPlayServer::StartGame()
  1319. {
  1320. INFO_LOG_FMT(NETPLAY, "Starting game.");
  1321. m_timebase_by_frame.clear();
  1322. m_desync_detected = false;
  1323. std::lock_guard lkg(m_crit.game);
  1324. // only used as an identifier, not time value, so truncation is fine
  1325. m_current_game = static_cast<u32>(Common::Timer::NowMs());
  1326. // no change, just update with clients
  1327. if (!m_host_input_authority)
  1328. AdjustPadBufferSize(m_target_buffer_size);
  1329. m_current_golfer = 1;
  1330. m_pending_golfer = 0;
  1331. const sf::Uint64 initial_rtc = GetInitialNetPlayRTC();
  1332. const std::string region = Config::GetDirectoryForRegion(
  1333. Config::ToGameCubeRegion(m_dialog->FindGameFile(m_selected_game_identifier)->GetRegion()));
  1334. // load host's GC SRAM
  1335. SConfig::GetInstance().m_strSRAM = File::GetUserPath(F_GCSRAM_IDX);
  1336. InitSRAM(&m_settings.sram, SConfig::GetInstance().m_strSRAM);
  1337. // tell clients to start game
  1338. sf::Packet spac;
  1339. spac << MessageID::StartGame;
  1340. spac << m_current_game;
  1341. spac << m_settings.cpu_thread;
  1342. spac << m_settings.cpu_core;
  1343. spac << m_settings.enable_cheats;
  1344. spac << m_settings.selected_language;
  1345. spac << m_settings.override_region_settings;
  1346. spac << m_settings.dsp_enable_jit;
  1347. spac << m_settings.dsp_hle;
  1348. spac << m_settings.ram_override_enable;
  1349. spac << m_settings.mem1_size;
  1350. spac << m_settings.mem2_size;
  1351. spac << m_settings.fallback_region;
  1352. spac << m_settings.allow_sd_writes;
  1353. spac << m_settings.oc_enable;
  1354. spac << m_settings.oc_factor;
  1355. for (auto slot : ExpansionInterface::SLOTS)
  1356. spac << static_cast<int>(m_settings.exi_device[slot]);
  1357. spac << m_settings.memcard_size_override;
  1358. for (u32 value : m_settings.sysconf_settings)
  1359. spac << value;
  1360. spac << m_settings.efb_access_enable;
  1361. spac << m_settings.bbox_enable;
  1362. spac << m_settings.force_progressive;
  1363. spac << m_settings.efb_to_texture_enable;
  1364. spac << m_settings.xfb_to_texture_enable;
  1365. spac << m_settings.disable_copy_to_vram;
  1366. spac << m_settings.immediate_xfb_enable;
  1367. spac << m_settings.efb_emulate_format_changes;
  1368. spac << m_settings.safe_texture_cache_color_samples;
  1369. spac << m_settings.perf_queries_enable;
  1370. spac << m_settings.float_exceptions;
  1371. spac << m_settings.divide_by_zero_exceptions;
  1372. spac << m_settings.fprf;
  1373. spac << m_settings.accurate_nans;
  1374. spac << m_settings.disable_icache;
  1375. spac << m_settings.sync_on_skip_idle;
  1376. spac << m_settings.sync_gpu;
  1377. spac << m_settings.sync_gpu_max_distance;
  1378. spac << m_settings.sync_gpu_min_distance;
  1379. spac << m_settings.sync_gpu_overclock;
  1380. spac << m_settings.jit_follow_branch;
  1381. spac << m_settings.fast_disc_speed;
  1382. spac << m_settings.mmu;
  1383. spac << m_settings.fastmem;
  1384. spac << m_settings.skip_ipl;
  1385. spac << m_settings.load_ipl_dump;
  1386. spac << m_settings.vertex_rounding;
  1387. spac << m_settings.internal_resolution;
  1388. spac << m_settings.efb_scaled_copy;
  1389. spac << m_settings.fast_depth_calc;
  1390. spac << m_settings.enable_pixel_lighting;
  1391. spac << m_settings.widescreen_hack;
  1392. spac << m_settings.force_texture_filtering;
  1393. spac << m_settings.max_anisotropy;
  1394. spac << m_settings.force_true_color;
  1395. spac << m_settings.disable_copy_filter;
  1396. spac << m_settings.disable_fog;
  1397. spac << m_settings.arbitrary_mipmap_detection;
  1398. spac << m_settings.arbitrary_mipmap_detection_threshold;
  1399. spac << m_settings.enable_gpu_texture_decoding;
  1400. spac << m_settings.defer_efb_copies;
  1401. spac << m_settings.efb_access_tile_size;
  1402. spac << m_settings.efb_access_defer_invalidation;
  1403. spac << m_settings.savedata_load;
  1404. spac << m_settings.savedata_write;
  1405. spac << m_settings.savedata_sync_all_wii;
  1406. spac << m_settings.strict_settings_sync;
  1407. spac << initial_rtc;
  1408. spac << region;
  1409. spac << m_settings.sync_codes;
  1410. spac << m_settings.golf_mode;
  1411. spac << m_settings.use_fma;
  1412. spac << m_settings.hide_remote_gbas;
  1413. for (size_t i = 0; i < sizeof(m_settings.sram); ++i)
  1414. spac << m_settings.sram[i];
  1415. SendAsyncToClients(std::move(spac));
  1416. m_start_pending = false;
  1417. m_is_running = true;
  1418. return true;
  1419. }
  1420. void NetPlayServer::AbortGameStart()
  1421. {
  1422. if (m_start_pending)
  1423. {
  1424. INFO_LOG_FMT(NETPLAY, "Aborting game start.");
  1425. m_dialog->OnGameStartAborted();
  1426. ChunkedDataAbort();
  1427. m_start_pending = false;
  1428. }
  1429. else
  1430. {
  1431. INFO_LOG_FMT(NETPLAY, "Aborting game start but no game start pending.");
  1432. }
  1433. }
  1434. // called from ---GUI--- thread
  1435. std::optional<SaveSyncInfo> NetPlayServer::CollectSaveSyncInfo()
  1436. {
  1437. INFO_LOG_FMT(NETPLAY, "Collecting saves.");
  1438. SaveSyncInfo sync_info;
  1439. sync_info.save_count = 0;
  1440. for (ExpansionInterface::Slot slot : ExpansionInterface::MEMCARD_SLOTS)
  1441. {
  1442. if (m_settings.exi_device[slot] == ExpansionInterface::EXIDeviceType::MemoryCard)
  1443. {
  1444. INFO_LOG_FMT(NETPLAY, "Adding memory card (raw) in slot {}.", slot);
  1445. ++sync_info.save_count;
  1446. }
  1447. else if (Config::Get(Config::GetInfoForEXIDevice(slot)) ==
  1448. ExpansionInterface::EXIDeviceType::MemoryCardFolder)
  1449. {
  1450. INFO_LOG_FMT(NETPLAY, "Adding memory card (folder) in slot {}.", slot);
  1451. ++sync_info.save_count;
  1452. }
  1453. }
  1454. sync_info.game = m_dialog->FindGameFile(m_selected_game_identifier);
  1455. if (sync_info.game == nullptr)
  1456. {
  1457. PanicAlertFmtT("Selected game doesn't exist in game list!");
  1458. return std::nullopt;
  1459. }
  1460. sync_info.has_wii_save = false;
  1461. if (m_settings.savedata_load && (sync_info.game->GetPlatform() == DiscIO::Platform::WiiDisc ||
  1462. sync_info.game->GetPlatform() == DiscIO::Platform::WiiWAD ||
  1463. sync_info.game->GetPlatform() == DiscIO::Platform::ELFOrDOL))
  1464. {
  1465. INFO_LOG_FMT(NETPLAY, "Adding Wii saves.");
  1466. sync_info.has_wii_save = true;
  1467. ++sync_info.save_count;
  1468. sync_info.configured_fs = IOS::HLE::FS::MakeFileSystem(IOS::HLE::FS::Location::Configured);
  1469. if (m_settings.savedata_sync_all_wii)
  1470. {
  1471. IOS::HLE::Kernel ios;
  1472. for (const u64 title : ios.GetESCore().GetInstalledTitles())
  1473. {
  1474. auto save = WiiSave::MakeNandStorage(sync_info.configured_fs.get(), title);
  1475. if (save && save->ReadHeader().has_value() && save->ReadBkHeader().has_value() &&
  1476. save->ReadFiles().has_value())
  1477. {
  1478. sync_info.wii_saves.emplace_back(title, std::move(save));
  1479. }
  1480. else
  1481. {
  1482. INFO_LOG_FMT(NETPLAY, "Skipping Wii save of title {:016x}.", title);
  1483. }
  1484. }
  1485. }
  1486. else if (sync_info.game->GetPlatform() == DiscIO::Platform::WiiDisc ||
  1487. sync_info.game->GetPlatform() == DiscIO::Platform::WiiWAD)
  1488. {
  1489. auto save =
  1490. WiiSave::MakeNandStorage(sync_info.configured_fs.get(), sync_info.game->GetTitleID());
  1491. sync_info.wii_saves.emplace_back(sync_info.game->GetTitleID(), std::move(save));
  1492. }
  1493. {
  1494. auto file = sync_info.configured_fs->OpenFile(
  1495. IOS::PID_KERNEL, IOS::PID_KERNEL, Common::GetMiiDatabasePath(), IOS::HLE::FS::Mode::Read);
  1496. if (file)
  1497. {
  1498. std::vector<u8> file_data(file->GetStatus()->size);
  1499. if (!file->Read(file_data.data(), file_data.size()))
  1500. return std::nullopt;
  1501. sync_info.mii_data = std::move(file_data);
  1502. }
  1503. }
  1504. if (sync_info.game->GetBlobType() == DiscIO::BlobType::MOD_DESCRIPTOR)
  1505. {
  1506. auto boot_params = BootParameters::GenerateFromFile(sync_info.game->GetFilePath());
  1507. if (boot_params)
  1508. {
  1509. sync_info.redirected_save =
  1510. DiscIO::Riivolution::ExtractSavegameRedirect(boot_params->riivolution_patches);
  1511. }
  1512. }
  1513. }
  1514. for (size_t i = 0; i < m_gba_config.size(); ++i)
  1515. {
  1516. const auto& config = m_gba_config[i];
  1517. if (config.enabled && config.has_rom)
  1518. {
  1519. INFO_LOG_FMT(NETPLAY, "Adding GBA save in slot {}.", i);
  1520. ++sync_info.save_count;
  1521. }
  1522. }
  1523. return sync_info;
  1524. }
  1525. // called from ---GUI--- thread
  1526. bool NetPlayServer::SyncSaveData(const SaveSyncInfo& sync_info)
  1527. {
  1528. INFO_LOG_FMT(NETPLAY, "Sending {} savegame chunks to clients.", sync_info.save_count);
  1529. // We're about to sync saves, so set m_saves_synced to false (waits to start game)
  1530. m_saves_synced = false;
  1531. m_save_data_synced_players = 0;
  1532. {
  1533. sf::Packet pac;
  1534. pac << MessageID::SyncSaveData;
  1535. pac << SyncSaveDataID::Notify;
  1536. pac << sync_info.save_count;
  1537. // send this on the chunked data channel to ensure it's sequenced properly
  1538. SendAsyncToClients(std::move(pac), 0, CHUNKED_DATA_CHANNEL);
  1539. }
  1540. if (sync_info.save_count == 0)
  1541. return true;
  1542. const auto game_region = sync_info.game->GetRegion();
  1543. const auto gamecube_region = Config::ToGameCubeRegion(game_region);
  1544. const std::string region = Config::GetDirectoryForRegion(gamecube_region);
  1545. for (ExpansionInterface::Slot slot : ExpansionInterface::MEMCARD_SLOTS)
  1546. {
  1547. const bool is_slot_a = slot == ExpansionInterface::Slot::A;
  1548. if (m_settings.exi_device[slot] == ExpansionInterface::EXIDeviceType::MemoryCard)
  1549. {
  1550. const int size_override = m_settings.memcard_size_override;
  1551. const u16 card_size_mbits =
  1552. size_override >= 0 && size_override <= 4 ?
  1553. static_cast<u16>(Memcard::MBIT_SIZE_MEMORY_CARD_59 << size_override) :
  1554. Memcard::MBIT_SIZE_MEMORY_CARD_2043;
  1555. const std::string path = Config::GetMemcardPath(slot, game_region, card_size_mbits);
  1556. sf::Packet pac;
  1557. pac << MessageID::SyncSaveData;
  1558. pac << SyncSaveDataID::RawData;
  1559. pac << is_slot_a << region << size_override;
  1560. if (File::Exists(path))
  1561. {
  1562. INFO_LOG_FMT(NETPLAY, "Sending data of raw memcard {} in slot {}.", path,
  1563. is_slot_a ? 'A' : 'B');
  1564. if (!CompressFileIntoPacket(path, pac))
  1565. return false;
  1566. }
  1567. else
  1568. {
  1569. // No file, so we'll say the size is 0
  1570. INFO_LOG_FMT(NETPLAY, "Sending empty marker for raw memcard {} in slot {}.", path,
  1571. is_slot_a ? 'A' : 'B');
  1572. pac << sf::Uint64{0};
  1573. }
  1574. SendChunkedToClients(std::move(pac), 1,
  1575. fmt::format("Memory Card {} Synchronization", is_slot_a ? 'A' : 'B'));
  1576. }
  1577. else if (Config::Get(Config::GetInfoForEXIDevice(slot)) ==
  1578. ExpansionInterface::EXIDeviceType::MemoryCardFolder)
  1579. {
  1580. const std::string path = Config::GetGCIFolderPath(slot, gamecube_region);
  1581. sf::Packet pac;
  1582. pac << MessageID::SyncSaveData;
  1583. pac << SyncSaveDataID::GCIData;
  1584. pac << is_slot_a;
  1585. if (File::IsDirectory(path))
  1586. {
  1587. std::vector<std::string> files =
  1588. GCMemcardDirectory::GetFileNamesForGameID(path + DIR_SEP, sync_info.game->GetGameID());
  1589. INFO_LOG_FMT(NETPLAY, "Sending data of GCI memcard {} in slot {} ({} files).", path,
  1590. is_slot_a ? 'A' : 'B', files.size());
  1591. pac << static_cast<u8>(files.size());
  1592. for (const std::string& file : files)
  1593. {
  1594. const std::string filename = file.substr(file.find_last_of('/') + 1);
  1595. INFO_LOG_FMT(NETPLAY, "Sending GCI {}.", filename);
  1596. pac << filename;
  1597. if (!CompressFileIntoPacket(file, pac))
  1598. return false;
  1599. }
  1600. }
  1601. else
  1602. {
  1603. INFO_LOG_FMT(NETPLAY, "Sending empty marker for GCI memcard {} in slot {}.", path,
  1604. is_slot_a ? 'A' : 'B');
  1605. pac << static_cast<u8>(0);
  1606. }
  1607. SendChunkedToClients(std::move(pac), 1,
  1608. fmt::format("GCI Folder {} Synchronization", is_slot_a ? 'A' : 'B'));
  1609. }
  1610. }
  1611. if (sync_info.has_wii_save)
  1612. {
  1613. sf::Packet pac;
  1614. pac << MessageID::SyncSaveData;
  1615. pac << SyncSaveDataID::WiiData;
  1616. // Shove the Mii data into the start the packet
  1617. if (sync_info.mii_data)
  1618. {
  1619. INFO_LOG_FMT(NETPLAY, "Sending Mii data.");
  1620. pac << true;
  1621. if (!CompressBufferIntoPacket(*sync_info.mii_data, pac))
  1622. return false;
  1623. }
  1624. else
  1625. {
  1626. INFO_LOG_FMT(NETPLAY, "Not sending Mii data.");
  1627. pac << false; // no mii data
  1628. }
  1629. // Carry on with the save files
  1630. INFO_LOG_FMT(NETPLAY, "Sending {} Wii saves.", sync_info.wii_saves.size());
  1631. pac << static_cast<u32>(sync_info.wii_saves.size());
  1632. for (const auto& [title_id, storage] : sync_info.wii_saves)
  1633. {
  1634. pac << sf::Uint64{title_id};
  1635. if (storage->SaveExists())
  1636. {
  1637. const std::optional<WiiSave::Header> header = storage->ReadHeader();
  1638. const std::optional<WiiSave::BkHeader> bk_header = storage->ReadBkHeader();
  1639. const std::optional<std::vector<WiiSave::Storage::SaveFile>> files = storage->ReadFiles();
  1640. if (!header || !bk_header || !files)
  1641. {
  1642. INFO_LOG_FMT(NETPLAY, "Wii save of title {:016x} is corrupted.", title_id);
  1643. return false;
  1644. }
  1645. INFO_LOG_FMT(NETPLAY, "Sending Wii save of title {:016x}.", title_id);
  1646. pac << true; // save exists
  1647. // Header
  1648. pac << sf::Uint64{header->tid};
  1649. pac << header->banner_size << header->permissions << header->unk1;
  1650. for (u8 byte : header->md5)
  1651. pac << byte;
  1652. pac << header->unk2;
  1653. for (size_t i = 0; i < header->banner_size; i++)
  1654. pac << header->banner[i];
  1655. // BkHeader
  1656. pac << bk_header->size << bk_header->magic << bk_header->ngid << bk_header->number_of_files
  1657. << bk_header->size_of_files << bk_header->unk1 << bk_header->unk2
  1658. << bk_header->total_size;
  1659. for (u8 byte : bk_header->unk3)
  1660. pac << byte;
  1661. pac << sf::Uint64{bk_header->tid};
  1662. for (u8 byte : bk_header->mac_address)
  1663. pac << byte;
  1664. // Files
  1665. for (const WiiSave::Storage::SaveFile& file : *files)
  1666. {
  1667. INFO_LOG_FMT(NETPLAY, "Sending Wii save data of type {} at {}",
  1668. static_cast<u8>(file.type), file.path);
  1669. pac << file.mode << file.attributes << file.type << file.path;
  1670. if (file.type == WiiSave::Storage::SaveFile::Type::File)
  1671. {
  1672. const std::optional<std::vector<u8>>& data = *file.data;
  1673. if (!data || !CompressBufferIntoPacket(*data, pac))
  1674. return false;
  1675. }
  1676. }
  1677. }
  1678. else
  1679. {
  1680. INFO_LOG_FMT(NETPLAY, "No data for Wii save of title {:016x}.", title_id);
  1681. pac << false; // save does not exist
  1682. }
  1683. }
  1684. if (sync_info.redirected_save)
  1685. {
  1686. INFO_LOG_FMT(NETPLAY, "Sending redirected save at {}.",
  1687. sync_info.redirected_save->m_target_path);
  1688. pac << true;
  1689. if (!CompressFolderIntoPacket(sync_info.redirected_save->m_target_path, pac))
  1690. return false;
  1691. }
  1692. else
  1693. {
  1694. INFO_LOG_FMT(NETPLAY, "Not sending redirected save.");
  1695. pac << false; // no redirected save
  1696. }
  1697. SendChunkedToClients(std::move(pac), 1, "Wii Save Synchronization");
  1698. }
  1699. for (size_t i = 0; i < m_gba_config.size(); ++i)
  1700. {
  1701. if (m_gba_config[i].enabled && m_gba_config[i].has_rom)
  1702. {
  1703. sf::Packet pac;
  1704. pac << MessageID::SyncSaveData;
  1705. pac << SyncSaveDataID::GBAData;
  1706. pac << static_cast<u8>(i);
  1707. std::string path;
  1708. #ifdef HAS_LIBMGBA
  1709. path = HW::GBA::Core::GetSavePath(Config::Get(Config::MAIN_GBA_ROM_PATHS[i]),
  1710. static_cast<int>(i));
  1711. #endif
  1712. if (File::Exists(path))
  1713. {
  1714. INFO_LOG_FMT(NETPLAY, "Sending data of GBA save at {} for slot {}.", path, i);
  1715. if (!CompressFileIntoPacket(path, pac))
  1716. return false;
  1717. }
  1718. else
  1719. {
  1720. // No file, so we'll say the size is 0
  1721. INFO_LOG_FMT(NETPLAY, "Sending empty marker for GBA save at {} for slot {}.", path, i);
  1722. pac << sf::Uint64{0};
  1723. }
  1724. SendChunkedToClients(std::move(pac), 1,
  1725. fmt::format("GBA{} Save File Synchronization", i + 1));
  1726. }
  1727. }
  1728. return true;
  1729. }
  1730. bool NetPlayServer::SyncCodes()
  1731. {
  1732. INFO_LOG_FMT(NETPLAY, "Sending codes to clients.");
  1733. // Sync Codes is ticked, so set m_codes_synced to false
  1734. m_codes_synced = false;
  1735. // Get Game Path
  1736. const auto game = m_dialog->FindGameFile(m_selected_game_identifier);
  1737. if (game == nullptr)
  1738. {
  1739. PanicAlertFmtT("Selected game doesn't exist in game list!");
  1740. return false;
  1741. }
  1742. // Find all INI files
  1743. const auto game_id = game->GetGameID();
  1744. const auto revision = game->GetRevision();
  1745. Common::IniFile globalIni;
  1746. for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(game_id, revision))
  1747. globalIni.Load(File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + filename, true);
  1748. Common::IniFile localIni;
  1749. for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(game_id, revision))
  1750. localIni.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + filename, true);
  1751. // Initialize Number of Synced Players
  1752. m_codes_synced_players = 0;
  1753. // Notify Clients of Incoming Code Sync
  1754. {
  1755. sf::Packet pac;
  1756. pac << MessageID::SyncCodes;
  1757. pac << SyncCodeID::Notify;
  1758. SendAsyncToClients(std::move(pac));
  1759. }
  1760. // Sync Gecko Codes
  1761. {
  1762. // Create a Gecko Code Vector with just the active codes
  1763. std::vector<Gecko::GeckoCode> s_active_codes =
  1764. Gecko::SetAndReturnActiveCodes(Gecko::LoadCodes(globalIni, localIni));
  1765. // Determine Codelist Size
  1766. u16 codelines = 0;
  1767. for (const Gecko::GeckoCode& active_code : s_active_codes)
  1768. {
  1769. INFO_LOG_FMT(NETPLAY, "Indexing {}", active_code.name);
  1770. for (const Gecko::GeckoCode::Code& code : active_code.codes)
  1771. {
  1772. INFO_LOG_FMT(NETPLAY, "{:08x} {:08x}", code.address, code.data);
  1773. codelines++;
  1774. }
  1775. }
  1776. // Output codelines to send
  1777. INFO_LOG_FMT(NETPLAY, "Sending {} Gecko codelines", codelines);
  1778. // Send initial packet. Notify of the sync operation and total number of lines being sent.
  1779. {
  1780. sf::Packet pac;
  1781. pac << MessageID::SyncCodes;
  1782. pac << SyncCodeID::NotifyGecko;
  1783. pac << codelines;
  1784. SendAsyncToClients(std::move(pac));
  1785. }
  1786. // Send entire codeset in the second packet
  1787. {
  1788. sf::Packet pac;
  1789. pac << MessageID::SyncCodes;
  1790. pac << SyncCodeID::GeckoData;
  1791. // Iterate through the active code vector and send each codeline
  1792. for (const Gecko::GeckoCode& active_code : s_active_codes)
  1793. {
  1794. INFO_LOG_FMT(NETPLAY, "Sending {}", active_code.name);
  1795. for (const Gecko::GeckoCode::Code& code : active_code.codes)
  1796. {
  1797. INFO_LOG_FMT(NETPLAY, "{:08x} {:08x}", code.address, code.data);
  1798. pac << code.address;
  1799. pac << code.data;
  1800. }
  1801. }
  1802. SendAsyncToClients(std::move(pac));
  1803. }
  1804. }
  1805. // Sync AR Codes
  1806. {
  1807. // Create an AR Code Vector with just the active codes
  1808. std::vector<ActionReplay::ARCode> s_active_codes =
  1809. ActionReplay::ApplyAndReturnCodes(ActionReplay::LoadCodes(globalIni, localIni));
  1810. // Determine Codelist Size
  1811. u16 codelines = 0;
  1812. for (const ActionReplay::ARCode& active_code : s_active_codes)
  1813. {
  1814. INFO_LOG_FMT(NETPLAY, "Indexing {}", active_code.name);
  1815. for (const ActionReplay::AREntry& op : active_code.ops)
  1816. {
  1817. INFO_LOG_FMT(NETPLAY, "{:08x} {:08x}", op.cmd_addr, op.value);
  1818. codelines++;
  1819. }
  1820. }
  1821. // Output codelines to send
  1822. INFO_LOG_FMT(NETPLAY, "Sending {} AR codelines", codelines);
  1823. // Send initial packet. Notify of the sync operation and total number of lines being sent.
  1824. {
  1825. sf::Packet pac;
  1826. pac << MessageID::SyncCodes;
  1827. pac << SyncCodeID::NotifyAR;
  1828. pac << codelines;
  1829. SendAsyncToClients(std::move(pac));
  1830. }
  1831. // Send entire codeset in the second packet
  1832. {
  1833. sf::Packet pac;
  1834. pac << MessageID::SyncCodes;
  1835. pac << SyncCodeID::ARData;
  1836. // Iterate through the active code vector and send each codeline
  1837. for (const ActionReplay::ARCode& active_code : s_active_codes)
  1838. {
  1839. INFO_LOG_FMT(NETPLAY, "Sending {}", active_code.name);
  1840. for (const ActionReplay::AREntry& op : active_code.ops)
  1841. {
  1842. INFO_LOG_FMT(NETPLAY, "{:08x} {:08x}", op.cmd_addr, op.value);
  1843. pac << op.cmd_addr;
  1844. pac << op.value;
  1845. }
  1846. }
  1847. SendAsyncToClients(std::move(pac));
  1848. }
  1849. }
  1850. return true;
  1851. }
  1852. void NetPlayServer::CheckSyncAndStartGame()
  1853. {
  1854. if (m_saves_synced && m_codes_synced)
  1855. {
  1856. INFO_LOG_FMT(NETPLAY, "Synchronized, starting game.");
  1857. StartGame();
  1858. }
  1859. else
  1860. {
  1861. INFO_LOG_FMT(NETPLAY, "Not synchronized.");
  1862. }
  1863. }
  1864. u64 NetPlayServer::GetInitialNetPlayRTC() const
  1865. {
  1866. if (Config::Get(Config::MAIN_CUSTOM_RTC_ENABLE))
  1867. return Config::Get(Config::MAIN_CUSTOM_RTC_VALUE);
  1868. return Common::Timer::GetLocalTimeSinceJan1970();
  1869. }
  1870. // called from multiple threads
  1871. void NetPlayServer::SendToClients(const sf::Packet& packet, const PlayerId skip_pid,
  1872. const u8 channel_id)
  1873. {
  1874. for (auto& p : m_players)
  1875. {
  1876. if (p.second.pid && p.second.pid != skip_pid)
  1877. {
  1878. Send(p.second.socket, packet, channel_id);
  1879. }
  1880. }
  1881. }
  1882. void NetPlayServer::Send(ENetPeer* socket, const sf::Packet& packet, const u8 channel_id)
  1883. {
  1884. Common::ENet::SendPacket(socket, packet, channel_id);
  1885. }
  1886. void NetPlayServer::KickPlayer(PlayerId player)
  1887. {
  1888. for (auto& current_player : m_players)
  1889. {
  1890. if (current_player.second.pid == player)
  1891. {
  1892. enet_peer_disconnect(current_player.second.socket, 0);
  1893. return;
  1894. }
  1895. }
  1896. }
  1897. bool NetPlayServer::PlayerHasControllerMapped(const PlayerId pid) const
  1898. {
  1899. const auto mapping_matches_player_id = [pid](const PlayerId& mapping) { return mapping == pid; };
  1900. return std::any_of(m_pad_map.begin(), m_pad_map.end(), mapping_matches_player_id) ||
  1901. std::any_of(m_wiimote_map.begin(), m_wiimote_map.end(), mapping_matches_player_id);
  1902. }
  1903. void NetPlayServer::AssignNewUserAPad(const Client& player)
  1904. {
  1905. for (PlayerId& mapping : m_pad_map)
  1906. {
  1907. // 0 means unmapped
  1908. if (mapping == 0)
  1909. {
  1910. mapping = player.pid;
  1911. break;
  1912. }
  1913. }
  1914. }
  1915. PlayerId NetPlayServer::GiveFirstAvailableIDTo(ENetPeer* player)
  1916. {
  1917. PlayerId pid = 1;
  1918. for (auto i = m_players.begin(); i != m_players.end(); ++i)
  1919. {
  1920. if (i->second.pid == pid)
  1921. {
  1922. pid++;
  1923. i = m_players.begin();
  1924. }
  1925. }
  1926. player->data = new PlayerId(pid);
  1927. return pid;
  1928. }
  1929. template <typename... Data>
  1930. void NetPlayServer::SendResponseToPlayer(const Client& player, const MessageID message_id,
  1931. Data&&... data_to_send)
  1932. {
  1933. sf::Packet response;
  1934. response << message_id;
  1935. // this is a C++17 fold expression used to call the << operator for all of the data
  1936. (response << ... << std::forward<Data>(data_to_send));
  1937. Send(player.socket, response);
  1938. }
  1939. template <typename... Data>
  1940. void NetPlayServer::SendResponseToAllPlayers(const MessageID message_id, Data&&... data_to_send)
  1941. {
  1942. sf::Packet response;
  1943. response << message_id;
  1944. // this is a C++17 fold expression used to call the << operator for all of the data
  1945. (response << ... << std::forward<Data>(data_to_send));
  1946. SendToClients(response);
  1947. }
  1948. u16 NetPlayServer::GetPort() const
  1949. {
  1950. return m_server->address.port;
  1951. }
  1952. // called from ---GUI--- thread
  1953. std::unordered_set<std::string> NetPlayServer::GetInterfaceSet() const
  1954. {
  1955. std::unordered_set<std::string> result;
  1956. for (const auto& list_entry : GetInterfaceListInternal())
  1957. result.emplace(list_entry.first);
  1958. return result;
  1959. }
  1960. // called from ---GUI--- thread
  1961. std::string NetPlayServer::GetInterfaceHost(const std::string& inter) const
  1962. {
  1963. char buf[16]{};
  1964. fmt::format_to_n(buf, sizeof(buf) - 1, ":{}", GetPort());
  1965. auto lst = GetInterfaceListInternal();
  1966. for (const auto& list_entry : lst)
  1967. {
  1968. if (list_entry.first == inter)
  1969. {
  1970. return list_entry.second + buf;
  1971. }
  1972. }
  1973. return "?";
  1974. }
  1975. // called from ---GUI--- thread
  1976. std::vector<std::pair<std::string, std::string>> NetPlayServer::GetInterfaceListInternal() const
  1977. {
  1978. std::vector<std::pair<std::string, std::string>> result;
  1979. #if defined(_WIN32)
  1980. #elif defined(ANDROID)
  1981. // Android has no getifaddrs for some stupid reason. If this
  1982. // functionality ends up actually being used on Android, fix this.
  1983. #else
  1984. ifaddrs* ifp = nullptr;
  1985. char buf[512];
  1986. if (getifaddrs(&ifp) != -1)
  1987. {
  1988. for (ifaddrs* curifp = ifp; curifp; curifp = curifp->ifa_next)
  1989. {
  1990. sockaddr* sa = curifp->ifa_addr;
  1991. if (sa == nullptr)
  1992. continue;
  1993. if (sa->sa_family != AF_INET)
  1994. continue;
  1995. sockaddr_in* sai = (struct sockaddr_in*)sa;
  1996. if (ntohl(((struct sockaddr_in*)sa)->sin_addr.s_addr) == 0x7f000001)
  1997. continue;
  1998. const char* ip = inet_ntop(sa->sa_family, &sai->sin_addr, buf, sizeof(buf));
  1999. if (ip == nullptr)
  2000. continue;
  2001. result.emplace_back(std::make_pair(curifp->ifa_name, ip));
  2002. }
  2003. freeifaddrs(ifp);
  2004. }
  2005. #endif
  2006. if (result.empty())
  2007. result.emplace_back(std::make_pair("!local!", "127.0.0.1"));
  2008. return result;
  2009. }
  2010. // called from ---Chunked Data--- thread
  2011. void NetPlayServer::ChunkedDataThreadFunc()
  2012. {
  2013. INFO_LOG_FMT(NETPLAY, "Starting Chunked Data Thread.");
  2014. while (m_do_loop)
  2015. {
  2016. m_chunked_data_event.Wait();
  2017. if (m_abort_chunked_data)
  2018. {
  2019. // thread-safe clear
  2020. while (!m_chunked_data_queue.Empty())
  2021. m_chunked_data_queue.Pop();
  2022. m_abort_chunked_data = false;
  2023. }
  2024. while (!m_chunked_data_queue.Empty())
  2025. {
  2026. if (!m_do_loop)
  2027. return;
  2028. if (m_abort_chunked_data)
  2029. break;
  2030. auto& e = m_chunked_data_queue.Front();
  2031. const u32 id = m_next_chunked_data_id++;
  2032. m_chunked_data_complete_count[id] = 0;
  2033. size_t player_count;
  2034. {
  2035. std::vector<int> players;
  2036. if (e.target_mode == TargetMode::Only)
  2037. {
  2038. players.push_back(e.target_pid);
  2039. }
  2040. else
  2041. {
  2042. for (auto& pl : m_players)
  2043. {
  2044. if (pl.second.pid != e.target_pid)
  2045. players.push_back(pl.second.pid);
  2046. }
  2047. }
  2048. player_count = players.size();
  2049. INFO_LOG_FMT(NETPLAY, "Informing players {} of data chunk {} start.",
  2050. fmt::join(players, ", "), id);
  2051. sf::Packet pac;
  2052. pac << MessageID::ChunkedDataStart;
  2053. pac << id << e.title << sf::Uint64{e.packet.getDataSize()};
  2054. ChunkedDataSend(std::move(pac), e.target_pid, e.target_mode);
  2055. if (e.target_mode == TargetMode::AllExcept && e.target_pid == 1)
  2056. m_dialog->ShowChunkedProgressDialog(e.title, e.packet.getDataSize(), players);
  2057. }
  2058. const bool enable_limit = Config::Get(Config::NETPLAY_ENABLE_CHUNKED_UPLOAD_LIMIT);
  2059. const float bytes_per_second =
  2060. (std::max(Config::Get(Config::NETPLAY_CHUNKED_UPLOAD_LIMIT), 1u) / 8.0f) * 1024.0f;
  2061. const std::chrono::duration<double> send_interval(CHUNKED_DATA_UNIT_SIZE / bytes_per_second);
  2062. bool skip_wait = false;
  2063. size_t index = 0;
  2064. do
  2065. {
  2066. if (!m_do_loop)
  2067. return;
  2068. if (m_abort_chunked_data)
  2069. {
  2070. INFO_LOG_FMT(NETPLAY, "Informing players of data chunk {} abort.", id);
  2071. sf::Packet pac;
  2072. pac << MessageID::ChunkedDataAbort;
  2073. pac << id;
  2074. ChunkedDataSend(std::move(pac), e.target_pid, e.target_mode);
  2075. break;
  2076. }
  2077. if (e.target_mode == TargetMode::Only)
  2078. {
  2079. if (!m_players.contains(e.target_pid))
  2080. {
  2081. skip_wait = true;
  2082. break;
  2083. }
  2084. }
  2085. auto start = std::chrono::steady_clock::now();
  2086. sf::Packet pac;
  2087. pac << MessageID::ChunkedDataPayload;
  2088. pac << id;
  2089. size_t len = std::min(CHUNKED_DATA_UNIT_SIZE, e.packet.getDataSize() - index);
  2090. pac.append(static_cast<const u8*>(e.packet.getData()) + index, len);
  2091. INFO_LOG_FMT(NETPLAY, "Sending data chunk of {} ({} bytes at {}/{}).", id, len, index,
  2092. e.packet.getDataSize());
  2093. ChunkedDataSend(std::move(pac), e.target_pid, e.target_mode);
  2094. index += CHUNKED_DATA_UNIT_SIZE;
  2095. if (enable_limit)
  2096. {
  2097. std::chrono::duration<double> delta = std::chrono::steady_clock::now() - start;
  2098. std::this_thread::sleep_for(send_interval - delta);
  2099. }
  2100. } while (index < e.packet.getDataSize());
  2101. if (!m_abort_chunked_data)
  2102. {
  2103. INFO_LOG_FMT(NETPLAY, "Informing players of data chunk {} end.", id);
  2104. sf::Packet pac;
  2105. pac << MessageID::ChunkedDataEnd;
  2106. pac << id;
  2107. ChunkedDataSend(std::move(pac), e.target_pid, e.target_mode);
  2108. }
  2109. while (m_chunked_data_complete_count[id] < player_count && m_do_loop &&
  2110. !m_abort_chunked_data && !skip_wait)
  2111. m_chunked_data_complete_event.Wait();
  2112. m_chunked_data_complete_count.erase(id);
  2113. m_dialog->HideChunkedProgressDialog();
  2114. m_chunked_data_queue.Pop();
  2115. }
  2116. }
  2117. INFO_LOG_FMT(NETPLAY, "Stopping Chunked Data Thread.");
  2118. }
  2119. // called from ---Chunked Data--- thread
  2120. void NetPlayServer::ChunkedDataSend(sf::Packet&& packet, const PlayerId pid,
  2121. const TargetMode target_mode)
  2122. {
  2123. if (target_mode == TargetMode::Only)
  2124. {
  2125. SendAsync(std::move(packet), pid, CHUNKED_DATA_CHANNEL);
  2126. }
  2127. else
  2128. {
  2129. SendAsyncToClients(std::move(packet), pid, CHUNKED_DATA_CHANNEL);
  2130. }
  2131. }
  2132. void NetPlayServer::ChunkedDataAbort()
  2133. {
  2134. m_abort_chunked_data = true;
  2135. m_chunked_data_event.Set();
  2136. m_chunked_data_complete_event.Set();
  2137. }
  2138. } // namespace NetPlay