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 ")
1591 if((size - written) > 6)
1592 {
1593 // Write Escaped Sequence
1594 strcpy(out + written, """);
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 <)
1608 if((size - written) > 4)
1609 {
1610 // Write Escaped Sequence
1611 strcpy(out + written, "<");
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 >)
1625 if((size - written) > 4)
1626 {
1627 // Write Escaped Sequence
1628 strcpy(out + written, ">");
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 &)
1642 if((size - written) > 5)
1643 {
1644 // Write Escaped Sequence
1645 strcpy(out + written, "&");
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