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