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