OpenMoHAA 0.82.0
Loading...
Searching...
No Matches
gsPlatformUtil.c
1
3#include "gsCommon.h"
4#include "gsPlatformUtil.h"
5
6// Include platform separated functions
7#if defined(_X360)
8 //#include "x360/gsUtilX360.c"
9#elif defined(_XBOX)
10 //#include "xbox/gsUtilXBox.c"
11#elif defined(_WIN32)
12 #include "win32/gsUtilWin32.c"
13#elif defined(_LINUX)
14 #include "linux/gsUtilLinux.c"
15#elif defined(_MACOSX)
16 #include "macosx/gsUtilMacOSX.c"
17#elif defined(_NITRO)
18 #include "nitro/gsUtilNitro.c"
19#elif defined(_PS2)
20 #include "ps2/gsUtilPs2.c"
21#elif defined(_PS3)
22 #include "ps3/gsUtilPs3.c"
23#elif defined(_PSP)
24 #include "psp/gsUtilPSP.c"
25#elif defined(_REVOLUTION)
26 #include "revolution/gsUtilRevolution.c"
27#else
28 #error "Missing or unsupported platform"
29#endif
30
31#if defined(__cplusplus)
32extern "C" {
33#endif
34
35
36
39// ********** ASYNC DNS ********** //
40
41//struct is used in both threaded and non-threaded versions
43{
44 char * hostname;
45 unsigned int ip;
46
47#if defined(_WIN32) /*|| defined(_PS2)*/ || defined(_UNIX) || defined (_REVOLUTION)
48 int finishedResolving;
49 GSIThreadID threadID;
50#endif
51
52/*#if defined(_PSP)
53 int finishedResolving;
54 GSIThreadID threadID;
55#endif*/
57
59// for asynch DNS, must have:
60// * platform that supports threaded lookup AND
61// * threading enabled
62// * and async lookup enabled
64#if (defined(_WIN32) || /*defined(_PS2) ||*/ defined(_UNIX) || defined (_REVOLUTION)) && !defined(GSI_NO_THREADS) && !defined(GSI_NO_ASYNC_DNS)
65
67#if defined(_WIN32) /*|| defined(_PS2)*/
68 #if defined(_WIN32)
69 DWORD WINAPI gsiResolveHostnameThread(void * arg)
70 /*#elif defined(_PS2)
71 static void gsiResolveHostnameThread(void * arg)*/
72 #endif
73 {
74 HOSTENT * hostent;
75 GSIResolveHostnameHandle handle = (GSIResolveHostnameHandle)arg;
76
77 SocketStartUp();
78
79 #ifdef SN_SYSTEMS
80 sockAPIregthr();
81 #endif
82
83 // do the gethostbyname
84 hostent = gethostbyname(handle->hostname);
85 if(hostent)
86 {
87 // got the ip
88 handle->ip = *(unsigned int *)hostent->h_addr_list[0];
89 }
90 else
91 {
92 // didn't resolve
93 handle->ip = GSI_ERROR_RESOLVING_HOSTNAME;
94 }
95
96 SocketShutDown();
97
98 // finished resolving
99 handle->finishedResolving = 1;
100
101 #ifdef SN_SYSTEMS
102 sockAPIderegthr();
103 #endif
104
105 // explicitly exit the thread to free resources
106 gsiExitThread(handle->threadID);
107
108 #if defined(_WIN32)
109 return 0;
110 #endif
111}
112#endif //defined _WIN32
114
115
116#ifdef _REVOLUTION
118static void *gsiResolveHostnameThread(void * arg)
119{
120 static GSICriticalSection aHostnameCrit;
121 static int aInitialized = 0;
122 //SOAddrInfo *aHostAddr;
123 HOSTENT *aHostAddr;
124 //int retval;
125 GSIResolveHostnameHandle handle = (GSIResolveHostnameHandle)arg;
126
127 if (!aInitialized)
128 {
129 gsiInitializeCriticalSection(&aHostnameCrit);
130 aInitialized = 1;
131 }
132 gsiEnterCriticalSection(&aHostnameCrit);
133
134 //retval = getaddrinfo(handle->hostname, NULL, NULL, &aHostAddr);
135 aHostAddr = gethostbyname(handle->hostname);
136 if (aHostAddr != 0)
137 {
138 char * ip;
139 // first convert to character string for debug output
140 ip = inet_ntoa(*(in_addr *)aHostAddr->addrList[0]);
141
142 gsDebugFormat(GSIDebugCat_HTTP, GSIDebugType_State, GSIDebugLevel_Comment,
143 "Resolved host '%s' to ip '%s'\n", handle->hostname, ip);
144
145 handle->ip = inet_addr(ip);
146 //freeaddrinfo(aHostAddr);
147 }
148 else
149 {
150 // couldnt reach host - debug output is printed later
151 handle->ip = GSI_ERROR_RESOLVING_HOSTNAME;
152 }
153
154
155 // finished resolving
156 handle->finishedResolving = 1;
157
158 gsiLeaveCriticalSection(&aHostnameCrit);
159}
160#endif // _REVOLUTION
162
163//
164// Linux/MacOSX implementation of multithreaded DNS lookup
165// Uses getaddrinfo instead of gethostbyname - since the latter
166// has static declarations and is thus un-safe for pthreads
167//
168// NOTE: The compiler option "-lpthread" must used for this
169#if defined(_UNIX)
171static void gsiResolveHostnameThread(void * arg)
172{
173 GSIResolveHostnameHandle handle = (GSIResolveHostnameHandle)arg;
174 struct addrinfo hints, *result = NULL;
175 int error;
176 char *ip;
177
178 SocketStartUp();
179
180 memset(&hints, 0, sizeof(hints));
181 hints.ai_family = PF_UNSPEC;
182 hints.ai_socktype = SOCK_STREAM;
183
184 // DNS lookup (works with pthreads)
185 error = getaddrinfo(handle->hostname, "http", &hints, &result);
186
187 if (!error)
188 {
189 // first convert to character string for debug output
190 ip = inet_ntoa((*(struct sockaddr_in*)result->ai_addr).sin_addr);
191
192 gsDebugFormat(GSIDebugCat_HTTP, GSIDebugType_State, GSIDebugLevel_Comment,
193 "Resolved host '%s' to ip '%s'\n", handle->hostname, ip);
194
195 // now convert to unsigned int and store it
196 handle->ip = inet_addr(ip);
197
198 // free the memory used
199 freeaddrinfo(result);
200 }
201 else
202 {
203 // couldnt reach host - debug output is printed later
204 handle->ip = GSI_ERROR_RESOLVING_HOSTNAME;
205 }
206
207 SocketShutDown();
208
209 // finished resolving
210 handle->finishedResolving = 1;
211
212 // explicitly exit the thread to free resources
213 gsiExitThread(handle->threadID);
214}
215#endif //_UNIX
217
218
219int gsiStartResolvingHostname(const char * hostname, GSIResolveHostnameHandle * handle)
220{
222
223 //PS2 Threading unsupported in current build - this should never be reached
224#if defined(_PS2)
225 GS_ASSERT_STR(gsi_false, "PS2 Threading unsupported in current version of the SDK\n");
226#endif
227
228 // allocate a handle
229 info = (GSIResolveHostnameInfo *)gsimalloc(sizeof(GSIResolveHostnameInfo));
230 if(!info)
231 return -1;
232
233 // make a copy of the hostname so the thread has access to it
234 info->hostname = goastrdup(hostname);
235 if(!info->hostname)
236 {
237 gsifree(info);
238 return -1;
239 }
240
241 // not resolved yet
242 info->finishedResolving = 0;
243
244 gsDebugFormat(GSIDebugCat_Common, GSIDebugType_State, GSIDebugLevel_Comment,
245 "(Asynchrounous) DNS lookup starting\n");
246
247 // start the thread
248 if(gsiStartThread(gsiResolveHostnameThread, (0x1000), info, &info->threadID) == -1)
249 {
250 gsifree(info->hostname);
251 info->hostname = NULL;
252 gsifree(info);
253 info = NULL;
254 return -1;
255 }
256
257 // set the handle to the info
258 *handle = info;
259
260 return 0;
261}
262
263void gsiCancelResolvingHostname(GSIResolveHostnameHandle handle)
264{
265 // cancel the thread
266 gsiCancelThread(handle->threadID);
267
268 if (handle->hostname)
269 {
270 gsifree(handle->hostname);
271 handle->hostname = NULL;
272 }
273 gsifree(handle);
274 handle = NULL;
275}
276
277unsigned int gsiGetResolvedIP(GSIResolveHostnameHandle handle)
278{
279 unsigned int ip;
280
281 // check if we haven't finished
282 if(!handle->finishedResolving)
283 return GSI_STILL_RESOLVING_HOSTNAME;
284
285 // save the ip
286 ip = handle->ip;
287
288 // free resources
289 gsiCleanupThread(handle->threadID);
290 gsifree(handle->hostname);
291 gsifree(handle);
292 handle = NULL;
293
294 return ip;
295}
296
297
298#else // if * not a supported platform OR * no threads allowed OR * no async lookup allowed
300 // if !(_WIN32 ||_PS2 || _LINUX || _MACOSX || _REVOLUTION) || GSI_NO_THREADS || GSI_NO_ASYNC_DNS
301
302
305// ********** NON-ASYNC DNS ********** //
306//
307// These are the non-threaded version of the above functions.
308// The following platforms have synchronous DNS lookups:
309// _NITRO || _XBOX || _X360 || _PS3 || _PS2 || _PSP
311
312int gsiStartResolvingHostname(const char * hostname, GSIResolveHostnameHandle * handle)
313{
315 HOSTENT * hostent;
316
317 gsDebugFormat(GSIDebugCat_HTTP, GSIDebugType_State, GSIDebugLevel_Comment,
318 "(NON-Asynchrounous) DNS lookup starting\n");
319
320 // do the lookup now
321 hostent = gethostbyname(hostname);
322 if(hostent == NULL)
323 return -1;
324
325 // allocate info to store the result
326 info = (GSIResolveHostnameHandle)gsimalloc(sizeof(GSIResolveHostnameInfo));
327 if(!info)
328 return -1;
329
330 // we already have the ip
331 info->ip = *(unsigned int *)hostent->h_addr_list[0];
332
333 // set the handle to the info
334 *handle = info;
335
336 return 0;
337}
338
339void gsiCancelResolvingHostname(GSIResolveHostnameHandle handle)
340{
341 gsifree(handle);
342 handle = NULL;
343}
344
345unsigned int gsiGetResolvedIP(GSIResolveHostnameHandle handle)
346{
347 // we always do the resolve in the initial call for systems without
348 // an async version, so we'll always have the IP at this point
349 unsigned int ip = handle->ip;
350 gsifree(handle);
351 handle = NULL;
352 return ip;
353}
354
356#endif // synch DNS lookup
357
358
361char * goastrdup(const char *src)
362{
363 char *res;
364 if(src == NULL) //PANTS|02.11.00|check for NULL before strlen
365 return NULL;
366 res = (char *)gsimalloc(strlen(src) + 1);
367 if(res != NULL) //PANTS|02.02.00|check for NULL before strcpy
368 strcpy(res, src);
369 return res;
370}
371
372unsigned short * goawstrdup(const unsigned short *src)
373{
374 unsigned short *res;
375 if(src == NULL)
376 return NULL;
377 res = (unsigned short *)gsimalloc((wcslen((wchar_t*)src) + 1) * sizeof(unsigned short));
378 if(res != NULL)
379 wcscpy((wchar_t*)res, (const wchar_t*)src);
380 return res;
381}
382
383#if !defined(_WIN32)
384
385char *_strlwr(char *string)
386{
387 char *hold = string;
388 while (*string)
389 {
390 *string = (char)tolower(*string);
391 string++;
392 }
393
394 return hold;
395}
396
397char *_strupr(char *string)
398{
399 char *hold = string;
400 while (*string)
401 {
402 *string = (char)toupper(*string);
403 string++;
404 }
405
406 return hold;
407}
408#endif
409
410
413void SocketStartUp()
414{
415#if defined(_WIN32)
416 WSADATA data;
417
418 #if defined(_X360)
419 XNetStartupParams xnsp;
420 memset(&xnsp,0,sizeof(xnsp));
421 xnsp.cfgSizeOfStruct=sizeof(xnsp);
422 xnsp.cfgFlags=XNET_STARTUP_BYPASS_SECURITY;
423 if(0 != XNetStartup(&xnsp))
424 {
425 OutputDebugString("XNetStartup failed\n");
426 }
427 #endif
428
429 // added support for winsock2
430 #if (!defined(_XBOX) || defined(_X360)) && (defined(GSI_WINSOCK2) || defined(_X360))
431 WSAStartup(MAKEWORD(2,2), &data);
432 #else
433 WSAStartup(MAKEWORD(1,1), &data);
434 #endif
435 // end added
436#endif
437}
438
439void SocketShutDown()
440{
441#if defined(_WIN32)
442 WSACleanup();
443 #if defined(_X360)
444 XNetCleanup();
445 #endif
446#endif
447}
448
449
452#ifdef _PS2
453extern int sceCdReadClock();
454
455#if !defined(__MWERKS__) && !defined(_PS2)
456typedef unsigned char u_char;
457#endif
458
459typedef struct {
460 u_char stat; /* status */
461 u_char second; /* second */
462 u_char minute; /* minute */
463 u_char hour; /* hour */
464
465 u_char pad; /* pad */
466 u_char day; /* day */
467 u_char month; /* month */
468 u_char year; /* year */
469} sceCdCLOCK;
470
471static unsigned long GetTicks()
472{
473 unsigned long ticks;
474 asm volatile (" mfc0 %0, $9 " : "=r" (ticks));
475 return ticks;
476}
477
478#define DEC(x) (10*(x/16)+(x%16))
479#define _BASE_YEAR 70L
480#define _MAX_YEAR 138L
481#define _LEAP_YEAR_ADJUST 17L
482int _days[] = {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364};
483
484static time_t _gmtotime_t (
485 int yr, /* 0 based */
486 int mo, /* 1 based */
487 int dy, /* 1 based */
488 int hr,
489 int mn,
490 int sc
491 )
492{
493 int tmpdays;
494 long tmptim;
495 struct tm tb;
496
497 if ( ((long)(yr -= 1900) < _BASE_YEAR) || ((long)yr > _MAX_YEAR) )
498 return (time_t)(-1);
499
500 tmpdays = dy + _days[mo - 1];
501 if ( !(yr & 3) && (mo > 2) )
502 tmpdays++;
503
504 tmptim = (long)yr - _BASE_YEAR;
505
506 tmptim = ( ( ( ( tmptim ) * 365L
507 + ((long)(yr - 1) >> 2) - (long)_LEAP_YEAR_ADJUST
508 + (long)tmpdays )
509 * 24L + (long)hr )
510 * 60L + (long)mn )
511 * 60L + (long)sc;
512
513 tb.tm_yday = tmpdays;
514 tb.tm_year = yr;
515 tb.tm_mon = mo - 1;
516 tb.tm_hour = hr;
517
518 return (tmptim >= 0) ? (time_t)tmptim : (time_t)(-1);
519}
520
521time_t time(time_t *timer)
522{
523 time_t tim;
524 sceCdCLOCK clocktime; /* defined in libcdvd.h */
525
526 sceCdReadClock(&clocktime); /* libcdvd.a */
527
528 tim = _gmtotime_t ( DEC(clocktime.year)+2000,
529 DEC(clocktime.month),
530 DEC(clocktime.day),
531 DEC(clocktime.hour),
532 DEC(clocktime.minute),
533 DEC(clocktime.second));
534
535 if(timer)
536 *timer = tim;
537
538 return tim;
539}
540
541#endif /* _PS2 */
542
543
546gsi_time current_time() //returns current time in milliseconds
547{
548#if defined(_WIN32)
549 return (GetTickCount());
550
551#elif defined(_PS2)
552 unsigned int ticks;
553 static unsigned int msec = 0;
554 static unsigned int lastticks = 0;
555 sceCdCLOCK lasttimecalled; /* defined in libcdvd.h */
556
557 if(!msec)
558 {
559 sceCdReadClock(&lasttimecalled); /* libcdvd.a */
560 msec = (unsigned int)(DEC(lasttimecalled.day) * 86400000) +
561 (unsigned int)(DEC(lasttimecalled.hour) * 3600000) +
562 (unsigned int)(DEC(lasttimecalled.minute) * 60000) +
563 (unsigned int)(DEC(lasttimecalled.second) * 1000);
564 }
565
566 ticks = (unsigned int)GetTicks();
567 if(lastticks > ticks)
568 msec += (unsigned int)(((unsigned int)(-1) - lastticks) + ticks) / 300000;
569 else
570 msec += (unsigned int)(ticks-lastticks) / 300000;
571 lastticks = ticks;
572
573 return msec;
574
575#elif defined(_UNIX)
576 struct timeval time;
577
578 gettimeofday(&time, NULL);
579 return (time.tv_sec * 1000 + time.tv_usec / 1000);
580
581#elif defined(_NITRO)
582 assert(OS_IsTickAvailable() == TRUE);
583 return (gsi_time)OS_TicksToMilliSeconds(OS_GetTick());
584
585#elif defined(_PSP)
586 struct SceRtcTick ticks;
587 int result = 0;
588
589 result = sceRtcGetCurrentTick(&ticks);
590 if (result < 0)
591 {
592 ScePspDateTime time;
593 result = sceRtcGetCurrentClock(&time, 0);
594 if (result < 0)
595 return 0; // um...error handling? //Nope, should return zero since time cannot be zero
596 result = sceRtcGetTick(&time, &ticks);
597 if (result < 0)
598 return 0; //Nope, should return zero since time cannot be zero
599 }
600
601 return (gsi_time)(ticks.tick / 1000);
602
603#elif defined(_PS3)
604 return (gsi_time)(sys_time_get_system_time()/1000);
605
606#elif defined(_REVOLUTION)
607 OSTick aTickNow= OSGetTick();
608 gsi_time aMilliseconds = (gsi_time)OSTicksToMilliseconds(aTickNow);
609 return aMilliseconds;
610#else
611 // unrecognized platform! contact devsupport
612 assert(0);
613#endif
614
615}
616
617gsi_time current_time_hires() // returns current time in microseconds
618{
619#ifdef _WIN32
620#if (!defined(_M_IX86) || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64))
621 static LARGE_INTEGER counterFrequency;
622 static BOOL haveCounterFrequency = FALSE;
623 static BOOL haveCounter = FALSE;
624 LARGE_INTEGER count;
625
626 if(!haveCounterFrequency)
627 {
628 haveCounter = QueryPerformanceFrequency(&counterFrequency);
629 haveCounterFrequency = TRUE;
630 }
631
632 if(haveCounter)
633 {
634 if(QueryPerformanceCounter(&count))
635 {
636 return (gsi_time)(count.QuadPart * 1000000 / counterFrequency.QuadPart);
637 }
638 }
639#endif
640
641 return (current_time() / 1000);
642#endif
643
644#ifdef _PS2
645 unsigned int ticks;
646 static unsigned int msec = 0;
647 static unsigned int lastticks = 0;
648 sceCdCLOCK lasttimecalled; /* defined in libcdvd.h */
649
650 if(!msec)
651 {
652 sceCdReadClock(&lasttimecalled); /* libcdvd.a */
653 msec = (unsigned int)(DEC(lasttimecalled.day) * 86400000) +
654 (unsigned int)(DEC(lasttimecalled.hour) * 3600000) +
655 (unsigned int)(DEC(lasttimecalled.minute) * 60000) +
656 (unsigned int)(DEC(lasttimecalled.second) * 1000);
657 msec *= 1000;
658 }
659
660 ticks = (unsigned int)GetTicks();
661 if(lastticks > ticks)
662 msec += ((sizeof(unsigned int) - lastticks) + ticks) / 300;
663 else
664 msec += (unsigned int)(ticks-lastticks) / 300;
665 lastticks = ticks;
666
667 return msec;
668#endif
669
670#ifdef _PSP
671 struct SceRtcTick ticks;
672 int result = 0;
673
674 result = sceRtcGetCurrentTick(&ticks);
675 if (result < 0)
676 {
677 ScePspDateTime time;
678 result = sceRtcGetCurrentClock(&time, 0);
679 if (result < 0)
680 return 0; // um...error handling? //Nope, should return zero since time cannot be zero
681 result = sceRtcGetTick(&time, &ticks);
682 if (result < 0)
683 return 0; //Nope, should return zero since time cannot be zero
684 }
685
686 return (gsi_time)(ticks.tick);
687#endif
688
689#ifdef _UNIX
690 struct timeval time;
691
692 gettimeofday(&time, NULL);
693 return (time.tv_sec * 1000000 + time.tv_usec);
694#endif
695
696#ifdef _NITRO
697 assert(OS_IsTickAvailable() == TRUE);
698 return (gsi_time)OS_TicksToMicroSeconds(OS_GetTick());
699#endif
700
701#ifdef _PS3
702 return (gsi_time)sys_time_get_system_time();
703#endif
704}
705
706
707void msleep(gsi_time msec)
708{
709#if defined(_WIN32)
710 Sleep(msec);
711
712#elif defined(_PS2)
713 #ifdef SN_SYSTEMS
714 sn_delay((int)msec);
715 #endif
716 #ifdef EENET
717 if(msec >= 1000)
718 {
719 sleep(msec / 1000);
720 msec -= (msec / 1000);
721 }
722 if(msec)
723 usleep(msec * 1000);
724 #endif
725 #ifdef INSOCK
726 DelayThread(msec * 1000);
727 #endif
728
729#elif defined(_PSP)
730 sceKernelDelayThread(msec * 1000);
731
732#elif defined(_UNIX)
733 usleep(msec * 1000);
734
735#elif defined(_NITRO)
736 OS_Sleep(msec);
737
738#elif defined(_PS3)
739 sys_timer_usleep(msec* 1000);
740#elif defined (_REVOLUTION)
741 OSSleepMilliseconds(msec);
742#else
743 assert(0); // missing platform handler, contact devsupport
744#endif
745}
746
749// Cross-platform GSI wrapper time conversion functions
750//
751// NOTE: some portions of this copied from standard C library
752#if defined(_NITRO) || defined(_REVOLUTION)
753
754// if an error occurs when calling mktime, return -1
755#define MKTIME_ERROR (time_t)(-1)
756
757// define common conversions for mktime
758#define DAY_SEC (24L * 60L * 60L) /* secs in a day */
759#define YEAR_SEC (365L * DAY_SEC) /* secs in a year */
760#define FOUR_YEAR_SEC (1461L * DAY_SEC) /* secs in a 4 year interval */
761#define DEC_SEC 315532800L /* secs in 1970-1979 */
762#define BASE_DOW 4 /* 01-01-70 was a Thursday */
763#define BASE_YEAR 70L /* 1970 is the base year */
764#define LEAP_YEAR_ADJUST 17L /* Leap years 1900 - 1970 */
765#define MAX_YEAR 138L /* 2038 is the max year */
766
767// ChkAdd evaluates to TRUE if dest = src1 + src2 has overflowed
768#define ChkAdd(dest, src1, src2) ( ((src1 >= 0L) && (src2 >= 0L) \
769 && (dest < 0L)) || ((src1 < 0L) && (src2 < 0L) && (dest >= 0L)) )
770
771// ChkMul evaluates to TRUE if dest = src1 * src2 has overflowed
772#define ChkMul(dest, src1, src2) ( src1 ? (dest/src1 != src2) : 0 )
773
774int _lpdays[] = { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
775int _days[] = { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 };
776
777const char _dnames[] = { "SunMonTueWedThuFriSat" };
778/* Month names must be Three character abbreviations strung together */
779const char _mnames[] = { "JanFebMarAprMayJunJulAugSepOctNovDec" };
780
781static struct tm tb = { 0 }; /* time block used in SecondsToDate */
782
783static char buf[26]; /* buffer used to store string in SecondsToString */
784
785
786static char * store_dt(char *, int);
787static char * store_dt(char *p, int val)
788{
789 *p++ = (char)(_T('0') + val / 10);
790 *p++ = (char)(_T('0') + val % 10);
791 return(p);
792}
793#endif //_NITRO || _REVOLUTION
794
797// GSI equivalent of Standard C-lib "gmtime function"
798struct tm * gsiSecondsToDate(const time_t *timp)
799{
800#if !defined(_NITRO) && !defined(_REVOLUTION)
801
802 // for all platforms that support the standard C 'gmtime' use that
803 return gmtime(timp);
804
805#else
806 time_t caltim = *timp; /* calendar time to convert */
807 int islpyr = 0; /* is-current-year-a-leap-year flag */
808 int tmptim;
809 int *mdays; /* pointer to days or lpdays */
810 struct tm *ptb = &tb;
811
812
813 if ( caltim < 0L )
814 return(NULL);
815
816 /*
817 * Determine years since 1970. First, identify the four-year interval
818 * since this makes handling leap-years easy (note that 2000 IS a
819 * leap year and 2100 is out-of-range).
820 */
821 tmptim = (int)(caltim / FOUR_YEAR_SEC);
822 caltim -= ((long)tmptim * FOUR_YEAR_SEC);
823
824 /*
825 * Determine which year of the interval
826 */
827 tmptim = (tmptim * 4) + 70; /* 1970, 1974, 1978,...,etc. */
828
829 if ( caltim >= YEAR_SEC )
830 {
831 tmptim++; /* 1971, 1975, 1979,...,etc. */
832 caltim -= YEAR_SEC;
833
834 if ( caltim >= YEAR_SEC )
835 {
836 tmptim++; /* 1972, 1976, 1980,...,etc. */
837 caltim -= YEAR_SEC;
838
839 /*
840 * Note, it takes 366 days-worth of seconds to get past a leap
841 * year.
842 */
843 if ( caltim >= (YEAR_SEC + DAY_SEC) )
844 {
845 tmptim++; /* 1973, 1977, 1981,...,etc. */
846 caltim -= (YEAR_SEC + DAY_SEC);
847 }
848 else
849 {
850 /*
851 * In a leap year after all, set the flag.
852 */
853 islpyr++;
854 }
855 }
856 }
857
858 /*
859 * tmptim now holds the value for tm_year. caltim now holds the
860 * number of elapsed seconds since the beginning of that year.
861 */
862 ptb->tm_year = tmptim;
863
864 /*
865 * Determine days since January 1 (0 - 365). This is the tm_yday value.
866 * Leave caltim with number of elapsed seconds in that day.
867 */
868 ptb->tm_yday = (int)(caltim / DAY_SEC);
869 caltim -= (long)(ptb->tm_yday) * DAY_SEC;
870
871 /*
872 * Determine months since January (0 - 11) and day of month (1 - 31)
873 */
874 if ( islpyr )
875 mdays = _lpdays;
876 else
877 mdays = _days;
878
879
880 for ( tmptim = 1 ; mdays[tmptim] < ptb->tm_yday ; tmptim++ ) ;
881
882 ptb->tm_mon = --tmptim;
883
884 ptb->tm_mday = ptb->tm_yday - mdays[tmptim];
885
886 /*
887 * Determine days since Sunday (0 - 6)
888 */
889 ptb->tm_wday = ((int)(*timp / DAY_SEC) + BASE_DOW) % 7;
890
891 /*
892 * Determine hours since midnight (0 - 23), minutes after the hour
893 * (0 - 59), and seconds after the minute (0 - 59).
894 */
895 ptb->tm_hour = (int)(caltim / 3600);
896 caltim -= (long)ptb->tm_hour * 3600L;
897
898 ptb->tm_min = (int)(caltim / 60);
899 ptb->tm_sec = (int)(caltim - (ptb->tm_min) * 60);
900
901 ptb->tm_isdst = 0;
902 return( (struct tm *)ptb );
903#endif
904}
905
908// GSI equivalent of Standard C-lib "mktime function"
909time_t gsiDateToSeconds(struct tm *tb)
910{
911#if !defined(_NITRO) && !defined(_REVOLUTION)
912
913 // for all platforms that support the standard C 'mktime' use that
914 return mktime(tb);
915
916#else
917 time_t tmptm1, tmptm2, tmptm3;
918 struct tm *tbtemp;
919 /*
920 * First, make sure tm_year is reasonably close to being in range.
921 */
922 if ( ((tmptm1 = tb->tm_year) < BASE_YEAR - 1) || (tmptm1 > MAX_YEAR + 1) )
923 return MKTIME_ERROR;
924
925
926 /*
927 * Adjust month value so it is in the range 0 - 11. This is because
928 * we don't know how many days are in months 12, 13, 14, etc.
929 */
930
931 if ( (tb->tm_mon < 0) || (tb->tm_mon > 11) ) {
932
933 /*
934 * no danger of overflow because the range check above.
935 */
936 tmptm1 += (tb->tm_mon / 12);
937
938 if ( (tb->tm_mon %= 12) < 0 ) {
939 tb->tm_mon += 12;
940 tmptm1--;
941 }
942
943 /*
944 * Make sure year count is still in range.
945 */
946 if ( (tmptm1 < BASE_YEAR - 1) || (tmptm1 > MAX_YEAR + 1) )
947 return MKTIME_ERROR;
948 }
949
950 /***** HERE: tmptm1 holds number of elapsed years *****/
951
952 /*
953 * Calculate days elapsed minus one, in the given year, to the given
954 * month. Check for leap year and adjust if necessary.
955 */
956 tmptm2 = _days[tb->tm_mon];
957 if ( !(tmptm1 & 3) && (tb->tm_mon > 1) )
958 tmptm2++;
959
960 /*
961 * Calculate elapsed days since base date (midnight, 1/1/70, UTC)
962 *
963 *
964 * 365 days for each elapsed year since 1970, plus one more day for
965 * each elapsed leap year. no danger of overflow because of the range
966 * check (above) on tmptm1.
967 */
968 tmptm3 = (tmptm1 - BASE_YEAR) * 365L + ((tmptm1 - 1L) >> 2)
969 - LEAP_YEAR_ADJUST;
970
971 /*
972 * elapsed days to current month (still no possible overflow)
973 */
974 tmptm3 += tmptm2;
975
976 /*
977 * elapsed days to current date. overflow is now possible.
978 */
979 tmptm1 = tmptm3 + (tmptm2 = (long)(tb->tm_mday));
980 if ( ChkAdd(tmptm1, tmptm3, tmptm2) )
981 return MKTIME_ERROR;
982
983 /***** HERE: tmptm1 holds number of elapsed days *****/
984
985 /*
986 * Calculate elapsed hours since base date
987 */
988 tmptm2 = tmptm1 * 24L;
989 if ( ChkMul(tmptm2, tmptm1, 24L) )
990 return MKTIME_ERROR;
991
992 tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_hour);
993 if ( ChkAdd(tmptm1, tmptm2, tmptm3) )
994 return MKTIME_ERROR;
995
996 /***** HERE: tmptm1 holds number of elapsed hours *****/
997
998 /*
999 * Calculate elapsed minutes since base date
1000 */
1001
1002 tmptm2 = tmptm1 * 60L;
1003 if ( ChkMul(tmptm2, tmptm1, 60L) )
1004 return MKTIME_ERROR;
1005
1006 tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_min);
1007 if ( ChkAdd(tmptm1, tmptm2, tmptm3) )
1008 return MKTIME_ERROR;
1009
1010 /***** HERE: tmptm1 holds number of elapsed minutes *****/
1011
1012 /*
1013 * Calculate elapsed seconds since base date
1014 */
1015
1016 tmptm2 = tmptm1 * 60L;
1017 if ( ChkMul(tmptm2, tmptm1, 60L) )
1018 return MKTIME_ERROR;
1019
1020 tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_sec);
1021 if ( ChkAdd(tmptm1, tmptm2, tmptm3) )
1022 return MKTIME_ERROR;
1023
1024 /***** HERE: tmptm1 holds number of elapsed seconds *****/
1025
1026 if ( (tbtemp = gsiSecondsToDate(&tmptm1)) == NULL )
1027 return MKTIME_ERROR;
1028
1029
1030 /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/
1031 /***** for local time if requested *****/
1032
1033 *tb = *tbtemp;
1034 return (time_t)tmptm1;
1035#endif
1036}
1037
1040// GSI equivalent of Standard C-lib "ctime function"
1041char * gsiSecondsToString(const time_t *timp)
1042{
1043#if !defined(_NITRO) && !defined(_REVOLUTION)
1044
1045 // for all platforms that support the standard C 'ctime' use that
1046 return ctime(timp);
1047
1048#else
1049 char *p = buf;
1050 int day, mon;
1051 int i;
1052 struct tm *ptm;
1053
1054 ptm = gsiSecondsToDate(timp); /* parse seconds into date structure */
1055
1056 p = buf; /* use static buffer */
1057
1058 /* copy day and month names into the buffer */
1059
1060 day = ptm->tm_wday * 3; /* index to correct day string */
1061 mon = ptm->tm_mon * 3; /* index to correct month string */
1062
1063 for (i=0; i < 3; i++,p++) {
1064 *p = *(_dnames + day + i);
1065 *(p+4) = *(_mnames + mon + i);
1066 }
1067
1068 *p = _T(' '); /* blank between day and month */
1069
1070 p += 4;
1071
1072 *p++ = _T(' ');
1073 p = store_dt(p, ptm->tm_mday); /* day of the month (1-31) */
1074 *p++ = _T(' ');
1075 p = store_dt(p, ptm->tm_hour); /* hours (0-23) */
1076 *p++ = _T(':');
1077 p = store_dt(p, ptm->tm_min); /* minutes (0-59) */
1078 *p++ = _T(':');
1079 p = store_dt(p, ptm->tm_sec); /* seconds (0-59) */
1080 *p++ = _T(' ');
1081 p = store_dt(p, 19 + (ptm->tm_year/100)); /* year (after 1900) */
1082 p = store_dt(p, ptm->tm_year%100);
1083 *p++ = _T('\n');
1084 *p = _T('\0');
1085
1086 return ((char *) buf);
1087#endif
1088}
1089
1090
1093// Cross platform random number generator
1094#define RANa 16807 // multiplier
1095#define LONGRAND_MAX 2147483647L // 2**31 - 1
1096
1097static long randomnum = 1;
1098
1099static long nextlongrand(long seed)
1100{
1101 unsigned
1102
1103 long lo, hi;
1104 lo = RANa *(unsigned long)(seed & 0xFFFF);
1105 hi = RANa *((unsigned long)seed >> 16);
1106 lo += (hi & 0x7FFF) << 16;
1107
1108 if (lo > LONGRAND_MAX)
1109 {
1110 lo &= LONGRAND_MAX;
1111 ++lo;
1112 }
1113 lo += hi >> 15;
1114
1115 if (lo > LONGRAND_MAX)
1116 {
1117 lo &= LONGRAND_MAX;
1118 ++lo;
1119 }
1120
1121 return(long)lo;
1122}
1123
1124// return next random long
1125static long longrand(void)
1126{
1127 randomnum = nextlongrand(randomnum);
1128 return randomnum;
1129}
1130
1131// to seed it
1132void Util_RandSeed(unsigned long seed)
1133{
1134 // nonzero seed
1135 randomnum = seed ? (long)(seed & LONGRAND_MAX) : 1;
1136}
1137
1138int Util_RandInt(int low, int high)
1139{
1140 unsigned int range = (unsigned int)high-low;
1141 int num;
1142
1143 if (range == 0)
1144 return (low); // Prevent divide by zero
1145
1146 num = (int)(longrand() % range);
1147
1148 return(num + low);
1149}
1150
1151
1154/*****************************
1155UNICODE ENCODING
1156******************************/
1157
1158static void QuartToTrip(char *quart, char *trip, int inlen)
1159{
1160 if (inlen >= 2)
1161 trip[0] = (char)(quart[0] << 2 | quart[1] >> 4);
1162 if (inlen >= 3)
1163 trip[1] = (char)((quart[1] & 0x0F) << 4 | quart[2] >> 2);
1164 if (inlen >= 4)
1165 trip[2] = (char)((quart[2] & 0x3) << 6 | quart[3]);
1166}
1167
1168static void TripToQuart(const char *trip, char *quart, int inlen)
1169{
1170 unsigned char triptemp[3];
1171 int i;
1172 for (i = 0; i < inlen ; i++)
1173 {
1174 triptemp[i] = (unsigned char)trip[i];
1175 }
1176 while (i < 3) //fill the rest with 0
1177 {
1178 triptemp[i] = 0;
1179 i++;
1180 }
1181 quart[0] = (char)(triptemp[0] >> 2);
1182 quart[1] = (char)(((triptemp[0] & 3) << 4) | (triptemp[1] >> 4));
1183 quart[2] = (char)((triptemp[1] & 0x0F) << 2 | (triptemp[2] >> 6));
1184 quart[3] = (char)(triptemp[2] & 0x3F);
1185
1186}
1187
1188const char defaultEncoding[] = {'+','/','='};
1189const char alternateEncoding[] = {'[',']','_'};
1190const char urlSafeEncodeing[] = {'-','_','='};
1191
1192void B64Decode(const char *input, char *output, int inlen, int * outlen, int encodingType)
1193{
1194 const char *encoding = NULL;
1195 const char *holdin = input;
1196 int readpos = 0;
1197 int writepos = 0;
1198 char block[4];
1199
1200 //int outlen = -1;
1201 //int inlen = (int)strlen(input);
1202
1203 // 10-31-2004 : Added by Saad Nader
1204 // now supports URL safe encoding
1206 switch(encodingType)
1207 {
1208 case 1:
1209 encoding = alternateEncoding;
1210 break;
1211 case 2:
1212 encoding = urlSafeEncodeing;
1213 break;
1214 default: encoding = defaultEncoding;
1215 }
1216
1217 GS_ASSERT(inlen >= 0);
1218 if (inlen <= 0)
1219 {
1220 if (outlen)
1221 *outlen = 0;
1222 output[0] = '\0';
1223 return;
1224 }
1225
1226 // Break at end of string or padding character
1227 while (readpos < inlen && input[readpos] != encoding[2])
1228 {
1229 // 'A'-'Z' maps to 0-25
1230 // 'a'-'z' maps to 26-51
1231 // '0'-'9' maps to 52-61
1232 // 62 maps to encoding[0]
1233 // 63 maps to encoding[1]
1234 if (input[readpos] >= '0' && input[readpos] <= '9')
1235 block[readpos%4] = (char)(input[readpos] - 48 + 52);
1236 else if (input[readpos] >= 'a' && input[readpos] <= 'z')
1237 block[readpos%4] = (char)(input[readpos] - 71);
1238 else if (input[readpos] >= 'A' && input[readpos] <= 'Z')
1239 block[readpos%4] = (char)(input[readpos] - 65);
1240 else if (input[readpos] == encoding[0])
1241 block[readpos%4] = 62;
1242 else if (input[readpos] == encoding[1])
1243 block[readpos%4] = 63;
1244
1245 // padding or '\0' characters also mark end of input
1246 else if (input[readpos] == encoding[2])
1247 break;
1248 else if (input[readpos] == '\0')
1249 break;
1250 else
1251 {
1252 // (assert(0)); //bad input data
1253 if (outlen)
1254 *outlen = 0;
1255 output[0] = '\0';
1256 return; //invaid data
1257 }
1258
1259 // every 4 bytes, convert QuartToTrip into destination
1260 if (readpos%4==3) // zero based, so (3%4) means four bytes, 0-1-2-3
1261 {
1262 QuartToTrip(block, &output[writepos], 4);
1263 writepos += 3;
1264 }
1265 readpos++;
1266 }
1267
1268 // Convert any leftover characters in block
1269 if ((readpos != 0) && (readpos%4 != 0))
1270 {
1271 // fill block with pad (required for QuartToTrip)
1272 memset(&block[readpos%4], encoding[2], (unsigned int)4-(readpos%4));
1273 QuartToTrip(block, &output[writepos], readpos%4);
1274
1275 // output bytes depend on the number of non-pad input bytes
1276 if (readpos%4 == 3)
1277 writepos += 2;
1278 else
1279 writepos += 1;
1280 }
1281
1282 if (outlen)
1283 *outlen = writepos;
1284
1285 GSI_UNUSED(holdin);
1286}
1287
1288
1289
1290void B64Encode(const char *input, char *output, int inlen, int encodingType)
1291{
1292 const char *encoding;
1293 char *holdout = output;
1294 char *lastchar;
1295 int todo = inlen;
1296
1297 // 10-31-2004 : Added by Saad Nader
1298 // now supports URL safe encoding
1300 switch(encodingType)
1301 {
1302 case 1:
1303 encoding = alternateEncoding;
1304 break;
1305 case 2:
1306 encoding = urlSafeEncodeing;
1307 break;
1308 default: encoding = defaultEncoding;
1309 }
1310
1311//assume interval of 3
1312 while (todo > 0)
1313 {
1314 TripToQuart(input, output, min(todo, 3));
1315 output += 4;
1316 input += 3;
1317 todo -= 3;
1318 }
1319 lastchar = output;
1320 if (inlen % 3 == 1)
1321 lastchar -= 2;
1322 else if (inlen % 3 == 2)
1323 lastchar -= 1;
1324 *output = 0; //null terminate!
1325 while (output > holdout)
1326 {
1327 output--;
1328 if (output >= lastchar) //pad the end
1329 *output = encoding[2];
1330 else if (*output <= 25)
1331 *output = (char)(*output + 65);
1332 else if (*output <= 51)
1333 *output = (char)(*output + 71);
1334 else if (*output <= 61)
1335 *output = (char)(*output + 48 - 52);
1336 else if (*output == 62)
1337 *output = encoding[0];
1338 else if (*output == 63)
1339 *output = encoding[1];
1340 }
1341}
1342
1343int B64DecodeLen(const char *input, int encodingType)
1344{
1345 const char *encoding;
1346 const char *holdin = input;
1347
1348 switch(encodingType)
1349 {
1350 case 1:
1351 encoding = alternateEncoding;
1352 break;
1353 case 2:
1354 encoding = urlSafeEncodeing;
1355 break;
1356 default: encoding = defaultEncoding;
1357 }
1358
1359 while (*input)
1360 {
1361 if (*input == encoding[2])
1362 return (input - holdin) / 4 * 3 + (input - holdin - 1) % 4;
1363 input++;
1364 }
1365
1366 return (input - holdin) / 4 * 3;
1367}
1368
1369void B64InitEncodeStream(B64StreamData *data, const char *input, int len, int encodingType)
1370{
1371 data->input = input;
1372 data->len = len;
1373 data->encodingType = encodingType;
1374}
1375
1376gsi_bool B64EncodeStream(B64StreamData *data, char output[4])
1377{
1378 const char *encoding;
1379 char *c;
1380 int i;
1381
1382 if(data->len <= 0)
1383 return gsi_false;
1384
1385 // 10-31-2004 : Added by Saad Nader
1386 // now supports URL safe encoding
1388 switch(data->encodingType)
1389 {
1390 case 1:
1391 encoding = alternateEncoding;
1392 break;
1393 case 2:
1394 encoding = urlSafeEncodeing;
1395 break;
1396 default: encoding = defaultEncoding;
1397 }
1398
1399 TripToQuart(data->input, output, min(data->len, 3));
1400 data->input += 3;
1401 data->len -= 3;
1402
1403 for(i = 0 ; i < 4 ; i++)
1404 {
1405 c = &output[i];
1406 if (*c <= 25)
1407 *c = (char)(*c + 65);
1408 else if (*c <= 51)
1409 *c = (char)(*c + 71);
1410 else if (*c <= 61)
1411 *c = (char)(*c + 48 - 52);
1412 else if (*c == 62)
1413 *c = encoding[0];
1414 else if (*c == 63)
1415 *c = encoding[1];
1416 }
1417
1418 if(data->len < 0)
1419 {
1420 output[3] = encoding[2];
1421 if(data->len == -2)
1422 output[2] = encoding[2];
1423 }
1424
1425 return gsi_true;
1426}
1427
1430void gsiPadRight(char *cArray, char padChar, int cLength);
1431char * gsiXxteaAlg(const char *sIn, int nIn, char key[XXTEA_KEY_SIZE], int bEnc, int *nOut);
1432
1433void gsiPadRight(char *cArray, char padChar, int cLength)
1434{
1435 int diff;
1436 int length = (int)strlen(cArray);
1437
1438 diff = cLength - length;
1439 memset(&cArray[length], padChar, (size_t)diff);
1440}
1441
1442
1445// The heart of the XXTEA encryption/decryption algorithm.
1446//
1447// sIn: Input stream.
1448// nIn: Input length (bytes).
1449// key: Key (only first 128 bits are significant).
1450// bEnc: Encrypt (else decrypt)?
1451char * gsiXxteaAlg(const char *sIn, int nIn, char key[XXTEA_KEY_SIZE], int bEnc, int *nOut)
1452{
1453 int i, p, n1;
1454 unsigned int *k, *v, z, y;
1455 char *oStr = NULL, *pStr = NULL;
1456 char *sIn2 = NULL;
1458 // ERROR CHECK!
1459 if (!sIn || !key[0] || nIn == 0)
1460 return NULL;
1461
1462 // Convert stream length to a round number of 32-bit words
1463 // Convert byte count to 32-bit word count
1464 if (nIn % 4 == 0) // Fix for null terminated strings divisible by 4
1465 nIn = (nIn/4)+1;
1466 else
1467 nIn = (nIn + 3)/4;
1468
1469 if ( nIn <= 1 ) // XXTEA requires at least 64 bits
1470 nIn = 2;
1471
1472 // Load and zero-pad first 16 characters (128 bits) of key
1473 gsiPadRight( key , '\0', XXTEA_KEY_SIZE);
1474 k = (unsigned int *)key;
1475
1476 // Load and zero-pad entire input stream as 32-bit words
1477 sIn2 = (char *)gsimalloc((size_t)(4 * nIn));
1478 strcpy(sIn2, sIn);
1479 gsiPadRight( sIn2, '\0', 4*nIn);
1480 v = (unsigned int *)sIn2;
1481
1482 // Prepare to encrypt or decrypt
1483 n1 = nIn - 1;
1484 z = v[ n1 ];
1485 y = v[ 0 ];
1486 i = ( int )( 6 + 52/nIn );
1487
1488 if (bEnc == 1) // Encrypt
1489 {
1490 unsigned int sum = 0;
1491 while ( i-- != 0 )
1492 {
1493 int e;
1494 sum += 0x9E3779B9;
1495 e = ( int )( sum >> 2 );
1496 for ( p = -1; ++p < nIn; )
1497 {
1498 y = v[( p < n1 ) ? p + 1 : 0 ];
1499 z = ( v[ p ] +=
1500 ( (( z >> 5 ) ^ ( y << 2 ))
1501 + (( y >> 3 ) ^ ( z << 4 )))
1502 ^ ( ( sum ^ y )
1503 + ( k[( p ^ e ) & 3 ] ^ z )));
1504 }
1505 }
1506 }
1507 else if (bEnc == 0) // Decrypt
1508 {
1509 unsigned int sum = ( unsigned int ) i * 0x9E3779B9;
1510 while ( sum != 0 )
1511 {
1512 int e = ( int )( sum >> 2 );
1513 for ( p = nIn; p-- != 0; )
1514 {
1515 z = v[( p != 0 ) ? p - 1 : n1 ];
1516 y = ( v[ p ] -=
1517 ( (( z >> 5 ) ^ ( y << 2 ))
1518 + (( y >> 3 ) ^ ( z << 4 )))
1519 ^ ( ( sum ^ y )
1520 + ( k[( p ^ e ) & 3 ] ^ z )));
1521 }
1522 sum -= 0x9E3779B9;
1523 }
1524 }
1525 else return NULL;
1526 // Convert result from 32-bit words to a byte stream
1527
1528
1529 oStr = (char *)gsimalloc((size_t)(4 * nIn + 1));
1530 pStr = oStr;
1531 *nOut = 4 *nIn;
1532 for ( i = -1; ++i < nIn; )
1533 {
1534 unsigned int q = v[ i ];
1535
1536 *pStr++ = (char)(q & 0xFF);
1537 *pStr++ = (char)(( q >> 8 ) & 0xFF);
1538 *pStr++ = (char)(( q >> 16 ) & 0xFF);
1539 *pStr++ = (char)(( q >> 24 ) & 0xFF);
1540 }
1541 *pStr = '\0';
1542 gsifree(sIn2);
1543
1544 return oStr;
1545}
1546
1547
1550// XXTEA Encrpyt
1551// params
1552// iStr : the input string to be encrypted
1553// iLength : the length of the input string
1554// key : the key used to encrypt
1555char * gsXxteaEncrypt(const char * iStr, int iLength, char key[XXTEA_KEY_SIZE], int *oLength)
1556{
1557 return gsiXxteaAlg( iStr, iLength, key, 1, oLength );
1558}
1559
1560
1563// XXTEA Decrypt
1564// params
1565// iStr : the input string to be decrypted
1566// iLength : the length of the input string
1567// key : the key used to decrypt
1568char * gsXxteaDecrypt(const char * iStr, int iLength, char key[XXTEA_KEY_SIZE], int *oLength)
1569{
1570 return gsiXxteaAlg( iStr, iLength, key, 0, oLength);
1571}
1572
1573
1576#if defined(_DEBUG)
1577
1578void gsiCheckStack(void)
1579{
1580#if defined(_NITRO)
1581#if 1
1582 OS_CheckStack(OS_GetCurrentThread());
1583#elif 1
1584 static gsi_bool checkFailed = gsi_false;
1585 if(!checkFailed)
1586 {
1587 OSStackStatus status = OS_GetStackStatus(OS_GetCurrentThread());
1588 if(status != 0)
1589 {
1590 const char * reason;
1591 if(status == OS_STACK_OVERFLOW)
1592 reason = "OVERFLOW";
1593 else if(status == OS_STACK_ABOUT_TO_OVERFLOW)
1594 reason = "ABOUT TO OVERFLOW";
1595 else if(status == OS_STACK_UNDERFLOW)
1596 reason = "UNDERFLOW";
1597 else
1598 reason = "UNKOWN REASON";
1599
1600 OS_TPrintf("STACK CHECK FAILED!: %s\n", reason);
1601
1602 checkFailed = gsi_true;
1603 }
1604 }
1605#endif
1606#endif // nitro
1607}
1608#endif // _DEBUG
1609
1610
1613#ifdef SN_SYSTEMS
1614int GOAGetLastError(SOCKET s)
1615{
1616 int val = 0;
1617 int soval = sizeof(val);
1618 if (0 != getsockopt(s,SOL_SOCKET,SO_ERROR,&val,&soval))
1619 return 0; // getsockopt failed
1620 else
1621 return val;
1622}
1623#endif
1624
1625#ifdef _NITRO
1626static const char * GOAGetUniqueID_Internal(void)
1627{
1628 static char keyval[17];
1629 u8 MAC[MAC_ALEN];
1630
1631 // check if we already have the Unique ID
1632 if(keyval[0])
1633 return keyval;
1634
1635 // get the MAC
1636 IP_GetMacAddr(NULL, MAC);
1637
1638 // format it
1639 sprintf(keyval, "%02X%02X%02X%02X%02X%02X0000",
1640 MAC[0] & 0xFF,
1641 MAC[1] & 0xFF,
1642 MAC[2] & 0xFF,
1643 MAC[3] & 0xFF,
1644 MAC[4] & 0xFF,
1645 MAC[5] & 0xFF);
1646
1647 return keyval;
1648}
1649#endif
1650
1651
1652#ifdef _PS2
1653#ifdef UNIQUEID
1654
1655#if defined(EENET)
1656
1657#include <net/if_dl.h>
1658// Removed due to updated sony libraries, Saad Nader
1659//#include <net/if_types.h>
1660#include <net/if_ether.h>
1661
1662static const char * GetMAC(void)
1663{
1664 static struct sceEENetEtherAddr linkAddress;
1665 struct sceEENetIfname * interfaces;
1666 struct sceEENetIfname * interface;
1667 int num;
1668 int type;
1669 int len;
1670 int i;
1671 const unsigned char * MAC = NULL;
1672
1673 // get the local interfaces
1674 sceEENetGetIfnames(NULL, &num);
1675 interfaces = (struct sceEENetIfname *)gsimalloc(num * sizeof(struct sceEENetIfname));
1676 if(!interfaces)
1677 return NULL;
1678 sceEENetGetIfnames(interfaces, &num);
1679
1680 // loop through the interfaces
1681 for(i = 0 ; i < num ; i++)
1682 {
1683 // the next interface
1684 interface = &interfaces[i];
1685 //printf("eenet%d: %s\n", i, interface->ifn_name);
1686
1687 // get the type
1688 len = sizeof(type);
1689 if(sceEENetGetIfinfo(interface->ifn_name, sceEENET_IFINFO_IFTYPE, &type, &len) != 0)
1690 continue;
1691 //printf("eenet%d type: %d\n", i, type);
1692
1693 // check for ethernet
1694 if(type != sceEENET_IFTYPE_ETHER)
1695 continue;
1696 //printf("eenet%d: ethernet\n", i);
1697
1698 // get the address
1699 len = sizeof(linkAddress);
1700 if(sceEENetGetIfinfo(interface->ifn_name, sceEENET_IFINFO_MACADDR, &linkAddress, &len) != 0)
1701 continue;
1702 MAC = linkAddress.ether_addr_octet;
1703 //printf("eenet%d: MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", i, MAC[0], MAC[1], MAC[2], MAC[3], MAC[4], MAC[5]);
1704
1705 break;
1706 }
1707
1708 // free the interfaces
1709 gsifree(interfaces);
1710
1711 return MAC;
1712}
1713
1714#elif defined(SN_SYSTEMS)
1715
1716 static const char * GetMAC(void)
1717 {
1718 static char MAC[6];
1719 int len = sizeof(MAC);
1720 int rcode;
1721
1722 // get the MAC
1723 rcode = sndev_get_status(0, SN_DEV_STAT_MAC, MAC, &len);
1724 if((rcode != 0) || (len != 6))
1725 return NULL;
1726
1727 return MAC;
1728 }
1729
1730#elif defined(INSOCK)
1731
1732 static const char * GetMAC(void)
1733 {
1734 // Get the MAC address using the interface control
1735 static char MAC[16];
1736 extern sceSifMClientData gGSIInsockClientData;
1737 extern u_int gGSIInsockSocketBuffer[NETBUFSIZE] __attribute__((aligned(64)));
1738
1739 int result = sceInetInterfaceControl(&gGSIInsockClientData, &gGSIInsockSocketBuffer,
1740 1, sceInetCC_GetHWaddr, MAC, sizeof(MAC));
1741 if (result == sceINETE_OK)
1742 return MAC;
1743
1744 // error
1745 return NULL;
1746 }
1747
1748#endif
1749
1750static const char * GOAGetUniqueID_Internal(void)
1751{
1752 static char keyval[17];
1753 const char * MAC;
1754
1755 // check if we already have the Unique ID
1756 if(keyval[0])
1757 return keyval;
1758
1759 // get the MAC
1760 MAC = GetMAC();
1761 if(!MAC)
1762 {
1763 // error getting the MAC
1764 static char errorMAC[6] = { 1, 2, 3, 4, 5, 6 };
1765 MAC = errorMAC;
1766 }
1767
1768 // format it
1769 sprintf(keyval, "%02X%02X%02X%02X%02X%02X0000",
1770 MAC[0] & 0xFF,
1771 MAC[1] & 0xFF,
1772 MAC[2] & 0xFF,
1773 MAC[3] & 0xFF,
1774 MAC[4] & 0xFF,
1775 MAC[5] & 0xFF);
1776
1777 return keyval;
1778}
1779
1780#endif // UNIQUEID
1781#endif // _PS2
1782
1783
1784#if ((defined(_WIN32) && !defined(_XBOX)) || defined(_UNIX))
1785
1786static void GenerateID(char *keyval)
1787{
1788 int i;
1789 const char crypttab[63] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1790#ifdef _WIN32
1791 LARGE_INTEGER l1;
1792 UINT seed;
1793 if (QueryPerformanceCounter(&l1))
1794 seed = (l1.LowPart ^ l1.HighPart);
1795 else
1796 seed = 0;
1797 Util_RandSeed(seed ^ GetTickCount() ^ (unsigned long)time(NULL) ^ clock());
1798#else
1799 Util_RandSeed(time(NULL) ^ clock());
1800#endif
1801 for (i = 0; i < 19; i++)
1802 if (i == 4 || i == 9 || i == 14)
1803 keyval[i] = '-';
1804 else
1805 keyval[i] = crypttab[Util_RandInt(0, 62)];
1806 keyval[19] = 0;
1807}
1808
1809#ifndef PATH_MAX
1810#define PATH_MAX MAX_PATH
1811#endif
1812
1813#ifdef _WIN32
1814#define REG_KEY "Software\\GameSpy\\GameSpy 3D\\Registration"
1815#endif
1816
1817const char * GOAGetUniqueID_Internal(void)
1818{
1819 static char keyval[PATH_MAX] = "";
1820 unsigned int ret;
1821
1822#ifdef _WIN32
1823 int docreate;
1824 HKEY thekey;
1825 DWORD thetype = REG_SZ;
1826 DWORD len = MAX_PATH;
1827 DWORD disp;
1828
1829 if (RegOpenKeyExA(HKEY_CURRENT_USER, REG_KEY, 0, KEY_ALL_ACCESS, &thekey) != ERROR_SUCCESS)
1830 docreate = 1;
1831 else
1832 docreate = 0;
1833 ret = RegQueryValueExA(thekey, (LPCSTR)"Crypt", 0, &thetype, (LPBYTE)keyval, &len);
1834#else
1835 FILE *f;
1836 f = fopen("id.bin","r");
1837 if (!f)
1838 ret = 0;
1839 else
1840 {
1841 ret = fread(keyval,1,19,f);
1842 keyval[ret] = 0;
1843 fclose(f);
1844 }
1845#endif
1846
1847 if (ret != 0 || strlen(keyval) != 19)//need to generate a new key
1848 {
1849 GenerateID(keyval);
1850#ifdef _WIN32
1851 if (docreate)
1852 {
1853 ret = RegCreateKeyExA(HKEY_CURRENT_USER, REG_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &thekey, &disp);
1854 }
1855 RegSetValueExA(thekey, (LPCSTR)"Crypt", 0, REG_SZ, (const LPBYTE)keyval, strlen(keyval)+1);
1856#else
1857 f = fopen("id.bin","w");
1858 if (f)
1859 {
1860 fwrite(keyval,1,19,f);
1861 fclose(f);
1862 } else
1863 keyval[0] = 0; //don't generate one each time!!
1864#endif
1865 }
1866
1867#ifdef _WIN32
1868 RegCloseKey(thekey);
1869#endif
1870
1871 // Strip out the -'s.
1873 memmove(keyval + 4, keyval + 5, 4);
1874 memmove(keyval + 8, keyval + 10, 4);
1875 memmove(keyval + 12, keyval + 15, 4);
1876 keyval[16] = '\0';
1877
1878 return keyval;
1879}
1880
1881#endif
1882
1883#ifdef _PSP
1884// Included here so that the implementation can appear in gsPlatformPSP.c
1885const char * GOAGetUniqueID_Internal(void);
1886#endif
1887
1888
1889#if (!defined(_PS2) && !defined(_PS3) && !defined(_XBOX) && !defined(_PSP)) || defined(UNIQUEID)
1890GetUniqueIDFunction GOAGetUniqueID = GOAGetUniqueID_Internal;
1891#endif
1892
1895#if defined(__cplusplus)
1896}
1897#endif
@ string
string value
Definition json.hpp:2859
Definition gsPlatformUtil.h:68
Definition gsPlatformUtil.c:43