1 // Copyright (c) 2014- PPSSPP Project.
2 
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6 
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License 2.0 for more details.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17 
18 
19 // proAdhocServer
20 
21 // This is a direct port of Coldbird's code from http://code.google.com/p/aemu/
22 // All credit goes to him!
23 
24 #include "ppsspp_config.h"
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <signal.h>
30 
31 #if defined(HAVE_LIBNX) || PPSSPP_PLATFORM(SWITCH)
32 #include <netdb.h>
33 #include <switch.h>
34 // Missing include, *shrugs*
35 extern "C" struct hostent *gethostbyname(const char *name);
36 #endif // defined(HAVE_LIBNX) || PPSSPP_PLATFORM(SWITCH)
37 
38 #if !defined(__APPLE__)
39 #include <stdlib.h>
40 #endif
41 
42 #include <sys/types.h>
43 // Net stuff
44 #if defined(_WIN32)
45 #include <WinSock2.h>
46 #include <WS2tcpip.h>
47 #else
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <netinet/tcp.h>
51 #endif
52 
53 #include <fcntl.h>
54 #include <errno.h>
55 //#include <sqlite3.h>
56 
57 #ifndef MSG_NOSIGNAL
58 // Default value to 0x00 (do nothing) in systems where it's not supported.
59 #define MSG_NOSIGNAL 0x00
60 #endif
61 
62 #include "Common/Data/Text/I18n.h"
63 #include "Common/Thread/ThreadUtil.h"
64 
65 #include "Common/File/FileUtil.h"
66 #include "Common/TimeUtil.h"
67 #include "Core/Util/PortManager.h"
68 #include "Core/Instance.h"
69 #include "Core/Core.h"
70 #include "Core/Host.h"
71 #include "Core/HLE/proAdhocServer.h"
72 
73 // User Count
74 uint32_t _db_user_count = 0;
75 
76 // User Database
77 SceNetAdhocctlUserNode * _db_user = NULL;
78 
79 // Game Database
80 SceNetAdhocctlGameNode * _db_game = NULL;
81 
82 // Server Status
83 std::atomic<bool> adhocServerRunning(false);
84 std::thread adhocServerThread;
85 
86 // Crosslink database for cross region Adhoc play
87 std::vector<db_crosslink> crosslinks;
88 static const db_crosslink default_crosslinks[] = {
89 	// Ace Combat X2 - Joint Assault
90 	{ "ULES01408", "ULUS10511" },
91 	{ "NPJH50263", "ULUS10511" },
92 
93 	// Armored Core 3 Portable
94 	{ "ULJM05492", "NPUH10023" },
95 
96 	// BlazBlue - Continuum Shift 2
97 	{ "NPJH50401", "ULUS10579" },
98 
99 	// Blood Bowl
100 	{ "ULES01230", "ULUS10516" },
101 
102 	// Bomberman
103 	{ "ULJM05034", "ULUS10121" },
104 	{ "ULES00469", "ULUS10121" },
105 	{ "ULJM05316", "ULUS10121" },
106 
107 	// Bomberman Land
108 	{ "ULJM05181", "ULUS10319" },
109 	{ "ULJM05319", "ULUS10319" },
110 	{ "ULES00959", "ULUS10319" },
111 
112 	// Call of Duty - Roads to Victory
113 	{ "ULES00643", "ULUS10218" },
114 
115 	// Dissidia 012 Duodecim Final Fantasy
116 	{ "ULES01505", "ULUS10566" },
117 	{ "NPJH50377", "ULUS10566" },
118 
119 	// Dissidia Final Fantasy
120 	{ "ULES01270", "ULUS10437" },
121 	{ "ULJM05262", "ULUS10437" },
122 
123 	// Dragon Ball Z - Shin Budokai
124 	{ "ULJS00049", "ULUS10081" },
125 	{ "ULKS46085", "ULUS10081" },
126 	{ "ULES00309", "ULUS10081" },
127 
128 	// Dragon Ball Z - Shin Budokai 2
129 	{ "ULJS00107", "ULUS10234" },
130 	{ "ULES00789", "ULUS10234" },
131 
132 	// Dragon Ball Z - Tenkaichi Tag Team
133 	{ "ULES01456", "ULUS10537" },
134 
135 	// Dungeon Siege - Throne of Agony
136 	{ "ULES00569", "ULUS10177" },
137 
138 	// Everybody's Tennis
139 	{ "UCJS10101", "UCUS98701" },
140 	{ "UCES01420", "UCUS98701" },
141 
142 	// Fat Princess - Fistful of Cake
143 	{ "UCES01312", "UCUS98740" },
144 	{ "NPHG00025", "UCUS98740" },
145 
146 	// God Eater Burst
147 	{ "ULES01519", "ULUS10563" },
148 	{ "NPJH50352", "ULUS10563" },
149 
150 	// Gran Turismo
151 	{ "UCES01245", "UCUS98632" },
152 	{ "UCES00543", "UCUS98645" },
153 
154 	// Gundam VS Gundam - Next Plus
155 	{ "ULJS00250", "NPJH50107" },
156 	{ "ULJS19048", "NPJH50107" },
157 
158 	// Hatsune Miku - Project Diva Extend
159 	{ "NPJH50465", "ULJM05933" },
160 
161 	// Hot Pixel
162 	{ "ULES00642", "ULUS10298" },
163 
164 	// Lord of Arcana
165 	{ "ULJM05767", "ULES01507" },
166 	{ "ULUS10479", "ULES01507" },
167 
168 	// M.A.C.H. - Modified Air Combat Heroes
169 	{ "ULES00565", "ULUS10180" },
170 	{ "ULES00566", "ULUS10180" },
171 	{ "ULJM05202", "ULUS10180" },
172 
173 	// Metal Gear Solid - Peace Walker
174 	{ "ULES01372", "NPJH50045" },
175 	{ "ULUS10509", "NPJH50045" },
176 
177 	// Metal Gear Solid - Portable Ops
178 	{ "ULES00645", "ULUS10202" },
179 	{ "ULJM05193", "ULUS10202" },
180 
181 	// Metal Gear Solid - Portable Ops +
182 	{ "ULES01003", "ULUS10290" },
183 	{ "ULJM05261", "ULUS10290" },
184 
185 	// Midnight Club - LA Remix
186 	{ "ULES01144", "ULUS10383" },
187 	{ "ULJS00180", "ULUS10383" },
188 
189 	// Mod Nation Racers
190 	{ "UCES01327", "UCUS98741" },
191 	{ "UCJS10112", "UCUS98741" },
192 	{ "UCAS40306", "UCUS98741" },
193 
194 	// Monster Hunter Freedom
195 	{ "ULJM05066", "ULUS10084" },
196 	{ "ULES00318", "ULUS10084" },
197 
198 	// Monster Hunter Freedom 2
199 	{ "ULJM05156", "ULUS10266" },
200 	{ "ULES00851", "ULUS10266" },
201 
202 	// Monster Hunter Freedom Unite
203 	{ "ULES01213", "ULUS10391" },
204 	{ "ULJM05500", "ULUS10391" },
205 
206 	// N+
207 	{ "ULES01026", "ULUS10340" },
208 
209 	// Need for Speed - Undercover
210 	{ "ULJM05403", "ULUS10376" },
211 	{ "ULJM05612", "ULUS10376" },
212 	{ "ULES01145", "ULUS10376" },
213 
214 	// Outrun 2006 - Coast 2 Coast
215 	{ "ULES00262", "ULUS10064" },
216 
217 	// Pangya! - Fantasy Golf
218 	{ "ULJM05440", "ULUS10438" },
219 	{ "ULKS46164", "ULUS10438" },
220 
221 	// PRO Evolution Soccer 2012
222 	{ "ULES01540", "ULUS10586" },
223 	{ "ULES01541", "ULUS10586" },
224 	{ "ULES01542", "ULUS10586" },
225 	{ "ULAS42289", "ULUS10586" },
226 
227 	// Patapon 2
228 	{ "UCJS10089", "UCUS98732" },
229 	{ "PSPJ30000", "UCUS98732" },
230 	{ "UCES01177", "UCUS98732" },
231 	{ "UCJS18036", "UCUS98732" },
232 
233 	// Patapon 3
234 	{ "UCES01421", "UCUS98751" },
235 	{ "NPJG00122", "UCUS98751" },
236 
237 	// Phantasy Star Portable
238 	{ "ULJM05309", "ULUS10410" },
239 	{ "ULES01218", "ULUS10410" },
240 	{ "ULJM08023", "ULUS10410" },
241 
242 	// Phantasy Star Portable 2
243 	{ "ULJM05493", "ULUS10529" },
244 	{ "ULJM08030", "ULUS10529" },
245 	{ "ULES01439", "ULUS10529" },
246 
247 	// Resistance - Retribution
248 	{ "UCES01184", "UCJS10090" },
249 	{ "UCUS98668", "UCJS10090" },
250 
251 	// Rocky Balboa
252 	{ "ULUS10233", "ULES00670" },
253 
254 	// SOCOM - Fireteam Bravo
255 	{ "UCES00038", "UCUS98615" },
256 	{ "UCJS10102", "UCUS98615" },
257 
258 	// SOCOM - Fireteam Bravo 3
259 	{ "UCES01242", "UCUS98716" },
260 	{ "NPJG00035", "UCUS98716" },
261 
262 	// Shrek - Smash and Crash Racing
263 	{ "ULES00618", "ULUS10194" },
264 
265 	// Smash Court Tennis 3
266 	{ "ULJS00098", "UCES00758" },
267 	{ "ULUS10269", "UCES00758" },
268 
269 	// Soul Calibur - Broken Destiny
270 	{ "ULES01298", "ULUS10457" },
271 	{ "ULJS00202", "ULUS10457" },
272 
273 	// Split Second - Velocity
274 	{ "ULES01402", "ULUS10513" },
275 	{ "ULJM05812", "ULUS10513" },
276 
277 	// Street Fighter Alpha 3 MAX
278 	{ "ULJM05082", "ULUS10062" },
279 	{ "ULES00235", "ULUS10062" },
280 	{ "ULJM05225", "ULUS10062" },
281 
282 	// Taiko no Tatsujin Portable DX"
283 	{ "ULJS00383", "NPJH50426" },
284 
285 	// Tekken 6
286 	{ "ULES01376", "ULUS10466" },
287 	{ "NPJH50184", "ULUS10466" },
288 	{ "ULJS00224", "ULUS10466" },
289 
290 	// TRON - Evolution
291 	{ "ULES01495", "ULUS10548" },
292 
293 	// Untold Legends - Brotherhood of the Blade
294 	{ "ULES00046", "ULUS10003" },
295 	{ "ULJM05087", "ULUS10003" },
296 	{ "ULKS46015", "ULUS10003" },
297 
298 	// Untold Legends - The Warrior's Code
299 	{ "ULES00301", "ULUS10086" },
300 	{ "ULJM05179", "ULUS10086" },
301 	{ "ULKS46069", "ULUS10086" },
302 
303 	// Virtua Tennis 3
304 	{ "ULES00763", "ULUS10246" },
305 
306 	// World Series of Poker 2008 - Battle for the Bracelets
307 	{ "ULES00991", "ULUS10321" },
308 
309 	// Worms Battle Islands
310 	{ "NPEH00019", "NPUH10045" },
311 
312 	// Worms Open Warfare
313 	{ "ULES00268", "ULUS10065" },
314 
315 	// Worms Open Warfare 2
316 	{ "ULES00819", "ULUS10260" },
317 
318 	// Yu-Gi-Oh! 5D's Tag Force 5
319 	{ "ULUS10555", "ULJM05734" },
320 	{ "ULES01474", "ULJM05734" },
321 };
322 
323 std::vector<db_productid> productids;
324 static const db_productid default_productids[] = {
325 	{ "ULUS10511", "Ace Combat X2 - Joint Assault" },
326 	{ "ULUS10245", "Alien Syndrome" },
327 	{ "NPUH10023", "Armored Core 3 Portable" },
328 	{ "ULES00719", "Asphalt - Urban GT 2" },
329 	{ "ULUS10579", "BlazBlue - Continuum Shift 2" },
330 	{ "ULUS10519", "BlazBlue Calamity Trigger" },
331 	{ "UCJS10110", "Bleach Heat The Soul 7" },
332 	{ "ULUS10516", "Blood Bowl" },
333 	{ "ULUS10121", "Bomberman" },
334 	{ "ULUS10319", "Bomberman Land" },
335 	{ "ULES00703", "Burnout Dominator" },
336 	{ "ULES00125", "Burnout Legends" },
337 	{ "ULJM05538", "Busou Shinki - Battle Masters" },
338 	{ "ULUS10057", "Bust A Move Deluxe" },
339 	{ "ULUS10218", "Call of Duty - Roads to Victory" },
340 	{ "ULUS10351", "Code Lyoko - Quest for Infinity" },
341 	{ "NPJH50583", "Conception - Please have my children!" },
342 	{ "ULUS10044", "Crash Tag Team Racing" },
343 	{ "ULUS10100", "Def Jam Fight For NY - The Takeover" },
344 	{ "NPJH50588", "Digimon World Re:Digitize" },
345 	{ "ULUS10566", "Dissidia 012 Duodecim Final Fantasy" },
346 	{ "ULUS10437", "Dissidia Final Fantasy" },
347 	{ "ULUS10081", "Dragon Ball Z - Shin Budokai" },
348 	{ "ULUS10234", "Dragon Ball Z - Shin Budokai 2" },
349 	{ "ULUS10537", "Dragon Ball Z - Tenkaichi Tag Team" },
350 	//maybe we can crosslinks this 2 region to ULUS10537 not having the game to test
351 	{ "ULJS00311", "Dragon Ball Z - Tenkaichi Tag Team" },
352 	{ "NPJH90135", "Dragon Ball Z - Tenkaichi Tag Team" },
353 	{ "ULJM05127", "Dragon Quest & Final Fantasy in Itadaki Street Special" },
354 	{ "ULES00847", "Dungeon Explorer - Warriors of Ancient Arts" },
355 	{ "ULUS10177", "Dungeon Siege - Throne of Agony" },
356 	{ "ULUS10170", "Dynasty Warrior 2" },
357 	//looks like can be crosslinked too
358 	{ "ULES01221", "Dynasty Warriors - Strike Force" },
359 	{ "ULUS10416", "Dynasty Warriors - Strike Force" },
360 	{ "UCUS98701", "Everybody's Tennis" },
361 	{ "UCUS98740", "Fat Princess - Fistful of Cake" },
362 	{ "ULJM05360", "Fate Tiger Colosseum Upper" },
363 	{ "ULUS10297", "Final Fantasy Tactics - The War of the Lions" },
364 	{ "ULES00850", "Final Fantasy Tactics - War of the Lions" },
365 	{ "NPJH50443", "Final Fantasy Type 0" },
366 	{ "NPJH50468", "Frontier Gate" },
367 	{ "NPJH50721", "Frontier Gate Boost+" },
368 	{ "ULES01432", "Full Metal Alchemist - Brotherhood" },
369 	{ "ULUS10490", "GTA Chinatown Wars" },
370 	{ "ULUS10160", "GTA Vice City Stories" },
371 	{ "ULUS10210", "Ghost Rider" },
372 	{ "ULJS00237", "God Eater" },
373 	{ "NPJH50832", "God Eater 2" },
374 	{ "ULUS10563", "God Eater Burst" },
375 	{ "UCUS98632", "Gran Turismo" },
376 	{ "NPJH50107", "Gundam VS Gundam - Next Plus" },
377 	{ "ULJM05933", "Hatsune Miku - Project Diva Extend" },
378 	{ "ULUS10298", "Hot Pixel" },
379 	{ "ULJM05709", "K-ON! Houkago Live" },
380 	{ "NPJH50221", "Kateikyoushi Hitman Reborn! Kizuna no Tag Battle" },
381 	{ "ULJS00165", "Kidou Senshi Gundam - Gundam vs. Gundam" },
382 	{ "UCUS98646", "Killzone Liberation" },
383 	{ "ULJM05775", "Kingdom Hearts - Birth by Sleep Final Mix" },
384 	{ "ULUS10487", "LEGO Indiana Jones 2" },
385 	{ "NPJH50503", "Lord of Apocalypse" },
386 	{ "ULES01507", "Lord of Arcana" },
387 	{ "ULUS10180", "M.A.C.H. - Modified Air Combat Heroes" },
388 	{ "UCUS98758", "MLB11 - The Show" },
389 	{ "ULUS10581", "Madden NFL 12" },
390 	{ "ULJS00385", "Mahou Shoujo Nanoha A's Portable - The Gears of Destiny" },
391 	{ "ULUS10408", "Mana Khemia Student Alliance" },
392 	{ "ULUS10141", "Medal Of Honor Heroes" },
393 	{ "NPJH50045", "Metal Gear Solid - Peace Walker" },
394 	{ "ULUS10202", "Metal Gear Solid - Portable Ops" },
395 	{ "ULUS10290", "Metal Gear Solid - Portable Ops +" },
396 	{ "ULUS10154", "Metal Slug Anthology" },
397 	{ "ULUS10495", "Metal Slug XX" },
398 	{ "ULES01429", "Metal Slug XX" },
399 	{ "ULES00368", "Micro Machines V4" },
400 	{ "ULUS10383", "Midnight Club - LA Remix" },
401 	{ "UCUS98741", "Mod Nation Racers" },
402 	{ "ULUS10084", "Monster Hunter Freedom" },
403 	{ "ULUS10266", "Monster Hunter Freedom 2" },
404 	{ "ULUS10391", "Monster Hunter Freedom Unite" },
405 	{ "ULJM05800", "Monster Hunter Portable 3rd" },
406 	{ "ULJM06097", "Musou Orochi 2 Special" },
407 	{ "ULUS10340", "N+" },
408 	{ "ULES01578", "NBA 2K13" },
409 	{ "ULUS10598", "NBA 2K13" },
410 	{ "ULUS10349", "Naruto - Ultimate Ninja Heroes 2" },
411 	{ "ULUS10518", "Naruto - Ultimate Ninja Heroes 3" },
412 	{ "ULJS00236", "Naruto - Accel 3" },
413 	{ "ULUS10582", "Naruto Shippuden - Ultimate Ninja Impact" },
414 	{ "ULES01537", "Naruto Shippuden - Ultimate Ninja Impact" },
415 	{ "ULUS10571", "Naruto Shippuden - Kizuna Drive" },
416 	{ "ULES00196", "Need For Speed - Most Wanted" },
417 	{ "ULUS10036", "Need For Speed - Most Wanted" },
418 	{ "ULUS10376", "Need for Speed - Undercover" },
419 	{ "ULKS46004", "Need for Speed - Underground Rivals" },
420 	{ "ULES01340", "Obscure - The Aftermath" },
421 	{ "ULUS10064", "Outrun 2006 - Coast 2 Coast" },
422 	{ "ULUS10586", "PRO Evolution Soccer 2012" },
423 	{ "ULUS10149", "Pac Man - World Rally" },
424 	{ "ULUS10438", "Pangya! - Fantasy Golf" },
425 	{ "UCUS98732", "Patapon 2" },
426 	{ "UCUS98751", "Patapon 3" },
427 	{ "ULUS10410", "Phantasy Star Portable" },
428 	{ "ULUS10529", "Phantasy Star Portable 2" },
429 	//looks like this japan version can crosslink to ULUS10529
430 	{ "NPJH50332", "Phantasy Star Portable 2" },
431 	{ "ULJM05732", "Phantasy Star Portable 2 - Infinity" },
432 	{ "ULES01596", "Pro Evolution Soccer 2014" },
433 	{ "ULES01595", "Pro Evolution Soccer 2015" },
434 	{ "NPJH50520", "Pro Yakyuu Spirits 2012" },
435 	{ "NPJH50838", "Pro Yakyuu Spirits 2014" },
436 	{ "NPJH50492", "Puyo Puyo!! 20th Anniversary" },
437 	{ "ULUS10292", "Renegrade Squadron" },
438 	{ "UCJS10090", "Resistance - Retribution" },
439 	{ "ULES00670", "Rocky Balboa" },
440 	{ "ULJS00360", "Rurouni Kenshin - Meiji Kenkaku Romantan Saisen" },
441 	{ "UCUS98615", "SOCOM - Fireteam Bravo" },
442 	{ "UCUS98645", "SOCOM - Fireteam Bravo 2" },
443 	{ "UCUS98716", "SOCOM - Fireteam Bravo 3" },
444 	{ "NPJH50460", "Sengoku Basara - Chronicles Heroes" },
445 	{ "ULJM05436", "Sengoku Basara - Battle Heroes" },
446 	{ "ULJM05637", "Shin Sangoku Musou - Multi Raid 2" },
447 	{ "ULJM05035", "Shinobido - Tales of the Ninja" },
448 	{ "ULUS10194", "Shrek - Smash and Crash Racing" },
449 	{ "UCES00758", "Smash Court Tennis 3" },
450 	{ "ULUS10195", "Sonic Rivals" },
451 	{ "ULUS10457", "Soul Calibur - Broken Destiny" },
452 	{ "ULUS10513", "Split Second - Velocity" },
453 	{ "ULES00183", "Star Wars Battle Front 2" },
454 	{ "ULUS10062", "Street Fighter Alpha 3 MAX" },
455 	{ "NPUH10020", "Strikers 1945 Plus Portable" },
456 	{ "ULUS10548", "TRON - Evolution" },
457 	{ "NPJH50426", "Taiko no Tatsujin Portable DX" },
458 	{ "ULUS10466", "Tekken 6" },
459 	{ "NPJH50691", "Tokusatsu University" },
460 	//looks like can be crosslinked
461 	{ "ULUS10445", "Tom Clancy's Ghost Recon - Predator" },
462 	{ "ULES01350", "Tom Clancy's Ghost Recon - Predator" },
463 	{ "NPJH50789", "Toukiden" },
464 	{ "NPJH50878", "Toukiden - Kiwami" },
465 	{ "UCUS98601", "Twisted Metal - Head On" },
466 	{ "ULUS10508", "UFC Undisputed 2010" },
467 	{ "ULJS00069", "Ultraman Fighting Evo Zero" },
468 	{ "ULUS10003", "Untold Legends - Brotherhood of the Blade" },
469 	{ "ULUS10086", "Untold Legends - The Warrior's Code" },
470 	{ "ULUS10515", "Valkryia Chronicles 2" },
471 	{ "ULUS10087", "Viewtiful Joe" },
472 	{ "ULUS10246", "Virtua Tennis 3" },
473 	{ "ULUS82741", "WWE 2K14" },
474 	{ "ULUS10543", "WWE Smackdown vs. Raw 2011" },
475 	{ "ULUS10423", "Warriors Orochi 2" },
476 	{ "ULJM05553", "Warship Gunner 2 Portable" },
477 	{ "ULJS00155", "Way Of The Samurai" },
478 	{ "UCES00465", "Wipeout Pulse" },
479 	{ "ULUS10321", "World Series of Poker 2008 - Battle for the Bracelets" },
480 	{ "NPUH10045", "Worms Battle Islands" },
481 	{ "ULUS10065", "Worms Open Warfare" },
482 	{ "ULUS10260", "Worms Open Warfare 2" },
483 	{ "ULJM05734", "Yu-Gi-Oh! 5D's Tag Force 5" },
484 	{ "ULJM05940", "Yu-Gi-Oh! 5D's Tag Force 6" },
485 	{ "NPJH00142", "Yu-Gi-Oh! Arc-V Tag Force" },
486 	{ "ULJM05151", "Yu-Gi-Oh! GX Tag Force" },
487 	{ "ULJM05373", "Yu-Gi-Oh! GX Tag Force 3" },
488 	{ "NPUG80086", "flOw" },
489 };
490 
491 // Function Prototypes
492 const char * strcpyxml(char * out, const char * in, uint32_t size);
493 
494 // Function Prototypes
495 void interrupt(int sig);
496 void enable_address_reuse(int fd);
497 void enable_keepalive(int fd);
498 void change_nodelay_mode(int fd, int flag);
499 void change_blocking_mode(int fd, int nonblocking);
500 int create_listen_socket(uint16_t port);
501 int server_loop(int server);
502 
__AdhocServerInit()503 void __AdhocServerInit() {
504 	// Database Product name will update if new game region played on my server to list possible crosslinks
505 	productids = std::vector<db_productid>(default_productids, default_productids + ARRAY_SIZE(default_productids));
506 	crosslinks = std::vector<db_crosslink>(default_crosslinks, default_crosslinks + ARRAY_SIZE(default_crosslinks));
507 }
508 
509 /**
510  * Login User into Database (Stream)
511  * @param fd Socket
512  * @param ip IP Address (Network Order)
513  */
login_user_stream(int fd,uint32_t ip)514 void login_user_stream(int fd, uint32_t ip)
515 {
516 	// Enough Space available
517 	if(_db_user_count < SERVER_USER_MAXIMUM)
518 	{
519 		// Check IP Duplication
520 		SceNetAdhocctlUserNode * u = _db_user;
521 		while(u != NULL && u->resolver.ip != ip) u = u->next;
522 
523 		if (u != NULL) { // IP Already existed
524 			WARN_LOG(SCENET, "AdhocServer: Already Existing IP: %s\n", ip2str(*(in_addr*)&u->resolver.ip).c_str());
525 		}
526 
527 		// Unique IP Address
528 		else //if(u == NULL)
529 		{
530 			// Allocate User Node Memory
531 			SceNetAdhocctlUserNode * user = (SceNetAdhocctlUserNode *)malloc(sizeof(SceNetAdhocctlUserNode));
532 
533 			// Allocated User Node Memory
534 			if(user != NULL)
535 			{
536 				// Clear Memory
537 				memset(user, 0, sizeof(SceNetAdhocctlUserNode));
538 
539 				// Save Socket
540 				user->stream = fd;
541 
542 				// Save IP
543 				user->resolver.ip = ip;
544 
545 				// Link into User List
546 				user->next = _db_user;
547 				if(_db_user != NULL) _db_user->prev = user;
548 				_db_user = user;
549 
550 				// Initialize Death Clock
551 				user->last_recv = time(NULL);
552 
553 				// Notify User
554 				INFO_LOG(SCENET, "AdhocServer: New Connection from %s", ip2str(*(in_addr*)&user->resolver.ip).c_str());
555 
556 				// Fix User Counter
557 				_db_user_count++;
558 
559 				// Update Status Log
560 				update_status();
561 
562 				// Exit Function
563 				return;
564 			}
565 		}
566 	}
567 
568 	// Duplicate IP, Allocation Error or not enough space - Close Stream
569 	closesocket(fd);
570 }
571 
572 /**
573  * Login User into Database (Login Data)
574  * @param user User Node
575  * @param data Login Packet
576  */
login_user_data(SceNetAdhocctlUserNode * user,SceNetAdhocctlLoginPacketC2S * data)577 void login_user_data(SceNetAdhocctlUserNode * user, SceNetAdhocctlLoginPacketC2S * data)
578 {
579 	// Product Code Check
580 	int valid_product_code = 1;
581 
582 	// Iterate Characters
583 	int i = 0; for(; i < PRODUCT_CODE_LENGTH && valid_product_code == 1; i++)
584 	{
585 		// Valid Characters
586 		if(!((data->game.data[i] >= 'A' && data->game.data[i] <= 'Z') || (data->game.data[i] >= '0' && data->game.data[i] <= '9'))) valid_product_code = 0;
587 	}
588 
589 	// Valid Packet Data
590 	if(valid_product_code == 1 && memcmp(&data->mac, "\xFF\xFF\xFF\xFF\xFF\xFF", sizeof(data->mac)) != 0 && memcmp(&data->mac, "\x00\x00\x00\x00\x00\x00", sizeof(data->mac)) != 0 && data->name.data[0] != 0)
591 	{
592 		// Check for duplicated MAC as most games identify Players by MAC
593 		SceNetAdhocctlUserNode* u = _db_user;
594 		while (u != NULL && !IsMatch(u->resolver.mac, data->mac)) u = u->next;
595 
596 		if (u != NULL) { // MAC Already existed
597 			WARN_LOG(SCENET, "AdhocServer: Already Existing MAC: %s [%s]\n", mac2str(&data->mac).c_str(), ip2str(*(in_addr*)&u->resolver.ip).c_str());
598 		}
599 
600 		// Game Product Override
601 		game_product_override(&data->game);
602 
603 		// Find existing Game
604 		SceNetAdhocctlGameNode * game = _db_game;
605 		while(game != NULL && strncmp(game->game.data, data->game.data, PRODUCT_CODE_LENGTH) != 0) game = game->next;
606 
607 		// Game not found
608 		if(game == NULL)
609 		{
610 			// Allocate Game Node Memory
611 			game = (SceNetAdhocctlGameNode *)malloc(sizeof(SceNetAdhocctlGameNode));
612 
613 			// Allocated Game Node Memory
614 			if(game != NULL)
615 			{
616 				// Clear Memory
617 				memset(game, 0, sizeof(SceNetAdhocctlGameNode));
618 
619 				// Save Game Product ID
620 				game->game = data->game;
621 
622 				// Link into Game List
623 				game->next = _db_game;
624 				if(_db_game != NULL) _db_game->prev = game;
625 				_db_game = game;
626 			}
627 		}
628 
629 		// Game now available
630 		if(game != NULL)
631 		{
632 			// Save MAC
633 			user->resolver.mac = data->mac;
634 
635 			// Save Nickname
636 			user->resolver.name = data->name;
637 
638 			// Increase Player Count in Game Node
639 			game->playercount++;
640 
641 			// Link Game to Player
642 			user->game = game;
643 
644 			// Notify User
645 			char safegamestr[10];
646 			memset(safegamestr, 0, sizeof(safegamestr));
647 			strncpy(safegamestr, game->game.data, PRODUCT_CODE_LENGTH);
648 			INFO_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) started playing %s", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), safegamestr);
649 
650 			// Update Status Log
651 			update_status();
652 
653 			// Leave Function
654 			return;
655 		}
656 	}
657 
658 	// Invalid Packet Data
659 	else
660 	{
661 		// Notify User
662 		WARN_LOG(SCENET, "AdhocServer: Invalid Login Packet Contents from %s", ip2str(*(in_addr*)&user->resolver.ip).c_str());
663 	}
664 
665 	// Logout User - Out of Memory or Invalid Arguments
666 	logout_user(user);
667 }
668 
669 /**
670  * Logout User from Database
671  * @param user User Node
672  */
logout_user(SceNetAdhocctlUserNode * user)673 void logout_user(SceNetAdhocctlUserNode * user)
674 {
675 	// Disconnect from Group
676 	if(user->group != NULL) disconnect_user(user);
677 
678 	// Unlink Leftside (Beginning)
679 	if(user->prev == NULL) _db_user = user->next;
680 
681 	// Unlink Leftside (Other)
682 	else user->prev->next = user->next;
683 
684 	// Unlink Rightside
685 	if(user->next != NULL) user->next->prev = user->prev;
686 
687 	// Close Stream
688 	closesocket(user->stream);
689 
690 	// Playing User
691 	if(user->game != NULL)
692 	{
693 		// Notify User
694 		char safegamestr[10];
695 		memset(safegamestr, 0, sizeof(safegamestr));
696 		strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
697 		INFO_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) stopped playing %s", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), safegamestr);
698 
699 		// Fix Game Player Count
700 		user->game->playercount--;
701 
702 		// Empty Game Node
703 		if(user->game->playercount == 0)
704 		{
705 			// Unlink Leftside (Beginning)
706 			if(user->game->prev == NULL) _db_game = user->game->next;
707 
708 			// Unlink Leftside (Other)
709 			else user->game->prev->next = user->game->next;
710 
711 			// Unlink Rightside
712 			if(user->game->next != NULL) user->game->next->prev = user->game->prev;
713 
714 			// Free Game Node Memory
715 			free(user->game);
716 		}
717 	}
718 
719 	// Unidentified User
720 	else
721 	{
722 		// Notify User
723 		WARN_LOG(SCENET, "AdhocServer: Dropped Connection to %s", ip2str(*(in_addr*)&user->resolver.ip).c_str());
724 	}
725 
726 	// Free Memory
727 	free(user);
728 
729 	// Fix User Counter
730 	_db_user_count--;
731 
732 	// Update Status Log
733 	update_status();
734 }
735 
736 /**
737  * Free Database Memory
738  */
free_database()739 void free_database()
740 {
741 	// There are users playing
742 	if(_db_user_count > 0)
743 	{
744 		// Send Shutdown Notice
745 		spread_message(NULL, SERVER_SHUTDOWN_MESSAGE);
746 	}
747 
748 	// Iterate Users for Deletion
749 	SceNetAdhocctlUserNode * user = _db_user;
750 	while(user != NULL)
751 	{
752 		// Next User (for safe delete)
753 		SceNetAdhocctlUserNode * next = user->next;
754 
755 		// Logout User
756 		logout_user(user);
757 
758 		// Move Pointer
759 		user = next;
760 	}
761 }
762 
763 /**
764  * Connect User to Game Group
765  * @param user User Node
766  * @param group Group Name
767  */
connect_user(SceNetAdhocctlUserNode * user,SceNetAdhocctlGroupName * group)768 void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group)
769 {
770 	// Group Name Check
771 	int valid_group_name = 1;
772 	{
773 		// Iterate Characters
774 		int i = 0; for(; i < ADHOCCTL_GROUPNAME_LEN && valid_group_name == 1; i++)
775 		{
776 			// End of Name
777 			if(group->data[i] == 0) break;
778 
779 			// A - Z
780 			if(group->data[i] >= 'A' && group->data[i] <= 'Z') continue;
781 
782 			// a - z
783 			if(group->data[i] >= 'a' && group->data[i] <= 'z') continue;
784 
785 			// 0 - 9
786 			if(group->data[i] >= '0' && group->data[i] <= '9') continue;
787 
788 			// Invalid Symbol
789 			valid_group_name = 0;
790 		}
791 	}
792 
793 	// Valid Group Name
794 	if(valid_group_name == 1)
795 	{
796 		// User is disconnected
797 		if(user->group == NULL)
798 		{
799 			// Find Group in Game Node
800 			SceNetAdhocctlGroupNode * g = user->game->group;
801 			while(g != NULL && strncmp((char *)g->group.data, (char *)group->data, ADHOCCTL_GROUPNAME_LEN) != 0) g = g->next;
802 
803 			// BSSID Packet
804 			SceNetAdhocctlConnectBSSIDPacketS2C bssid;
805 
806 			// Set BSSID Opcode
807 			bssid.base.opcode = OPCODE_CONNECT_BSSID;
808 
809 			// Set Default BSSID
810 			bssid.mac = user->resolver.mac;
811 
812 			// No Group found
813 			if(g == NULL)
814 			{
815 				// Allocate Group Memory
816 				g = (SceNetAdhocctlGroupNode *)malloc(sizeof(SceNetAdhocctlGroupNode));
817 
818 				// Allocated Group Memory
819 				if(g != NULL)
820 				{
821 					// Clear Memory
822 					memset(g, 0, sizeof(SceNetAdhocctlGroupNode));
823 
824 					// Link Game Node
825 					g->game = user->game;
826 
827 					// Link Group Node
828 					g->next = g->game->group;
829 					if(g->game->group != NULL) g->game->group->prev = g;
830 					g->game->group = g;
831 
832 					// Copy Group Name
833 					g->group = *group;
834 
835 					// Increase Group Counter for Game
836 					g->game->groupcount++;
837 				}
838 			}
839 
840 			// Group now available
841 			if(g != NULL)
842 			{
843 				// Iterate remaining Group Players
844 				SceNetAdhocctlUserNode * peer = g->player;
845 				while(peer != NULL)
846 				{
847 					// Connect Packet
848 					SceNetAdhocctlConnectPacketS2C packet;
849 
850 					// Clear Memory
851 					// memset(&packet, 0, sizeof(packet));
852 
853 					// Set Connect Opcode
854 					packet.base.opcode = OPCODE_CONNECT;
855 
856 					// Set Player Name
857 					packet.name = user->resolver.name;
858 
859 					// Set Player MAC
860 					packet.mac = user->resolver.mac;
861 
862 					// Set Player IP
863 					packet.ip = user->resolver.ip;
864 
865 					// Send Data
866 					int iResult = send(peer->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
867 					if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: connect_user[send peer] (Socket error %d)", errno);
868 
869 					// Set Player Name
870 					packet.name = peer->resolver.name;
871 
872 					// Set Player MAC
873 					packet.mac = peer->resolver.mac;
874 
875 					// Set Player IP
876 					packet.ip = peer->resolver.ip;
877 
878 					// Send Data
879 					iResult = send(user->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
880 					if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: connect_user[send user] (Socket error %d)", errno);
881 
882 					// Set BSSID
883 					if(peer->group_next == NULL) bssid.mac = peer->resolver.mac;
884 
885 					// Move Pointer
886 					peer = peer->group_next;
887 				}
888 
889 				// Link User to Group
890 				user->group_next = g->player;
891 				if(g->player != NULL) g->player->group_prev = user;
892 				g->player = user;
893 
894 				// Link Group to User
895 				user->group = g;
896 
897 				// Increase Player Count
898 				g->playercount++;
899 
900 				// Send Network BSSID to User
901 				int iResult = send(user->stream, (const char*)&bssid, sizeof(bssid), MSG_NOSIGNAL);
902 				if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: connect_user[send user bssid] (Socket error %d)", errno);
903 
904 				// Notify User
905 				char safegamestr[10];
906 				memset(safegamestr, 0, sizeof(safegamestr));
907 				strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
908 				char safegroupstr[9];
909 				memset(safegroupstr, 0, sizeof(safegroupstr));
910 				strncpy(safegroupstr, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
911 				INFO_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) joined %s group %s", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), safegamestr, safegroupstr);
912 
913 				// Update Status Log
914 				update_status();
915 
916 				// Exit Function
917 				return;
918 			}
919 		}
920 
921 		// Already connected to another group
922 		else
923 		{
924 			// Notify User
925 			char safegamestr[10];
926 			memset(safegamestr, 0, sizeof(safegamestr));
927 			strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
928 			char safegroupstr[9];
929 			memset(safegroupstr, 0, sizeof(safegroupstr));
930 			strncpy(safegroupstr, (char *)group->data, ADHOCCTL_GROUPNAME_LEN);
931 			char safegroupstr2[9];
932 			memset(safegroupstr2, 0, sizeof(safegroupstr2));
933 			strncpy(safegroupstr2, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
934 			WARN_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) attempted to join %s group %s without disconnecting from %s first", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), safegamestr, safegroupstr, safegroupstr2);
935 		}
936 	}
937 
938 	// Invalid Group Name
939 	else
940 	{
941 		// Notify User
942 		char safegamestr[10];
943 		memset(safegamestr, 0, sizeof(safegamestr));
944 		strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
945 		char safegroupstr[9];
946 		memset(safegroupstr, 0, sizeof(safegroupstr));
947 		strncpy(safegroupstr, (char *)group->data, ADHOCCTL_GROUPNAME_LEN);
948 		WARN_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) attempted to join invalid %s group %s", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), safegamestr, safegroupstr);
949 	}
950 
951 	// Invalid State, Out of Memory or Invalid Group Name
952 	logout_user(user);
953 }
954 
955 /**
956  * Disconnect User from Game Group
957  * @param user User Node
958  */
disconnect_user(SceNetAdhocctlUserNode * user)959 void disconnect_user(SceNetAdhocctlUserNode * user)
960 {
961 	// User is connected
962 	if(user->group != NULL)
963 	{
964 		// Unlink Leftside (Beginning)
965 		if(user->group_prev == NULL) user->group->player = user->group_next;
966 
967 		// Unlink Leftside (Other)
968 		else user->group_prev->group_next = user->group_next;
969 
970 		// Unlink Rightside
971 		if(user->group_next != NULL) user->group_next->group_prev = user->group_prev;
972 
973 		// Fix Player Count
974 		user->group->playercount--;
975 
976 		// Iterate remaining Group Players
977 		SceNetAdhocctlUserNode * peer = user->group->player;
978 		while(peer != NULL)
979 		{
980 			// Disconnect Packet
981 			SceNetAdhocctlDisconnectPacketS2C packet;
982 
983 			// Clear Memory
984 			// memset(&packet, 0, sizeof(packet));
985 
986 			// Set Disconnect Opcode
987 			packet.base.opcode = OPCODE_DISCONNECT;
988 
989 			// Set User IP
990 			packet.ip = user->resolver.ip;
991 
992 			// Send Data
993 			int iResult = send(peer->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
994 			if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: disconnect_user[send peer] (Socket error %d)", errno);
995 
996 			// Move Pointer
997 			peer = peer->group_next;
998 		}
999 
1000 		// Notify User
1001 		char safegamestr[10];
1002 		memset(safegamestr, 0, sizeof(safegamestr));
1003 		strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
1004 		char safegroupstr[9];
1005 		memset(safegroupstr, 0, sizeof(safegroupstr));
1006 		strncpy(safegroupstr, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
1007 		INFO_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) left %s group %s", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), safegamestr, safegroupstr);
1008 
1009 		// Empty Group
1010 		if(user->group->playercount == 0)
1011 		{
1012 			// Unlink Leftside (Beginning)
1013 			if(user->group->prev == NULL) user->group->game->group = user->group->next;
1014 
1015 			// Unlink Leftside (Other)
1016 			else user->group->prev->next = user->group->next;
1017 
1018 			// Unlink Rightside
1019 			if(user->group->next != NULL) user->group->next->prev = user->group->prev;
1020 
1021 			// Free Group Memory
1022 			free(user->group);
1023 
1024 			// Decrease Group Counter in Game Node
1025 			user->game->groupcount--;
1026 		}
1027 
1028 		// Unlink from Group
1029 		user->group = NULL;
1030 		user->group_next = NULL;
1031 		user->group_prev = NULL;
1032 
1033 		// Update Status Log
1034 		update_status();
1035 
1036 		// Exit Function
1037 		return;
1038 	}
1039 
1040 	// Not in a game group
1041 	else
1042 	{
1043 		// Notify User
1044 		char safegamestr[10];
1045 		memset(safegamestr, 0, sizeof(safegamestr));
1046 		strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
1047 		WARN_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) attempted to leave %s group without joining one first", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), safegamestr);
1048 	}
1049 
1050 	// Delete User
1051 	logout_user(user);
1052 }
1053 
1054 /**
1055  * Send Game Group List
1056  * @param user User Node
1057  */
send_scan_results(SceNetAdhocctlUserNode * user)1058 void send_scan_results(SceNetAdhocctlUserNode * user)
1059 {
1060 	// User is disconnected
1061 	if(user->group == NULL)
1062 	{
1063 		// Iterate Groups
1064 		SceNetAdhocctlGroupNode * group = user->game->group;
1065 		for(; group != NULL; group = group->next)
1066 		{
1067 			// Scan Result Packet
1068 			SceNetAdhocctlScanPacketS2C packet;
1069 
1070 			// Clear Memory
1071 			// memset(&packet, 0, sizeof(packet));
1072 
1073 			// Set Opcode
1074 			packet.base.opcode = OPCODE_SCAN;
1075 
1076 			// Set Group Name
1077 			packet.group = group->group;
1078 
1079 			// Iterate Players in Network Group
1080 			SceNetAdhocctlUserNode * peer = group->player;
1081 			for(; peer != NULL; peer = peer->group_next)
1082 			{
1083 				// Found Network Founder
1084 				if(peer->group_next == NULL)
1085 				{
1086 					// Set Group Host MAC
1087 					packet.mac = peer->resolver.mac;
1088 				}
1089 			}
1090 
1091 			// Send Group Packet
1092 			int iResult = send(user->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
1093 			if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: send_scan_result[send user] (Socket error %d)", errno);
1094 		}
1095 
1096 		// Notify Player of End of Scan
1097 		uint8_t opcode = OPCODE_SCAN_COMPLETE;
1098 		int iResult = send(user->stream, (const char*)&opcode, 1, MSG_NOSIGNAL);
1099 		if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: send_scan_result[send peer complete] (Socket error %d)", errno);
1100 
1101 		// Notify User
1102 		char safegamestr[10];
1103 		memset(safegamestr, 0, sizeof(safegamestr));
1104 		strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
1105 		INFO_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) requested information on %d %s groups", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), user->game->groupcount, safegamestr);
1106 
1107 		// Exit Function
1108 		return;
1109 	}
1110 
1111 	// User in a game group
1112 	else
1113 	{
1114 		// Notify User
1115 		char safegamestr[10];
1116 		memset(safegamestr, 0, sizeof(safegamestr));
1117 		strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
1118 		char safegroupstr[9];
1119 		memset(safegroupstr, 0, sizeof(safegroupstr));
1120 		strncpy(safegroupstr, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
1121 		WARN_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) attempted to scan for %s groups without disconnecting from %s first", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), safegamestr, safegroupstr);
1122 	}
1123 
1124 	// Delete User
1125 	logout_user(user);
1126 }
1127 
1128 /**
1129  * Spread Chat Message in P2P Network
1130  * @param user Sender User Node
1131  * @param message Chat Message
1132  */
spread_message(SceNetAdhocctlUserNode * user,const char * message)1133 void spread_message(SceNetAdhocctlUserNode *user, const char *message)
1134 {
1135 	// Global Notice
1136 	if(user == NULL)
1137 	{
1138 		// Iterate Players
1139 		for(user = _db_user; user != NULL; user = user->next)
1140 		{
1141 			// Player has access to chat
1142 			if(user->group != NULL)
1143 			{
1144 				// Chat Packet
1145 				SceNetAdhocctlChatPacketS2C packet;
1146 
1147 				// Clear Memory
1148 				memset(&packet, 0, sizeof(packet));
1149 
1150 				// Set Chat Opcode
1151 				packet.base.base.opcode = OPCODE_CHAT;
1152 
1153 				// Set Chat Message
1154 				strcpy(packet.base.message, message);
1155 
1156 				// Send Data
1157 				int iResult = send(user->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
1158 				if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: spread_message[send user chat] (Socket error %d)", errno);
1159 			}
1160 		}
1161 
1162 		// Prevent NULL Error
1163 		return;
1164 	}
1165 
1166 	// User is connected
1167 	else if(user->group != NULL)
1168 	{
1169 		// Broadcast Range Counter
1170 		uint32_t counter = 0;
1171 
1172 		// Iterate Group Players
1173 		SceNetAdhocctlUserNode * peer = user->group->player;
1174 		while(peer != NULL)
1175 		{
1176 			// Skip Self
1177 			if(peer == user)
1178 			{
1179 				// Move Pointer
1180 				peer = peer->group_next;
1181 
1182 				// Continue Loop
1183 				continue;
1184 			}
1185 
1186 			// Chat Packet
1187 			SceNetAdhocctlChatPacketS2C packet;
1188 
1189 			// Set Chat Opcode
1190 			packet.base.base.opcode = OPCODE_CHAT;
1191 
1192 			// Set Chat Message
1193 			strcpy(packet.base.message, message);
1194 
1195 			// Set Sender Nickname
1196 			packet.name = user->resolver.name;
1197 
1198 			// Send Data
1199 			int iResult = send(peer->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
1200 			if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: spread_message[send peer chat] (Socket error %d)", errno);
1201 
1202 			// Move Pointer
1203 			peer = peer->group_next;
1204 
1205 			// Increase Broadcast Range Counter
1206 			counter++;
1207 		}
1208 
1209 		// Message Sent
1210 		if(counter > 0)
1211 		{
1212 			// Notify User
1213 			char safegamestr[10];
1214 			memset(safegamestr, 0, sizeof(safegamestr));
1215 			strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
1216 			char safegroupstr[9];
1217 			memset(safegroupstr, 0, sizeof(safegroupstr));
1218 			strncpy(safegroupstr, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
1219 			INFO_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) sent \"%s\" to %d players in %s group %s", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), message, counter, safegamestr, safegroupstr);
1220 		}
1221 
1222 		// Exit Function
1223 		return;
1224 	}
1225 
1226 	// User not in a game group
1227 	else
1228 	{
1229 		// Notify User
1230 		char safegamestr[10];
1231 		memset(safegamestr, 0, sizeof(safegamestr));
1232 		strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
1233 		WARN_LOG(SCENET, "AdhocServer: %s (MAC: %s - IP: %s) attempted to send a text message without joining a %s group first", (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str(), safegamestr);
1234 	}
1235 
1236 	// Delete User
1237 	logout_user(user);
1238 }
1239 
1240 /**
1241  * Get User State
1242  * @param user User Node
1243  */
get_user_state(SceNetAdhocctlUserNode * user)1244 int get_user_state(SceNetAdhocctlUserNode * user)
1245 {
1246 	// Timeout Status
1247 	if((time(NULL) - user->last_recv) >= SERVER_USER_TIMEOUT) return USER_STATE_TIMED_OUT;
1248 
1249 	// Waiting Status
1250 	if(user->game == NULL) return USER_STATE_WAITING;
1251 
1252 	// Logged-In Status
1253 	return USER_STATE_LOGGED_IN;
1254 }
1255 
1256 /**
1257  * Clear RX Buffer
1258  * @param user User Node
1259  * @param clear Number of Bytes to clear (-1 for all)
1260  */
clear_user_rxbuf(SceNetAdhocctlUserNode * user,int clear)1261 void clear_user_rxbuf(SceNetAdhocctlUserNode * user, int clear)
1262 {
1263 	// Fix Clear Length
1264 	if(clear == -1 || clear > (int)user->rxpos) clear = user->rxpos;
1265 
1266 	// Move Buffer
1267 	memmove(user->rx, user->rx + clear, sizeof(user->rx) - clear);
1268 
1269 	// Fix RX Buffer Pointer
1270 	user->rxpos -= clear;
1271 }
1272 
1273 /**
1274  * Patch Game Product Code
1275  * @param product To-be-patched Product Code
1276  * @param from If the Product Code matches this...
1277  * @param to ... then change it to this one.
1278  */
game_product_relink(SceNetAdhocctlProductCode * product,char * from,char * to)1279 void game_product_relink(SceNetAdhocctlProductCode * product, char * from, char * to)
1280 {
1281 	// Relink Region Code
1282 	if(strncmp(product->data, from, PRODUCT_CODE_LENGTH) == 0) strncpy(product->data, to, PRODUCT_CODE_LENGTH);
1283 }
1284 
1285 /**
1286  * Game Product Override (used for mixing multi-region games)
1287  * @param product IN: Source Product OUT: Override Product
1288  */
game_product_override(SceNetAdhocctlProductCode * product)1289 void game_product_override(SceNetAdhocctlProductCode * product)
1290 {
1291 	// Safe Product Code
1292 	char productid[PRODUCT_CODE_LENGTH + 1];
1293 
1294 	// Prepare Safe Product Code
1295 	strncpy(productid, product->data, PRODUCT_CODE_LENGTH);
1296 	productid[PRODUCT_CODE_LENGTH] = 0;
1297 
1298 	// Database Handle
1299 	//sqlite3 * db = NULL;
1300 
1301 	// Open Database
1302 	//if(sqlite3_open(SERVER_DATABASE, &db) == SQLITE_OK)
1303 	{
1304 		// Crosslinked Flag
1305 		int crosslinked = 0;
1306 
1307 		// Exists Flag
1308 		int exists = 0;
1309 
1310 		// SQL Statements
1311 		/*const char * sql = "SELECT id_to FROM crosslinks WHERE id_from=?;";
1312 		const char * sql2 = "SELECT * FROM productids WHERE id=?;";
1313 		const char * sql3 = "INSERT INTO productids(id, name) VALUES(?, ?);";
1314 
1315 		// Prepared SQL Statement
1316 		sqlite3_stmt * statement = NULL;
1317 
1318 		// Prepare SQL Statement
1319 		if(sqlite3_prepare_v2(db, sql, strlen(sql) + 1, &statement, NULL) == SQLITE_OK)
1320 		{
1321 			// Bind SQL Statement Data
1322 			if(sqlite3_bind_text(statement, 1, productid, strlen(productid), SQLITE_STATIC) == SQLITE_OK)
1323 			{
1324 				// Found Matching Row
1325 				if(sqlite3_step(statement) == SQLITE_ROW)
1326 				{
1327 					// Grab Crosslink ID
1328 					const char * crosslink = (const char *)sqlite3_column_text(statement, 0);
1329 
1330 					// Crosslink Product Code
1331 					strncpy(product->data, crosslink, PRODUCT_CODE_LENGTH);
1332 
1333 					// Log Crosslink
1334 					INFO_LOG(SCENET, "Crosslinked %s to %s", productid, crosslink);
1335 
1336 					// Set Crosslinked Flag
1337 					crosslinked = 1;
1338 				}
1339 			}
1340 
1341 			// Destroy Prepared SQL Statement
1342 			sqlite3_finalize(statement);
1343 		}*/
1344 		for (std::vector<db_crosslink>::iterator it = crosslinks.begin(); it != crosslinks.end(); it++) {
1345 			if (IsMatch(it->id_from, productid)) {
1346 				// Grab Crosslink ID
1347 				char crosslink[PRODUCT_CODE_LENGTH + 1];
1348 				strncpy(crosslink, it->id_to, PRODUCT_CODE_LENGTH);
1349 				crosslink[PRODUCT_CODE_LENGTH] = 0; // null terminated
1350 
1351 				// Crosslink Product Code
1352 				strncpy(product->data, it->id_to, PRODUCT_CODE_LENGTH);
1353 
1354 				// Log Crosslink
1355 				INFO_LOG(SCENET, "AdhocServer: Crosslinked %s to %s", productid, crosslink);
1356 
1357 				// Set Crosslinked Flag
1358 				crosslinked = 1;
1359 				break;
1360 			}
1361 		}
1362 
1363 		// Not Crosslinked
1364 		if(!crosslinked)
1365 		{
1366 			// Prepare SQL Statement
1367 			/*if(sqlite3_prepare_v2(db, sql2, strlen(sql2) + 1, &statement, NULL) == SQLITE_OK)
1368 			{
1369 				// Bind SQL Statement Data
1370 				if(sqlite3_bind_text(statement, 1, productid, strlen(productid), SQLITE_STATIC) == SQLITE_OK)
1371 				{
1372 					// Found Matching Row
1373 					if(sqlite3_step(statement) == SQLITE_ROW)
1374 					{
1375 						// Set Exists Flag
1376 						exists = 1;
1377 					}
1378 				}
1379 
1380 				// Destroy Prepare SQL Statement
1381 				sqlite3_finalize(statement);
1382 			}*/
1383 			for (std::vector<db_productid>::iterator it = productids.begin(); it != productids.end(); it++) {
1384 				if (IsMatch(it->id, productid)) {
1385 					// Set Exists Flag
1386 					exists = 1;
1387 					break;
1388 				}
1389 			}
1390 
1391 			// Game doesn't exist in Database
1392 			if(!exists)
1393 			{
1394 				// Prepare SQL Statement
1395 				/*if(sqlite3_prepare_v2(db, sql3, strlen(sql3) + 1, &statement, NULL) == SQLITE_OK)
1396 				{
1397 					// Bind SQL Statement Data
1398 					if(sqlite3_bind_text(statement, 1, productid, strlen(productid), SQLITE_STATIC) == SQLITE_OK && sqlite3_bind_text(statement, 2, productid, strlen(productid), SQLITE_STATIC) == SQLITE_OK)
1399 					{
1400 						// Save Product ID to Database
1401 						if(sqlite3_step(statement) == SQLITE_DONE)
1402 						{
1403 							// Log Addition
1404 							INFO_LOG(SCENET, "Added Unknown Product ID %s to Database", productid);
1405 						}
1406 					}
1407 
1408 					// Destroy Prepare SQL Statement
1409 					sqlite3_finalize(statement);
1410 				}*/
1411 				db_productid unkproduct;
1412 				strncpy(unkproduct.id, productid, sizeof(unkproduct.id));
1413 				strncpy(unkproduct.name, productid, sizeof(productid));
1414 				productids.push_back(unkproduct); //productids[productids.size()] = unkproduct;
1415 				// Log Addition
1416 				INFO_LOG(SCENET, "AdhocServer: Added Unknown Product ID %s to Database", productid);
1417 			}
1418 		}
1419 
1420 		// Close Database
1421 		//sqlite3_close(db);
1422 	}
1423 }
1424 
1425 /**
1426  * Update Status Logfile
1427  */
update_status()1428 void update_status()
1429 {
1430 	// Open Logfile
1431 	FILE * log = File::OpenCFile(Path(SERVER_STATUS_XMLOUT), "w");
1432 
1433 	// Opened Logfile
1434 	if(log != NULL)
1435 	{
1436 		// Write XML Header
1437 		fprintf(log, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1438 
1439 		// Write XSL Processor Information
1440 		fprintf(log, "<?xml-stylesheet type=\"text/xsl\" href=\"status.xsl\"?>\n");
1441 
1442 		// Output Root Tag + User Count
1443 		fprintf(log, "<prometheus usercount=\"%u\">\n", _db_user_count);
1444 
1445 		// Database Handle
1446 		//sqlite3 * db = NULL;
1447 
1448 		// Open Database
1449 		//if(sqlite3_open(SERVER_DATABASE, &db) == SQLITE_OK)
1450 		{
1451 			// Iterate Games
1452 			SceNetAdhocctlGameNode * game = _db_game; for(; game != NULL; game = game->next)
1453 			{
1454 				// Safe Product ID
1455 				char productid[PRODUCT_CODE_LENGTH + 1];
1456 				strncpy(productid, game->game.data, PRODUCT_CODE_LENGTH);
1457 				productid[PRODUCT_CODE_LENGTH] = 0;
1458 
1459 				// Display Name
1460 				char displayname[128];
1461 				memset(displayname, 0, sizeof(displayname));
1462 
1463 				// SQL Statement
1464 				//const char * sql = "SELECT name FROM productids WHERE id=?;";
1465 
1466 				// Prepared SQL Statement
1467 				//sqlite3_stmt * statement = NULL;
1468 
1469 				// Prepare SQL Statement
1470 				/*if(sqlite3_prepare_v2(db, sql, strlen(sql) + 1, &statement, NULL) == SQLITE_OK)
1471 				{
1472 					// Bind SQL Statement Data
1473 					if(sqlite3_bind_text(statement, 1, productid, strlen(productid), SQLITE_STATIC) == SQLITE_OK)
1474 					{
1475 						// Found Matching Row
1476 						if(sqlite3_step(statement) == SQLITE_ROW)
1477 						{
1478 							// Fetch Game Name from Database
1479 							const char * gamename = (const char *)sqlite3_column_text(statement, 0);
1480 
1481 							// Copy Game Name
1482 							strcpyxml(displayname, gamename, sizeof(displayname));
1483 						}
1484 
1485 						// Game not in Database
1486 						else
1487 						{
1488 							// Use Product Code as Name
1489 							strcpyxml(displayname, productid, sizeof(displayname));
1490 						}
1491 					}
1492 
1493 					// Destroy Prepared SQL Statement
1494 					sqlite3_finalize(statement);
1495 				}*/
1496 				//db_productid *foundid = NULL;
1497 				bool found = false;
1498 				for (std::vector<db_productid>::iterator it = productids.begin(); it != productids.end(); it++) {
1499 					if (IsMatch(it->id, productid)) {
1500 						// Copy Game Name
1501 						strcpyxml(displayname, it->name, sizeof(displayname));
1502 						found = true;
1503 						break;
1504 					}
1505 				}
1506 
1507 				if (!found) {
1508 					// Use Product Code as Name
1509 					strcpyxml(displayname, productid, sizeof(displayname));
1510 				}
1511 
1512 				// Output Game Tag + Game Name
1513 				fprintf(log, "\t<game name=\"%s\" usercount=\"%u\">\n", displayname, game->playercount);
1514 
1515 				// Activate User Count
1516 				uint32_t activecount = 0;
1517 
1518 				// Iterate Game Groups
1519 				SceNetAdhocctlGroupNode * group = game->group; for(; group != NULL; group = group->next)
1520 				{
1521 					// Safe Group Name
1522 					char groupname[ADHOCCTL_GROUPNAME_LEN + 1];
1523 					strncpy(groupname, (const char *)group->group.data, ADHOCCTL_GROUPNAME_LEN);
1524 					groupname[ADHOCCTL_GROUPNAME_LEN] = 0;
1525 
1526 					// Output Group Tag + Group Name + User Count
1527 					fprintf(log, "\t\t<group name=\"%s\" usercount=\"%u\">\n", strcpyxml(displayname, groupname, sizeof(displayname)), group->playercount);
1528 
1529 					// Iterate Users
1530 					SceNetAdhocctlUserNode * user = group->player; for(; user != NULL; user = user->group_next)
1531 					{
1532 						// Output User Tag + Username
1533 						fprintf(log, "\t\t\t<user>%s</user>\n", strcpyxml(displayname, (const char *)user->resolver.name.data, sizeof(displayname)));
1534 					}
1535 
1536 					// Output Closing Group Tag
1537 					fprintf(log, "\t\t</group>\n");
1538 
1539 					// Increase Active Game User Count
1540 					activecount += group->playercount;
1541 				}
1542 
1543 				// Output Idle Game Group
1544 				if(game->playercount > activecount)
1545 				{
1546 					// Output Group Tag + Group Name + Idle User Count
1547 					fprintf(log, "\t\t<group name=\"Groupless\" usercount=\"%u\" />\n", game->playercount - activecount);
1548 				}
1549 
1550 				// Output Closing Game Tag
1551 				fprintf(log, "\t</game>\n");
1552 			}
1553 
1554 			// Close Database
1555 			//sqlite3_close(db);
1556 		}
1557 
1558 		// Output Closing Root Tag
1559 		fprintf(log, "</prometheus>");
1560 
1561 		// Close Logfile
1562 		fclose(log);
1563 	}
1564 }
1565 
1566 /**
1567  * Escape XML Sequences to avoid malformed XML files.
1568  * @param out Out Buffer
1569  * @param in In Buffer
1570  * @param size Size of Out Buffer
1571  * @return Reference to Out Buffer
1572  */
strcpyxml(char * out,const char * in,uint32_t size)1573 const char * strcpyxml(char * out, const char * in, uint32_t size)
1574 {
1575 	// Valid Arguments
1576 	if(out != NULL && in != NULL && size > 0)
1577 	{
1578 		// Clear Memory
1579 		memset(out, 0, size);
1580 
1581 		// Written Size Pointer
1582 		uint32_t written = 0;
1583 
1584 		// Iterate In-Buffer Symbols
1585 		uint32_t i = 0; for(; i < strlen(in); i++)
1586 		{
1587 			// " Symbol
1588 			if(in[i] == '"')
1589 			{
1590 				// Enough Space in Out-Buffer (6B for &quot;)
1591 				if((size - written) > 6)
1592 				{
1593 					// Write Escaped Sequence
1594 					strcpy(out + written, "&quot;");
1595 
1596 					// Move Pointer
1597 					written += 6;
1598 				}
1599 
1600 				// Truncate required
1601 				else break;
1602 			}
1603 
1604 			// < Symbol
1605 			else if(in[i] == '<')
1606 			{
1607 				// Enough Space in Out-Buffer (4B for &lt;)
1608 				if((size - written) > 4)
1609 				{
1610 					// Write Escaped Sequence
1611 					strcpy(out + written, "&lt;");
1612 
1613 					// Move Pointer
1614 					written += 4;
1615 				}
1616 
1617 				// Truncate required
1618 				else break;
1619 			}
1620 
1621 			// > Symbol
1622 			else if(in[i] == '>')
1623 			{
1624 				// Enough Space in Out-Buffer (4B for &gt;)
1625 				if((size - written) > 4)
1626 				{
1627 					// Write Escaped Sequence
1628 					strcpy(out + written, "&gt;");
1629 
1630 					// Move Pointer
1631 					written += 4;
1632 				}
1633 
1634 				// Truncate required
1635 				else break;
1636 			}
1637 
1638 			// & Symbol
1639 			else if(in[i] == '&')
1640 			{
1641 				// Enough Space in Out-Buffer (5B for &amp;)
1642 				if((size - written) > 5)
1643 				{
1644 					// Write Escaped Sequence
1645 					strcpy(out + written, "&amp;");
1646 
1647 					// Move Pointer
1648 					written += 5;
1649 				}
1650 
1651 				// Truncate required
1652 				else break;
1653 			}
1654 
1655 			// Normal Character
1656 			else
1657 			{
1658 				// Enough Space in Out-Buffer (1B)
1659 				if((size - written) > 1)
1660 				{
1661 					// Write Character
1662 					out[written++] = in[i];
1663 				}
1664 			}
1665 		}
1666 
1667 		// Return Reference
1668 		return out;
1669 	}
1670 
1671 	// Invalid Arguments
1672 	return NULL;
1673 }
1674 
1675 /**
1676  * Server Entry Point
1677  * @param argc Number of Arguments
1678  * @param argv Arguments
1679  * @return OS Error Code
1680  */
proAdhocServerThread(int port)1681 int proAdhocServerThread(int port) // (int argc, char * argv[])
1682 {
1683 	SetCurrentThreadName("AdhocServer");
1684 	// Result
1685 	int result = 0;
1686 
1687 	INFO_LOG(SCENET, "AdhocServer: Begin of AdhocServer Thread");
1688 
1689 	// Create Signal Receiver for CTRL + C
1690 	//signal(SIGINT, interrupt);
1691 
1692 	// Create Signal Receiver for kill / killall
1693 	//signal(SIGTERM, interrupt);
1694 
1695 	// Create Listening Socket
1696 	int server = create_listen_socket(port); //SERVER_PORT
1697 
1698 	// Created Listening Socket
1699 	if(server != SOCKET_ERROR)
1700 	{
1701 		// Notify User
1702 		INFO_LOG(SCENET, "AdhocServer: Listening for Connections on TCP Port %u", port); //SERVER_PORT
1703 
1704 		// Port forward
1705 		UPnP_Add(IP_PROTOCOL_TCP, port); // g_PortManager.Add(IP_PROTOCOL_TCP, port);
1706 
1707 		// Enter Server Loop
1708 		result = server_loop(server);
1709 
1710 		// Remove Port mapping
1711 		UPnP_Remove(IP_PROTOCOL_TCP, port); // g_PortManager.Remove(IP_PROTOCOL_TCP, port);
1712 
1713 		// Notify User
1714 		INFO_LOG(SCENET, "AdhocServer: Shutdown complete");
1715 	}
1716 
1717 	//_status = 0;
1718 	adhocServerRunning = false;
1719 
1720 	INFO_LOG(SCENET, "AdhocServer: End of AdhocServer Thread");
1721 
1722 	// Return Result
1723 	return result;
1724 }
1725 
1726 /**
1727  * Server Shutdown Request Handler
1728  * @param sig Captured Signal
1729  */
interrupt(int sig)1730 void interrupt(int sig)
1731 {
1732 	// Notify User
1733 	INFO_LOG(SCENET, "AdhocServer: Shutting down... please wait");
1734 
1735 	// Trigger Shutdown
1736 	//_status = 0;
1737 	adhocServerRunning = false;
1738 }
1739 
1740 /**
1741  * Enable Address Reuse on Socket
1742  * @param fd Socket
1743  */
enable_address_reuse(int fd)1744 void enable_address_reuse(int fd)
1745 {
1746 	// Enable Port Reuse
1747 	setSockReuseAddrPort(fd);
1748 }
1749 
1750 /**
1751  * Enable KeepAlive on Socket
1752  * @param fd Socket
1753  */
enable_keepalive(int fd)1754 void enable_keepalive(int fd)
1755 {
1756 	// Enable Value
1757 	int on = 1;
1758 
1759 	// Enable Port Reuse
1760 	setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char*)&on, sizeof(on));
1761 }
1762 
1763 /**
1764  * Change TCP Socket TCP_NODELAY (Nagle Algo) mode
1765  * @param fd Socket
1766  * @param nonblocking 1 for Nonblocking, 0 for Blocking
1767  */
change_nodelay_mode(int fd,int flag)1768 void change_nodelay_mode(int fd, int flag)
1769 {
1770 	int opt = flag;
1771 	setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt));
1772 }
1773 
1774 /**
1775  * Change Socket Blocking Mode
1776  * @param fd Socket
1777  * @param nonblocking 1 for Nonblocking, 0 for Blocking
1778  */
change_blocking_mode(int fd,int nonblocking)1779 void change_blocking_mode(int fd, int nonblocking)
1780 {
1781 	unsigned long on = 1;
1782 	unsigned long off = 0;
1783 #ifdef _WIN32
1784 	if (nonblocking){
1785 		// Change to Non-Blocking Mode
1786 		ioctlsocket(fd, FIONBIO, &on);
1787 	}
1788 	else {
1789 		// Change to Blocking Mode
1790 		ioctlsocket(fd, FIONBIO, &off);
1791 	}
1792 #else
1793 	// Change to Non-Blocking Mode
1794 	if(nonblocking) fcntl(fd, F_SETFL, O_NONBLOCK);
1795 
1796 	// Change to Blocking Mode
1797 	else
1798 	{
1799 		// Get Flags
1800 		int flags = fcntl(fd, F_GETFL);
1801 
1802 		// Remove Non-Blocking Flag
1803 		fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
1804 	}
1805 #endif
1806 }
1807 
1808 /**
1809  * Create Port-Bound Listening Socket
1810  * @param port TCP Port
1811  * @return Socket Descriptor
1812  */
create_listen_socket(uint16_t port)1813 int create_listen_socket(uint16_t port)
1814 {
1815 	// Create Socket
1816 	int fd = (int)socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1817 
1818 	// Created Socket
1819 	if(fd != -1)
1820 	{
1821 		// Ignore SIGPIPE when supported (ie. BSD/MacOS)
1822 		setSockNoSIGPIPE(fd, 1);
1823 
1824 		// Enable KeepAlive
1825 		enable_keepalive(fd);
1826 
1827 		// Enable Address Reuse
1828 		enable_address_reuse(fd); // Shouldn't Reuse the port for built-in AdhocServer to prevent conflict with Dedicated AdhocServer
1829 
1830 		// Make Socket Nonblocking
1831 		change_blocking_mode(fd, 1);
1832 
1833 		// Make TCP Socket send immediately
1834 		change_nodelay_mode(fd, 1);
1835 
1836 		// Prepare Local Address Information
1837 		struct sockaddr_in local;
1838 		memset(&local, 0, sizeof(local));
1839 		local.sin_family = AF_INET;
1840 		local.sin_addr.s_addr = INADDR_ANY;
1841 		local.sin_port = htons(port);
1842 
1843 		// Should only bind to specific IP for the 2nd or more instance of PPSSPP to prevent communication interference issue when sharing the same port. (ie. Capcom Classics Collection Remixed)
1844 		if (PPSSPP_ID > 1) {
1845 			local.sin_addr = g_localhostIP.in.sin_addr;
1846 		}
1847 
1848 		// Bind Local Address to Socket
1849 		int bindresult = bind(fd, (struct sockaddr *)&local, sizeof(local));
1850 
1851 		// Bound Local Address to Socket
1852 		if(bindresult != SOCKET_ERROR)
1853 		{
1854 			// Switch Socket into Listening Mode
1855 			listen(fd, SERVER_LISTEN_BACKLOG);
1856 
1857 			// Return Socket
1858 			return fd;
1859 		}
1860 
1861 		// Notify User
1862 		else {
1863 			ERROR_LOG(SCENET, "AdhocServer: Bind returned %i (Socket error %d)", bindresult, errno);
1864 			auto n = GetI18NCategory("Networking");
1865 			host->NotifyUserMessage(std::string(n->T("AdhocServer Failed to Bind Port")) + " " + std::to_string(port), 3.0, 0x0000ff);
1866 		}
1867 
1868 		// Close Socket
1869 		closesocket(fd);
1870 	}
1871 
1872 	// Notify User
1873 	else ERROR_LOG(SCENET, "AdhocServer: Socket returned %i (Socket error %d)", fd, errno);
1874 
1875 	// Return Error
1876 	return -1;
1877 }
1878 
1879 /**
1880  * Server Main Loop
1881  * @param server Server Listening Socket
1882  * @return OS Error Code
1883  */
server_loop(int server)1884 int server_loop(int server)
1885 {
1886 	// Set Running Status
1887 	//_status = 1;
1888 	adhocServerRunning = true;
1889 
1890 	// Create Empty Status Logfile
1891 	update_status();
1892 
1893 	// Handling Loop
1894 	while (adhocServerRunning) //(_status == 1)
1895 	{
1896 		// Login Block
1897 		{
1898 			// Login Result
1899 			int loginresult = 0;
1900 
1901 			// Login Processing Loop
1902 			do
1903 			{
1904 				// Prepare Address Structure
1905 				struct sockaddr_in addr;
1906 				socklen_t addrlen = sizeof(addr);
1907 				memset(&addr, 0, sizeof(addr));
1908 
1909 				// Accept Login Requests
1910 				// loginresult = accept4(server, (struct sockaddr *)&addr, &addrlen, SOCK_NONBLOCK);
1911 
1912 				// Alternative Accept Approach (some Linux Kernel don't support the accept4 Syscall... wtf?)
1913 				loginresult = accept(server, (struct sockaddr *)&addr, &addrlen);
1914 				if(loginresult != -1)
1915 				{
1916 					// Switch Socket into Non-Blocking Mode
1917 					change_blocking_mode(loginresult, 1);
1918 				}
1919 
1920 				// Login User (Stream)
1921 				if (loginresult != -1) {
1922 					u32_le sip = addr.sin_addr.s_addr;
1923 					/* // Replacing 127.0.0.x with Ethernet IP will cause issue with multiple-instance of localhost (127.0.0.x)
1924 					if (sip == 0x0100007f) { //127.0.0.1 should be replaced with LAN/WAN IP whenever available
1925 						char str[100];
1926 						gethostname(str, 100);
1927 						u8 *pip = (u8*)&sip;
1928 						if (gethostbyname(str)->h_addrtype == AF_INET && gethostbyname(str)->h_addr_list[0] != NULL) pip = (u8*)gethostbyname(str)->h_addr_list[0];
1929 						sip = *(u32_le*)pip;
1930 						WARN_LOG(SCENET, "AdhocServer: Replacing IP %s with %s", inet_ntoa(addr.sin_addr), inet_ntoa(*(in_addr*)&pip));
1931 					}
1932 					*/
1933 					login_user_stream(loginresult, sip);
1934 				}
1935 			} while(loginresult != -1);
1936 		}
1937 
1938 		// Receive Data from Users
1939 		SceNetAdhocctlUserNode * user = _db_user;
1940 		while(user != NULL)
1941 		{
1942 			// Next User (for safe delete)
1943 			SceNetAdhocctlUserNode * next = user->next;
1944 
1945 			// Receive Data from User
1946 			int recvresult = recv(user->stream, (char*)user->rx + user->rxpos, sizeof(user->rx) - user->rxpos, MSG_NOSIGNAL);
1947 
1948 			// Connection Closed or Timed Out
1949 			if(recvresult == 0 || (recvresult == -1 && errno != EAGAIN && errno != EWOULDBLOCK) || get_user_state(user) == USER_STATE_TIMED_OUT)
1950 			{
1951 				// Logout User
1952 				logout_user(user);
1953 			}
1954 
1955 			// Received Data (or leftovers in RX-Buffer)
1956 			else if(recvresult > 0 || user->rxpos > 0)
1957 			{
1958 				// New Incoming Data
1959 				if(recvresult > 0)
1960 				{
1961 					// Move RX Pointer
1962 					user->rxpos += recvresult;
1963 
1964 					// Update Death Clock
1965 					user->last_recv = time(NULL);
1966 				}
1967 
1968 				// Waiting for Login Packet
1969 				if(get_user_state(user) == USER_STATE_WAITING)
1970 				{
1971 					// Valid Opcode
1972 					if(user->rx[0] == OPCODE_LOGIN)
1973 					{
1974 						// Enough Data available
1975 						if(user->rxpos >= sizeof(SceNetAdhocctlLoginPacketC2S))
1976 						{
1977 							// Clone Packet
1978 							SceNetAdhocctlLoginPacketC2S packet = *(SceNetAdhocctlLoginPacketC2S *)user->rx;
1979 
1980 							// Remove Packet from RX Buffer
1981 							clear_user_rxbuf(user, sizeof(SceNetAdhocctlLoginPacketC2S));
1982 
1983 							// Login User (Data)
1984 							login_user_data(user, &packet);
1985 						}
1986 					}
1987 
1988 					// Invalid Opcode
1989 					else
1990 					{
1991 						// Notify User
1992 						WARN_LOG(SCENET, "AdhocServer: Invalid Opcode 0x%02X in Waiting State from %s", user->rx[0], ip2str(*(in_addr*)&user->resolver.ip).c_str());
1993 
1994 						// Logout User
1995 						logout_user(user);
1996 					}
1997 				}
1998 
1999 				// Logged-In User
2000 				else if(get_user_state(user) == USER_STATE_LOGGED_IN)
2001 				{
2002 					// Ping Packet
2003 					if(user->rx[0] == OPCODE_PING)
2004 					{
2005 						// Delete Packet from RX Buffer
2006 						clear_user_rxbuf(user, 1);
2007 					}
2008 
2009 					// Group Connect Packet
2010 					else if(user->rx[0] == OPCODE_CONNECT)
2011 					{
2012 						// Enough Data available
2013 						if(user->rxpos >= sizeof(SceNetAdhocctlConnectPacketC2S))
2014 						{
2015 							// Cast Packet
2016 							SceNetAdhocctlConnectPacketC2S * packet = (SceNetAdhocctlConnectPacketC2S *)user->rx;
2017 
2018 							// Clone Group Name
2019 							SceNetAdhocctlGroupName group = packet->group;
2020 
2021 							// Remove Packet from RX Buffer
2022 							clear_user_rxbuf(user, sizeof(SceNetAdhocctlConnectPacketC2S));
2023 
2024 							// Change Game Group
2025 							connect_user(user, &group);
2026 						}
2027 					}
2028 
2029 					// Group Disconnect Packet
2030 					else if(user->rx[0] == OPCODE_DISCONNECT)
2031 					{
2032 						// Remove Packet from RX Buffer
2033 						clear_user_rxbuf(user, 1);
2034 
2035 						// Leave Game Group
2036 						disconnect_user(user);
2037 					}
2038 
2039 					// Network Scan Packet
2040 					else if(user->rx[0] == OPCODE_SCAN)
2041 					{
2042 						// Remove Packet from RX Buffer
2043 						clear_user_rxbuf(user, 1);
2044 
2045 						// Send Network List
2046 						send_scan_results(user);
2047 					}
2048 
2049 					// Chat Text Packet
2050 					else if(user->rx[0] == OPCODE_CHAT)
2051 					{
2052 						// Enough Data available
2053 						if(user->rxpos >= sizeof(SceNetAdhocctlChatPacketC2S))
2054 						{
2055 							// Cast Packet
2056 							SceNetAdhocctlChatPacketC2S * packet = (SceNetAdhocctlChatPacketC2S *)user->rx;
2057 
2058 							// Clone Buffer for Message
2059 							char message[64];
2060 							memset(message, 0, sizeof(message));
2061 							strncpy(message, packet->message, sizeof(message) - 1);
2062 
2063 							// Remove Packet from RX Buffer
2064 							clear_user_rxbuf(user, sizeof(SceNetAdhocctlChatPacketC2S));
2065 
2066 							// Spread Chat Message
2067 							spread_message(user, message);
2068 						}
2069 					}
2070 
2071 					// Invalid Opcode
2072 					else
2073 					{
2074 						// Notify User
2075 						WARN_LOG(SCENET, "AdhocServer: Invalid Opcode 0x%02X in Logged-In State from %s (MAC: %s - IP: %s)", user->rx[0], (char *)user->resolver.name.data, mac2str(&user->resolver.mac).c_str(), ip2str(*(in_addr*)&user->resolver.ip).c_str());
2076 
2077 						// Logout User
2078 						logout_user(user);
2079 					}
2080 				}
2081 			}
2082 
2083 			// Move Pointer
2084 			user = next;
2085 		}
2086 
2087 		// Prevent needless CPU Overload (1ms Sleep)
2088 		sleep_ms(10);
2089 
2090 		// Don't do anything if it's paused, otherwise the log will be flooded
2091 		while (adhocServerRunning && Core_IsStepping() && coreState != CORE_POWERDOWN) sleep_ms(10);
2092 	}
2093 
2094 	// Free User Database Memory
2095 	free_database();
2096 
2097 	// Close Server Socket
2098 	closesocket(server);
2099 
2100 	// Return Success
2101 	return 0;
2102 }
2103