├── .gitignore ├── LICENSE ├── README.md └── system ├── imembase.c ├── imembase.h ├── imemdata.c ├── imemdata.h ├── inetbase.c ├── inetbase.h ├── inetcode.c ├── inetcode.h ├── inetkcp.c ├── inetkcp.h ├── inetnot.c ├── inetnot.h ├── inetsim.c ├── inetsim.h ├── inettcp.c ├── inettcp.h ├── ineturl.c ├── ineturl.h ├── iposix.c ├── iposix.h ├── isecure.c ├── isecure.h ├── itimer.c ├── itimer.h ├── itoolbox.c ├── itoolbox.h └── system.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Libraries 8 | *.lib 9 | *.a 10 | 11 | # Shared objects (inc. Windows DLLs) 12 | *.dll 13 | *.so 14 | *.so.* 15 | *.dylib 16 | 17 | # Executables 18 | *.exe 19 | *.out 20 | *.app 21 | *.i*86 22 | *.x86_64 23 | *.hex 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Linwei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | nanolib 2 | ======= 3 | 4 | Cross-Platform networking library 5 | 6 | -------------------------------------------------------------------------------- /system/inetbase.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * inetbase.h - basic interface of socket operation & system calls 4 | * skywind3000 (at) gmail.com, 2006-2016 5 | * 6 | * for more information, please see the readme file. 7 | * 8 | * link: -lpthread -lrt (linux/bsd/aix/...) 9 | * link: -lwsock32 -lwinmm -lws2_32 (win) 10 | * link: -lsocket -lnsl -lpthread (solaris) 11 | * 12 | **********************************************************************/ 13 | 14 | #ifndef __INETBASE_H__ 15 | #define __INETBASE_H__ 16 | 17 | /*-------------------------------------------------------------------*/ 18 | /* C99 Compatible */ 19 | /*-------------------------------------------------------------------*/ 20 | #if defined(linux) || defined(__linux) || defined(__linux__) 21 | 22 | #ifndef __linux 23 | #define __linux 1 24 | #endif 25 | 26 | #define _GNU_SOURCE 1 27 | #define _BSD_SOURCE 1 28 | #define _SVID_SOURCE 1 29 | #define _DEFAULT_SOURCE 1 30 | 31 | #endif 32 | 33 | #include 34 | #include 35 | 36 | #if defined(__unix__) || defined(unix) || defined(__linux) 37 | #ifndef __unix 38 | #define __unix 1 39 | #endif 40 | #endif 41 | 42 | 43 | /*-------------------------------------------------------------------*/ 44 | /* Unix Platform */ 45 | /*-------------------------------------------------------------------*/ 46 | #if defined(__unix) || defined(unix) || defined(__MACH__) || defined(_AIX) 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | 59 | #if defined(__sun) || defined(__sun__) 60 | #include 61 | #endif 62 | 63 | #ifndef __unix 64 | #define __unix 1 65 | #endif 66 | 67 | #if defined(__MACH__) && (!defined(_SOCKLEN_T)) && (!defined(HAVE_SOCKLEN)) 68 | typedef int socklen_t; 69 | #endif 70 | 71 | #include 72 | 73 | #define IESOCKET -1 74 | #define IEAGAIN EAGAIN 75 | #define IEISCONN EISCONN 76 | #define IEINPROGRESS EINPROGRESS 77 | #define IEALREADY EALREADY 78 | 79 | 80 | /*-------------------------------------------------------------------*/ 81 | /* Windows Platform */ 82 | /*-------------------------------------------------------------------*/ 83 | #elif defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) 84 | #if ((!defined(_M_PPC)) && (!defined(_M_PPC_BE)) && (!defined(_XBOX))) 85 | #ifndef _WIN32_WINNT 86 | #define _WIN32_WINNT 0x0500 87 | #endif 88 | #ifndef WIN32_LEAN_AND_MEAN 89 | #define WIN32_LEAN_AND_MEAN 90 | #endif 91 | #include 92 | #include 93 | #ifdef AF_INET6 94 | #include 95 | #endif 96 | #else 97 | #ifndef _XBOX 98 | #define _XBOX 99 | #endif 100 | #include 101 | #include 102 | #endif 103 | 104 | #include 105 | 106 | #define IESOCKET SOCKET_ERROR 107 | #define IEAGAIN WSAEWOULDBLOCK 108 | #define IEISCONN WSAEISCONN 109 | #define IEINPROGRESS WSAEINPROGRESS 110 | #define IEALREADY WSAEALREADY 111 | 112 | #ifndef IPV6_V6ONLY 113 | #define IPV6_V6ONLY 27 114 | #endif 115 | 116 | #ifndef _WIN32 117 | #define _WIN32 118 | #endif 119 | 120 | typedef int socklen_t; 121 | typedef SOCKET Socket; 122 | 123 | #ifndef EWOULDBLOCK 124 | #define EWOULDBLOCK WSAEWOULDBLOCK 125 | #endif 126 | #ifndef EAGAIN 127 | #define EAGAIN WSAEWOULDBLOCK 128 | #endif 129 | #ifndef EINPROGRESS 130 | #define EINPROGRESS WSAEINPROGRESS 131 | #endif 132 | #ifndef EALREADY 133 | #define EALREADY WSAEALREADY 134 | #endif 135 | #ifndef ENOTSOCK 136 | #define ENOTSOCK WSAENOTSOCK 137 | #endif 138 | #ifndef EDESTADDRREQ 139 | #define EDESTADDRREQ WSAEDESTADDRREQ 140 | #endif 141 | #ifndef EMSGSIZE 142 | #define EMSGSIZE WSAEMSGSIZE 143 | #endif 144 | #ifndef EPROTOTYPE 145 | #define EPROTOTYPE WSAEPROTOTYPE 146 | #endif 147 | #ifndef ENOPROTOOPT 148 | #define ENOPROTOOPT WSAENOPROTOOPT 149 | #endif 150 | #ifndef EPROTONOSUPPORT 151 | #define EPROTONOSUPPORT WSAEPROTONOSUPPORT 152 | #endif 153 | #ifndef ESOCKTNOSUPPORT 154 | #define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT 155 | #endif 156 | #ifndef EOPNOTSUPP 157 | #define EOPNOTSUPP WSAEOPNOTSUPP 158 | #endif 159 | #ifndef EPFNOSUPPORT 160 | #define EPFNOSUPPORT WSAEPFNOSUPPORT 161 | #endif 162 | #ifndef EAFNOSUPPORT 163 | #define EAFNOSUPPORT WSAEAFNOSUPPORT 164 | #endif 165 | #ifndef EADDRINUSE 166 | #define EADDRINUSE WSAEADDRINUSE 167 | #endif 168 | #ifndef EADDRNOTAVAIL 169 | #define EADDRNOTAVAIL WSAEADDRNOTAVAIL 170 | #endif 171 | 172 | #ifndef ENETDOWN 173 | #define ENETDOWN WSAENETDOWN 174 | #endif 175 | #ifndef ENETUNREACH 176 | #define ENETUNREACH WSAENETUNREACH 177 | #endif 178 | #ifndef ENETRESET 179 | #define ENETRESET WSAENETRESET 180 | #endif 181 | #ifndef ECONNABORTED 182 | #define ECONNABORTED WSAECONNABORTED 183 | #endif 184 | #ifndef ECONNRESET 185 | #define ECONNRESET WSAECONNRESET 186 | #endif 187 | #ifndef ENOBUFS 188 | #define ENOBUFS WSAENOBUFS 189 | #endif 190 | #ifndef EISCONN 191 | #define EISCONN WSAEISCONN 192 | #endif 193 | #ifndef ENOTCONN 194 | #define ENOTCONN WSAENOTCONN 195 | #endif 196 | #ifndef ESHUTDOWN 197 | #define ESHUTDOWN WSAESHUTDOWN 198 | #endif 199 | #ifndef ETOOMANYREFS 200 | #define ETOOMANYREFS WSAETOOMANYREFS 201 | #endif 202 | #ifndef ETIMEDOUT 203 | #define ETIMEDOUT WSAETIMEDOUT 204 | #endif 205 | #ifndef ECONNREFUSED 206 | #define ECONNREFUSED WSAECONNREFUSED 207 | #endif 208 | #ifndef ELOOP 209 | #define ELOOP WSAELOOP 210 | #endif 211 | #ifndef EHOSTDOWN 212 | #define EHOSTDOWN WSAEHOSTDOWN 213 | #endif 214 | #ifndef EHOSTUNREACH 215 | #define EHOSTUNREACH WSAEHOSTUNREACH 216 | #endif 217 | #define EPROCLIM WSAEPROCLIM 218 | #define EUSERS WSAEUSERS 219 | #define EDQUOT WSAEDQUOT 220 | #define ESTALE WSAESTALE 221 | #define EREMOTE WSAEREMOTE 222 | 223 | #else 224 | #error Unknow platform, only support unix and win32 225 | #endif 226 | 227 | #ifndef EINVAL 228 | #define EINVAL 22 229 | #endif 230 | 231 | #ifdef IHAVE_CONFIG_H 232 | #include "config.h" 233 | #endif 234 | 235 | #if defined(i386) || defined(__i386__) || defined(__i386) || \ 236 | defined(_M_IX86) || defined(_X86_) || defined(__THW_INTEL) 237 | #ifndef __i386__ 238 | #define __i386__ 239 | #endif 240 | #endif 241 | 242 | #if (defined(__MACH__) && defined(__APPLE__)) || defined(__MACOS__) 243 | #ifndef __imac__ 244 | #define __imac__ 245 | #endif 246 | #endif 247 | 248 | #if defined(linux) || defined(__linux) || defined(__linux__) 249 | #ifndef __linux 250 | #define __linux 1 251 | #endif 252 | #ifndef __linux__ 253 | #define __linux__ 1 254 | #endif 255 | #endif 256 | 257 | #if defined(__sun) || defined(__sun__) 258 | #ifndef __sun 259 | #define __sun 1 260 | #endif 261 | #ifndef __sun__ 262 | #define __sun__ 1 263 | #endif 264 | #endif 265 | 266 | 267 | /* check ICLOCK_TYPE_REALTIME for using pthread_condattr_setclock */ 268 | #if defined(__CYGWIN__) || defined(__imac__) || defined(__AVM2__) 269 | #define ICLOCK_TYPE_REALTIME 270 | #endif 271 | 272 | #if defined(ANDROID) && (!defined(__ANDROID__)) 273 | #define __ANDROID__ 274 | #endif 275 | 276 | 277 | 278 | /*===================================================================*/ 279 | /* 32BIT INTEGER DEFINITION */ 280 | /*===================================================================*/ 281 | #ifndef __INTEGER_32_BITS__ 282 | #define __INTEGER_32_BITS__ 283 | #if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) 284 | typedef __UINT32_TYPE__ ISTDUINT32; 285 | typedef __INT32_TYPE__ ISTDINT32; 286 | #elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) 287 | typedef __UINT_FAST32_TYPE__ ISTDUINT32; 288 | typedef __INT_FAST32_TYPE__ ISTDINT32; 289 | #elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 290 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 291 | defined(_M_AMD64) 292 | typedef unsigned int ISTDUINT32; 293 | typedef int ISTDINT32; 294 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 295 | defined(__i386) || defined(_M_X86) 296 | typedef unsigned long ISTDUINT32; 297 | typedef long ISTDINT32; 298 | #elif defined(__MACOS__) 299 | typedef UInt32 ISTDUINT32; 300 | typedef SInt32 ISTDINT32; 301 | #elif defined(__APPLE__) && defined(__MACH__) 302 | #include 303 | typedef u_int32_t ISTDUINT32; 304 | typedef int32_t ISTDINT32; 305 | #elif defined(__BEOS__) 306 | #include 307 | typedef u_int32_t ISTDUINT32; 308 | typedef int32_t ISTDINT32; 309 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 310 | typedef unsigned __int32 ISTDUINT32; 311 | typedef __int32 ISTDINT32; 312 | #elif defined(__GNUC__) && (__GNUC__ > 3) 313 | #include 314 | typedef uint32_t ISTDUINT32; 315 | typedef int32_t ISTDINT32; 316 | #else 317 | typedef unsigned long ISTDUINT32; 318 | typedef long ISTDINT32; 319 | #endif 320 | #endif 321 | 322 | 323 | /*===================================================================*/ 324 | /* Global Macro Definition */ 325 | /*===================================================================*/ 326 | #define ISOCK_NOBLOCK 1 /* flag - non-block */ 327 | #define ISOCK_REUSEADDR 2 /* flag - reuse address */ 328 | #define ISOCK_NODELAY 3 /* flag - no delay */ 329 | #define ISOCK_NOPUSH 4 /* flag - no push */ 330 | #define ISOCK_CLOEXEC 5 /* flag - FD_CLOEXEC */ 331 | #define ISOCK_REUSEPORT 8 /* flag - reuse port(bsd) */ 332 | #define ISOCK_UNIXREUSE 16 /* use reuseaddr in bsd */ 333 | 334 | #define ISOCK_ERECV 1 /* event - recv */ 335 | #define ISOCK_ESEND 2 /* event - send */ 336 | #define ISOCK_ERROR 4 /* event - error */ 337 | 338 | #if (defined(__BORLANDC__) || defined(__WATCOMC__)) 339 | #pragma warn -8002 340 | #pragma warn -8004 341 | #pragma warn -8008 342 | #pragma warn -8012 343 | #pragma warn -8027 344 | #pragma warn -8057 345 | #pragma warn -8066 346 | #endif 347 | 348 | #ifndef ICLOCKS_PER_SEC 349 | #ifdef CLK_TCK 350 | #define ICLOCKS_PER_SEC CLK_TCK 351 | #else 352 | #define ICLOCKS_PER_SEC 1000000 353 | #endif 354 | #endif 355 | 356 | #ifndef __IINT8_DEFINED 357 | #define __IINT8_DEFINED 358 | typedef char IINT8; 359 | #endif 360 | 361 | #ifndef __IUINT8_DEFINED 362 | #define __IUINT8_DEFINED 363 | typedef unsigned char IUINT8; 364 | #endif 365 | 366 | #ifndef __IUINT16_DEFINED 367 | #define __IUINT16_DEFINED 368 | typedef unsigned short IUINT16; 369 | #endif 370 | 371 | #ifndef __IINT16_DEFINED 372 | #define __IINT16_DEFINED 373 | typedef short IINT16; 374 | #endif 375 | 376 | #ifndef __IINT32_DEFINED 377 | #define __IINT32_DEFINED 378 | typedef ISTDINT32 IINT32; 379 | #endif 380 | 381 | #ifndef __IUINT32_DEFINED 382 | #define __IUINT32_DEFINED 383 | typedef ISTDUINT32 IUINT32; 384 | #endif 385 | 386 | #ifndef __IINT64_DEFINED 387 | #define __IINT64_DEFINED 388 | #if defined(_MSC_VER) || defined(__BORLANDC__) 389 | typedef __int64 IINT64; 390 | #else 391 | typedef long long IINT64; 392 | #endif 393 | #endif 394 | 395 | #ifndef __IUINT64_DEFINED 396 | #define __IUINT64_DEFINED 397 | #if defined(_MSC_VER) || defined(__BORLANDC__) 398 | typedef unsigned __int64 IUINT64; 399 | #else 400 | typedef unsigned long long IUINT64; 401 | #endif 402 | #endif 403 | 404 | 405 | /*====================================================================*/ 406 | /* IULONG/ILONG (ensure sizeof(iulong) == sizeof(void*)) */ 407 | /*====================================================================*/ 408 | #ifndef __IULONG_DEFINED 409 | #define __IULONG_DEFINED 410 | typedef ptrdiff_t ilong; 411 | typedef size_t iulong; 412 | #endif 413 | 414 | 415 | #ifdef __cplusplus 416 | extern "C" { 417 | #endif 418 | 419 | 420 | /*===================================================================*/ 421 | /* Cross-Platform Time Interface */ 422 | /*===================================================================*/ 423 | 424 | /* sleep in millisecond */ 425 | void isleep(unsigned long millisecond); 426 | 427 | /* get system time of day */ 428 | void itimeofday(long *sec, long *usec); 429 | 430 | /* get clock in millisecond */ 431 | unsigned long iclock(void); 432 | 433 | /* get clock in millisecond 64 */ 434 | IINT64 iclock64(void); 435 | 436 | /* real time usec (1/1000000 sec) clock */ 437 | IINT64 iclockrt(void); 438 | 439 | /* global millisecond clock value, updated by itimeofday */ 440 | volatile extern IINT64 itimeclock; 441 | 442 | 443 | /*===================================================================*/ 444 | /* Cross-Platform Threading Interface */ 445 | /*===================================================================*/ 446 | 447 | /* thread entry */ 448 | typedef void (*ITHREADPROC)(void *); 449 | 450 | /* create thread */ 451 | int ithread_create(ilong *id, ITHREADPROC fun, long stacksize, void *args); 452 | 453 | /* exit thread */ 454 | void ithread_exit(long retval); 455 | 456 | /* join thread */ 457 | int ithread_join(ilong id); 458 | 459 | /* detach thread */ 460 | int ithread_detach(ilong id); 461 | 462 | /* kill thread */ 463 | int ithread_kill(ilong id); 464 | 465 | /* CloseHandle in windows, do nothing in linux/unix */ 466 | int ithread_close(ilong id); 467 | 468 | /* thread once init, *control must be 0 */ 469 | void ithread_once(int *control, void (*run_once)(void)); 470 | 471 | 472 | /*===================================================================*/ 473 | /* Cross-Platform Mutex Interface */ 474 | /*===================================================================*/ 475 | #ifndef IMUTEX_TYPE 476 | 477 | #if (defined(WIN32) || defined(_WIN32)) 478 | #if ((!defined(_M_PPC)) && (!defined(_M_PPC_BE)) && (!defined(_XBOX))) 479 | #ifndef _WIN32_WINNT 480 | #define _WIN32_WINNT 0x0500 481 | #endif 482 | #ifndef WIN32_LEAN_AND_MEAN 483 | #define WIN32_LEAN_AND_MEAN 484 | #endif 485 | #include 486 | #else 487 | #ifndef _XBOX 488 | #define _XBOX 489 | #endif 490 | #include 491 | #endif 492 | 493 | #define IMUTEX_TYPE CRITICAL_SECTION 494 | #define IMUTEX_INIT(m) InitializeCriticalSection((CRITICAL_SECTION*)(m)) 495 | #define IMUTEX_DESTROY(m) DeleteCriticalSection((CRITICAL_SECTION*)(m)) 496 | #define IMUTEX_LOCK(m) EnterCriticalSection((CRITICAL_SECTION*)(m)) 497 | #define IMUTEX_UNLOCK(m) LeaveCriticalSection((CRITICAL_SECTION*)(m)) 498 | 499 | #elif defined(__unix) || defined(__unix__) || defined(__MACH__) 500 | #include 501 | #include 502 | #define IMUTEX_TYPE pthread_mutex_t 503 | #define IMUTEX_INIT(m) pthread_mutex_init((pthread_mutex_t*)(m), 0) 504 | #define IMUTEX_DESTROY(m) pthread_mutex_destroy((pthread_mutex_t*)(m)) 505 | #define IMUTEX_LOCK(m) pthread_mutex_lock((pthread_mutex_t*)(m)) 506 | #define IMUTEX_UNLOCK(m) pthread_mutex_unlock((pthread_mutex_t*)(m)) 507 | 508 | #else 509 | #define IMUTEX_TYPE int 510 | #define IMUTEX_INIT(m) { (*(m)) = (*(m)); } 511 | #define IMUTEX_DESTROY(m) { (*(m)) = (*(m)); } 512 | #define IMUTEX_LOCK(m) { (*(m)) = (*(m)); } 513 | #define IMUTEX_UNLOCK(m) { (*(m)) = (*(m)); } 514 | #endif 515 | 516 | #endif 517 | 518 | 519 | 520 | /*===================================================================*/ 521 | /* Cross-Platform Socket Interface */ 522 | /*===================================================================*/ 523 | 524 | /* create socket */ 525 | int isocket(int family, int type, int protocol); 526 | 527 | /* close socket */ 528 | int iclose(int sock); 529 | 530 | /* connect to */ 531 | int iconnect(int sock, const struct sockaddr *addr, int addrlen); 532 | 533 | /* shutdown */ 534 | int ishutdown(int sock, int mode); 535 | 536 | /* bind */ 537 | int ibind(int sock, const struct sockaddr *addr, int addrlen); 538 | 539 | /* listen */ 540 | int ilisten(int sock, int count); 541 | 542 | /* accept */ 543 | int iaccept(int sock, struct sockaddr *addr, int *addrlen); 544 | 545 | /* get errno */ 546 | int ierrno(void); 547 | 548 | /* send */ 549 | long isend(int sock, const void *buf, long size, int mode); 550 | 551 | /* receive */ 552 | long irecv(int sock, void *buf, long size, int mode); 553 | 554 | /* sendto */ 555 | long isendto(int sock, const void *buf, long size, int mode, 556 | const struct sockaddr *addr, int addrlen); 557 | 558 | /* recvfrom */ 559 | long irecvfrom(int sock, void *buf, long size, int mode, 560 | struct sockaddr *addr, int *addrlen); 561 | 562 | /* ioctl */ 563 | int iioctl(int sock, unsigned long cmd, unsigned long *argp); 564 | 565 | /* set socket option */ 566 | int isetsockopt(int sock, int level, int optname, const char *optval, 567 | int optlen); 568 | 569 | /* get socket option */ 570 | int igetsockopt(int sock, int level, int optname, char *optval, 571 | int *optlen); 572 | 573 | /* get socket name */ 574 | int isockname(int sock, struct sockaddr *addr, int *addrlen); 575 | 576 | /* get peer name */ 577 | int ipeername(int sock, struct sockaddr *addr, int *addrlen); 578 | 579 | 580 | /*===================================================================*/ 581 | /* Basic Function Definition */ 582 | /*===================================================================*/ 583 | 584 | /* poll event */ 585 | int ipollfd(int sock, int event, long millisec); 586 | 587 | /* iselect: fds(fd set), events(mask), revents(received events) */ 588 | int iselect(const int *fds, const int *events, int *revents, int count, 589 | long millisec, void *workmem); 590 | 591 | /* ipollfds: poll many sockets with iselect */ 592 | int ipollfds(const int *fds, const int *events, int *revents, int count, 593 | long millisec); 594 | 595 | /* ikeepalive: tcp keep alive option */ 596 | int ikeepalive(int sock, int keepcnt, int keepidle, int keepintvl); 597 | 598 | /* send all data */ 599 | int isendall(int sock, const void *buf, long size); 600 | 601 | /* try to receive all data */ 602 | int irecvall(int sock, void *buf, long size); 603 | 604 | /* format error string */ 605 | char *ierrstr(int errnum, char *msg, int size); 606 | 607 | /* get host address */ 608 | int igethostaddr(struct in_addr *addrs, int count); 609 | 610 | /* setup sockaddr */ 611 | struct sockaddr* isockaddr_set(struct sockaddr *a, unsigned long ip, int p); 612 | 613 | /* set address of sockaddr */ 614 | void isockaddr_set_ip(struct sockaddr *a, unsigned long ip); 615 | 616 | /* get address of sockaddr */ 617 | unsigned long isockaddr_get_ip(const struct sockaddr *a); 618 | 619 | /* set port of sockaddr */ 620 | void isockaddr_set_port(struct sockaddr *a, int port); 621 | 622 | /* get port of sockaddr */ 623 | int isockaddr_get_port(const struct sockaddr *a); 624 | 625 | /* set family */ 626 | void isockaddr_set_family(struct sockaddr *a, int family); 627 | 628 | /* get family */ 629 | int isockaddr_get_family(const struct sockaddr *a); 630 | 631 | /* set text to ip */ 632 | int isockaddr_set_ip_text(struct sockaddr *a, const char *text); 633 | 634 | /* get ip text */ 635 | char *isockaddr_get_ip_text(const struct sockaddr *a, char *text); 636 | 637 | /* make up address */ 638 | struct sockaddr *isockaddr_makeup(struct sockaddr *a, const char *ip, int p); 639 | 640 | /* convert address to text */ 641 | char *isockaddr_str(const struct sockaddr *a, char *text); 642 | 643 | /* compare two addresses */ 644 | int isockaddr_cmp(const struct sockaddr *a, const struct sockaddr *b); 645 | 646 | 647 | /*===================================================================*/ 648 | /* Memory Hook Definition */ 649 | /*===================================================================*/ 650 | 651 | /* internal malloc of this module */ 652 | void* ikmalloc(size_t size); 653 | 654 | /* internal free of this module */ 655 | void ikfree(void *ptr); 656 | 657 | /* set ikmalloc / ikfree internal implementation */ 658 | void ikmset(void *ikmalloc_func, void *ikfree_func); 659 | 660 | 661 | /*===================================================================*/ 662 | /* Simple Assistant Function */ 663 | /*===================================================================*/ 664 | 665 | /* start network */ 666 | int isocket_init(void); 667 | 668 | /* socket option */ 669 | int isocket_option(int fd, int option, int enable); 670 | 671 | /* enable option */ 672 | int isocket_enable(int fd, int mode); 673 | 674 | /* enable option */ 675 | int isocket_disable(int fd, int mode); 676 | 677 | /* open a dgram */ 678 | int isocket_udp_open(const struct sockaddr *addr, int addrlen, int flags); 679 | 680 | /* check tcp is established ?, returns 1/true, 0/false, -1/error */ 681 | int isocket_tcp_estab(int sock); 682 | 683 | /* set recv buf and send buf */ 684 | int isocket_set_buffer(int sock, long recvbuf_size, long sendbuf_size); 685 | 686 | /* create socket pair */ 687 | int isocket_pair(int fds[2], int cloexec); 688 | 689 | /* try can listen on windows firewall */ 690 | int isocket_try_firewall(void); 691 | 692 | 693 | /*===================================================================*/ 694 | /* Cross-Platform Poll Interface */ 695 | /*===================================================================*/ 696 | #define IDEVICE_AUTO 0 697 | #define IDEVICE_SELECT 1 698 | #define IDEVICE_POLL 2 699 | #define IDEVICE_KQUEUE 3 700 | #define IDEVICE_EPOLL 4 701 | #define IDEVICE_DEVPOLL 5 702 | #define IDEVICE_POLLSET 6 703 | #define IDEVICE_RTSIG 7 704 | #define IDEVICE_WINCP 8 705 | 706 | #ifndef IPOLL_IN 707 | #define IPOLL_IN 1 708 | #endif 709 | 710 | #ifndef IPOLL_OUT 711 | #define IPOLL_OUT 2 712 | #endif 713 | 714 | #ifndef IPOLL_ERR 715 | #define IPOLL_ERR 4 716 | #endif 717 | 718 | typedef void * ipolld; 719 | 720 | /* init poll device */ 721 | int ipoll_init(int device); 722 | 723 | /* quit poll device */ 724 | int ipoll_quit(void); 725 | 726 | /* name of poll device */ 727 | const char *ipoll_name(void); 728 | 729 | /* create poll descriptor */ 730 | int ipoll_create(ipolld *ipd, int param); 731 | 732 | /* delete poll descriptor */ 733 | int ipoll_delete(ipolld ipd); 734 | 735 | /* add file/socket into poll descriptor */ 736 | int ipoll_add(ipolld ipd, int fd, int mask, void *udata); 737 | 738 | /* delete file/socket from poll descriptor */ 739 | int ipoll_del(ipolld ipd, int fd); 740 | 741 | /* set file event mask in a poll descriptor */ 742 | int ipoll_set(ipolld ipd, int fd, int mask); 743 | 744 | /* wait for events coming */ 745 | int ipoll_wait(ipolld ipd, int millisecond); 746 | 747 | /* query one event: loop call it until it returns non-zero */ 748 | int ipoll_event(ipolld ipd, int *fd, int *event, void **udata); 749 | 750 | 751 | 752 | /*===================================================================*/ 753 | /* Condition Variable Cross-Platform Interface */ 754 | /*===================================================================*/ 755 | struct iConditionVariable; 756 | typedef struct iConditionVariable iConditionVariable; 757 | 758 | iConditionVariable *iposix_cond_new(void); 759 | 760 | void iposix_cond_delete(iConditionVariable *cond); 761 | 762 | /* sleep and wait, returns 1 for been waked up, 0 for timeout */ 763 | int iposix_cond_sleep_cs_time(iConditionVariable *cond, 764 | IMUTEX_TYPE *mutex, unsigned long millisec); 765 | 766 | /* sleep and wait, returns 1 for been waked up, 0 for timeout */ 767 | int iposix_cond_sleep_cs(iConditionVariable *cond, 768 | IMUTEX_TYPE *mutex); 769 | 770 | /* wake up one sleeped thread */ 771 | void iposix_cond_wake(iConditionVariable *cond); 772 | 773 | /* wake up all sleeped thread */ 774 | void iposix_cond_wake_all(iConditionVariable *cond); 775 | 776 | 777 | /*===================================================================*/ 778 | /* Event Cross-Platform Interface */ 779 | /*===================================================================*/ 780 | struct iEventPosix; 781 | typedef struct iEventPosix iEventPosix; 782 | 783 | #define IEVENT_INFINITE 0xffffffff 784 | 785 | iEventPosix *iposix_event_new(void); 786 | 787 | void iposix_event_delete(iEventPosix *event); 788 | 789 | /* set signal to 1 */ 790 | void iposix_event_set(iEventPosix *event); 791 | 792 | /* set signal to 0 */ 793 | void iposix_event_reset(iEventPosix *event); 794 | 795 | /* sleep until signal is 1(returns 1), or timeout(returns 0) */ 796 | int iposix_event_wait(iEventPosix *event, unsigned long millisec); 797 | 798 | 799 | /*===================================================================*/ 800 | /* ReadWriteLock Cross-Platform Interface */ 801 | /*===================================================================*/ 802 | struct iRwLockPosix; 803 | typedef struct iRwLockPosix iRwLockPosix; 804 | 805 | iRwLockPosix *iposix_rwlock_new(void); 806 | 807 | void iposix_rwlock_delete(iRwLockPosix *rwlock); 808 | 809 | void iposix_rwlock_w_lock(iRwLockPosix *rwlock); 810 | 811 | void iposix_rwlock_w_unlock(iRwLockPosix *rwlock); 812 | 813 | void iposix_rwlock_r_lock(iRwLockPosix *rwlock); 814 | 815 | void iposix_rwlock_r_unlock(iRwLockPosix *rwlock); 816 | 817 | 818 | /*===================================================================*/ 819 | /* Threading Cross-Platform Interface */ 820 | /*===================================================================*/ 821 | struct iPosixThread; 822 | typedef struct iPosixThread iPosixThread; 823 | 824 | /* Thread Entry Point, it will be called repeatly after started until 825 | it returns zero, or iposix_thread_set_notalive is called. */ 826 | typedef int (*iPosixThreadFun)(void *obj); 827 | 828 | /* create a new thread object */ 829 | iPosixThread *iposix_thread_new(iPosixThreadFun target, void *obj, 830 | const char *name); 831 | 832 | /* delete a thread object: (IMPORTANT!!) thread must stop before this */ 833 | void iposix_thread_delete(iPosixThread *thread); 834 | 835 | 836 | /* start thread, each thread object can only have one running thread at 837 | the same time. if it has started already, returns nonezero for error */ 838 | int iposix_thread_start(iPosixThread *thread); 839 | 840 | /* join thread, wait the thread finish */ 841 | int iposix_thread_join(iPosixThread *thread, unsigned long millisec); 842 | 843 | /* kill thread: very dangerous */ 844 | int iposix_thread_cancel(iPosixThread *thread); 845 | 846 | /* stop repeatly calling iPosixThreadFun, if thread is NULL, use current */ 847 | void iposix_thread_set_notalive(iPosixThread *thread); 848 | 849 | /* returns 1 for running, 0 for not running */ 850 | int iposix_thread_is_running(const iPosixThread *thread); 851 | 852 | 853 | #define IPOSIX_THREAD_PRIO_LOW 0 854 | #define IPOSIX_THREAD_PRIO_NORMAL 1 855 | #define IPOSIX_THREAD_PRIO_HIGH 2 856 | #define IPOSIX_THREAD_PRIO_HIGHEST 3 857 | #define IPOSIX_THREAD_PRIO_REALTIME 4 858 | 859 | /* set thread priority, the thread must not be started */ 860 | int iposix_thread_set_priority(iPosixThread *thread, int priority); 861 | 862 | /* set stack size, the thread must not be started */ 863 | int iposix_thread_set_stack(iPosixThread *thread, int stacksize); 864 | 865 | /* set cpu mask affinity, the thread must be started (supports win/linux)*/ 866 | int iposix_thread_affinity(iPosixThread *thread, unsigned int cpumask); 867 | 868 | 869 | /* set signal: if thread is NULL, current thread object is used */ 870 | void iposix_thread_set_signal(iPosixThread *thread, int sig); 871 | 872 | /* get signal: if thread is NULL, current thread object is used */ 873 | int iposix_thread_get_signal(iPosixThread *thread); 874 | 875 | /* get name: if thread is NULL, current thread object is used */ 876 | const char *iposix_thread_get_name(const iPosixThread *thread); 877 | 878 | 879 | /*===================================================================*/ 880 | /* Timer Cross-Platform Interface */ 881 | /*===================================================================*/ 882 | struct iPosixTimer; 883 | typedef struct iPosixTimer iPosixTimer; 884 | 885 | 886 | /* create a new timer */ 887 | iPosixTimer *iposix_timer_new(void); 888 | 889 | /* delete a timer */ 890 | void iposix_timer_delete(iPosixTimer *timer); 891 | 892 | /* start timer, delay is millisec, returns zero for success */ 893 | int iposix_timer_start(iPosixTimer *timer, unsigned long delay, 894 | int periodic); 895 | 896 | /* stop timer */ 897 | void iposix_timer_stop(iPosixTimer *timer); 898 | 899 | /* wait, returns 1 for timer, otherwise for timeout */ 900 | int iposix_timer_wait_time(iPosixTimer *timer, unsigned long millisec); 901 | 902 | /* wait infinite */ 903 | int iposix_timer_wait(iPosixTimer *timer); 904 | 905 | /* timer signal set */ 906 | int iposix_timer_set(iPosixTimer *timer); 907 | 908 | /* timer signal reset */ 909 | int iposix_timer_reset(iPosixTimer *timer); 910 | 911 | 912 | /*===================================================================*/ 913 | /* Semaphore Cross-Platform Interface */ 914 | /*===================================================================*/ 915 | struct iPosixSemaphore; 916 | typedef struct iPosixSemaphore iPosixSemaphore; 917 | 918 | /* semaphore callback when value changed */ 919 | typedef void (*iPosixSemHook)(iulong changed, void *arg); 920 | 921 | /* create a semaphore with a maximum count, and initial count is 0. */ 922 | iPosixSemaphore* iposix_sem_new(iulong maximum); 923 | 924 | /* delete a semaphore */ 925 | void iposix_sem_delete(iPosixSemaphore *sem); 926 | 927 | /* increase count of the semaphore, returns how much it increased */ 928 | iulong iposix_sem_post(iPosixSemaphore *sem, iulong count, 929 | unsigned long millisec, iPosixSemHook hook, void *arg); 930 | 931 | /* decrease count of the semaphore, returns how much it decreased */ 932 | iulong iposix_sem_wait(iPosixSemaphore *sem, iulong count, 933 | unsigned long millisec, iPosixSemHook hook, void *arg); 934 | 935 | /* returns how much it can be decreased */ 936 | iulong iposix_sem_peek(iPosixSemaphore *sem, iulong count, 937 | unsigned long millisec, iPosixSemHook hook, void *arg); 938 | 939 | /* get the count value of the specified semaphore */ 940 | iulong iposix_sem_value(iPosixSemaphore *sem); 941 | 942 | 943 | /*===================================================================*/ 944 | /* DateTime Cross-Platform Interface */ 945 | /*===================================================================*/ 946 | 947 | /* GetSystemTime (utc=1) or GetLocalTime (utc=0) */ 948 | void iposix_datetime(int utc, IINT64 *BCD); 949 | 950 | /* macros to unpack posix time */ 951 | #define iposix_time_year(bcd) ((int)(((bcd) >> 48) & 0xffff)) 952 | #define iposix_time_mon(bcd) ((int)(((bcd) >> 35) & 0xf)) 953 | #define iposix_time_mday(bcd) ((int)(((bcd) >> 30) & 31)) 954 | #define iposix_time_wday(bcd) ((int)(((bcd) >> 27) & 7)) 955 | #define iposix_time_hour(bcd) ((int)(((bcd) >> 22) & 31)) 956 | #define iposix_time_min(bcd) ((int)(((bcd) >> 16) & 63)) 957 | #define iposix_time_sec(bcd) ((int)(((bcd) >> 10) & 63)) 958 | #define iposix_time_ms(bcd) ((int)(((bcd) >> 0) & 1023)) 959 | 960 | 961 | /* make up date time */ 962 | void iposix_date_make(IINT64 *BCD, int year, int mon, int mday, int wday, 963 | int hour, int min, int sec, int ms); 964 | 965 | /* format time */ 966 | char *iposix_date_format(const char *fmt, IINT64 datetime, char *dst); 967 | 968 | 969 | /*===================================================================*/ 970 | /* IPV4/IPV6 interfaces */ 971 | /*===================================================================*/ 972 | 973 | /* convert presentation format to network format */ 974 | /* another inet_pton returns 0 for success, supports AF_INET/AF_INET6 */ 975 | int isockaddr_pton(int af, const char *src, void *dst); 976 | 977 | /* convert network format to presentation format */ 978 | /* another inet_ntop, supports AF_INET/AF_INET6 */ 979 | const char *isockaddr_ntop(int af, const void *src, char *dst, size_t size); 980 | 981 | 982 | 983 | #ifdef __cplusplus 984 | } 985 | #endif 986 | 987 | 988 | #endif 989 | 990 | 991 | 992 | -------------------------------------------------------------------------------- /system/inetcode.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * inetcode.c - core interface of socket operation 4 | * skywind3000 (at) gmail.com, 2006-2016 5 | * 6 | * NOTE: 7 | * for more information, please see the readme file 8 | * 9 | **********************************************************************/ 10 | 11 | #ifndef __INETCODE_H__ 12 | #define __INETCODE_H__ 13 | 14 | #include "inetbase.h" 15 | #include "imemdata.h" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /*===================================================================*/ 26 | /* Network Information */ 27 | /*===================================================================*/ 28 | #define IMAX_HOSTNAME 256 29 | #define IMAX_ADDRESS 64 30 | 31 | /* host name */ 32 | extern char ihostname[]; 33 | 34 | /* host address list */ 35 | extern struct in_addr ihost_addr[]; 36 | 37 | /* host ip address string list */ 38 | extern char *ihost_ipstr[]; 39 | 40 | /* host names */ 41 | extern char *ihost_names[]; 42 | 43 | /* host address count */ 44 | extern int ihost_addr_num; 45 | 46 | /* refresh address list */ 47 | int isocket_update_address(int resolvname); 48 | 49 | 50 | 51 | /*===================================================================*/ 52 | /* CAsyncSock */ 53 | /*===================================================================*/ 54 | struct CAsyncSock 55 | { 56 | IUINT32 time; /* timeout */ 57 | int fd; /* socket fd */ 58 | int state; /* CLOSED/CONNECTING/ESTABLISHED */ 59 | long hid; /* hid */ 60 | long tag; /* tag */ 61 | int error; /* errno value */ 62 | int header; /* header mode (0-13) */ 63 | int mask; /* poll event mask */ 64 | int mode; /* socket mode */ 65 | int ipv6; /* 0:ipv4, 1:ipv6 */ 66 | int flags; /* flag bits */ 67 | char *buffer; /* internal working buffer */ 68 | char *external; /* external working buffer */ 69 | long bufsize; /* working buffer size */ 70 | long maxsize; /* max packet size */ 71 | long limited; /* buffer limited */ 72 | int rc4_send_x; /* rc4 encryption variable */ 73 | int rc4_send_y; /* rc4 encryption variable */ 74 | int rc4_recv_x; /* rc4 encryption variable */ 75 | int rc4_recv_y; /* rc4 encryption variable */ 76 | void *filter; /* filter function */ 77 | void *object; /* filter object */ 78 | int closing; /* pending close */ 79 | int exitcode; /* exit code */ 80 | int protocol; /* protocol */ 81 | struct ILISTHEAD node; /* list node */ 82 | struct ILISTHEAD pending; /* waiting close */ 83 | struct IMSTREAM linemsg; /* line buffer */ 84 | struct IMSTREAM sendmsg; /* send buffer */ 85 | struct IMSTREAM recvmsg; /* recv buffer */ 86 | unsigned char rc4_send_box[256]; 87 | unsigned char rc4_recv_box[256]; 88 | }; 89 | 90 | 91 | #ifndef ITMH_WORDLSB 92 | #define ITMH_WORDLSB 0 /* header: 2 bytes LSB */ 93 | #define ITMH_WORDMSB 1 /* header: 2 bytes MSB */ 94 | #define ITMH_DWORDLSB 2 /* header: 4 bytes LSB */ 95 | #define ITMH_DWORDMSB 3 /* header: 4 bytes MSB */ 96 | #define ITMH_BYTELSB 4 /* header: 1 byte LSB */ 97 | #define ITMH_BYTEMSB 5 /* header: 1 byte MSB */ 98 | #define ITMH_EWORDLSB 6 /* header: 2 bytes LSB (exclude self) */ 99 | #define ITMH_EWORDMSB 7 /* header: 2 bytes MSB (exclude self) */ 100 | #define ITMH_EDWORDLSB 8 /* header: 4 bytes LSB (exclude self) */ 101 | #define ITMH_EDWORDMSB 9 /* header: 4 bytes MSB (exclude self) */ 102 | #define ITMH_EBYTELSB 10 /* header: 1 byte LSB (exclude self) */ 103 | #define ITMH_EBYTEMSB 11 /* header: 1 byte MSB (exclude self) */ 104 | #define ITMH_DWORDMASK 12 /* header: 4 bytes LSB (self and mask) */ 105 | #define ITMH_RAWDATA 13 /* header: raw data */ 106 | #define ITMH_LINESPLIT 14 /* header: '\n' split */ 107 | #endif 108 | 109 | #define ASYNC_SOCK_STATE_CLOSED 0 110 | #define ASYNC_SOCK_STATE_CONNECTING 1 111 | #define ASYNC_SOCK_STATE_ESTAB 2 112 | 113 | typedef struct CAsyncSock CAsyncSock; 114 | 115 | 116 | /* create a new asyncsock */ 117 | void async_sock_init(CAsyncSock *asyncsock, struct IMEMNODE *nodes); 118 | 119 | /* delete asyncsock */ 120 | void async_sock_destroy(CAsyncSock *asyncsock); 121 | 122 | 123 | /* connect to remote address */ 124 | int async_sock_connect(CAsyncSock *asyncsock, const struct sockaddr *remote, 125 | int addrlen, int header); 126 | 127 | /* assign a new socket */ 128 | int async_sock_assign(CAsyncSock *asyncsock, int sock, int header); 129 | 130 | /* close socket */ 131 | void async_sock_close(CAsyncSock *asyncsock); 132 | 133 | 134 | /* get state */ 135 | int async_sock_state(const CAsyncSock *asyncsock); 136 | 137 | /* get fd */ 138 | int async_sock_fd(const CAsyncSock *asyncsock); 139 | 140 | /* get how many bytes remain in the send buffer */ 141 | long async_sock_remain(const CAsyncSock *asyncsock); 142 | 143 | 144 | /* send data */ 145 | long async_sock_send(CAsyncSock *asyncsock, const void *ptr, 146 | long size, int mask); 147 | 148 | /** 149 | * recv vector: returns packet size, -1 for not enough data, -2 for 150 | * buffer size too small, -3 for packet size error, -4 for size over limit, 151 | * returns packet size if ptr equals NULL. 152 | */ 153 | long async_sock_recv(CAsyncSock *asyncsock, void *ptr, int size); 154 | 155 | 156 | /* send vector */ 157 | long async_sock_send_vector(CAsyncSock *asyncsock, 158 | const void * const vecptr[], 159 | const long veclen[], int count, int mask); 160 | 161 | /** 162 | * recv vector: returns packet size, -1 for not enough data, -2 for 163 | * buffer size too small, -3 for packet size error, -4 for size over limit, 164 | * returns packet size if vecptr equals NULL. 165 | */ 166 | long async_sock_recv_vector(CAsyncSock *asyncsock, void* const vecptr[], 167 | const long veclen[], int count); 168 | 169 | 170 | /* update */ 171 | int async_sock_update(CAsyncSock *asyncsock, int what); 172 | 173 | /* process */ 174 | void async_sock_process(CAsyncSock *asyncsock); 175 | 176 | 177 | /* set send cryption key */ 178 | void async_sock_rc4_set_skey(CAsyncSock *asyncsock, 179 | const unsigned char *key, int keylen); 180 | 181 | /* set recv cryption key */ 182 | void async_sock_rc4_set_rkey(CAsyncSock *asyncsock, 183 | const unsigned char *key, int keylen); 184 | 185 | /* set nodelay */ 186 | int async_sock_nodelay(CAsyncSock *asyncsock, int nodelay); 187 | 188 | /* set buf size */ 189 | int async_sock_sys_buffer(CAsyncSock *asyncsock, long rcvbuf, long sndbuf); 190 | 191 | /* set keepalive */ 192 | int async_sock_keepalive(CAsyncSock *asyncsock, int keepcnt, int keepidle, 193 | int keepintvl); 194 | 195 | 196 | 197 | /*===================================================================*/ 198 | /* CAsyncCore */ 199 | /*===================================================================*/ 200 | struct CAsyncCore; 201 | typedef struct CAsyncCore CAsyncCore; 202 | 203 | #define ASYNC_CORE_EVT_NEW 0 /* new: (hid, tag) */ 204 | #define ASYNC_CORE_EVT_CLOSE 1 /* close: (hid, tag) */ 205 | #define ASYNC_CORE_EVT_ESTAB 2 /* estab: (hid, tag) */ 206 | #define ASYNC_CORE_EVT_DATA 3 /* data: (hid, tag) */ 207 | #define ASYNC_CORE_EVT_PROGRESS 4 /* output progress: (hid, tag) */ 208 | #define ASYNC_CORE_EVT_DGRAM 5 /* raw fd event: (hid, tag) */ 209 | #define ASYNC_CORE_EVT_POST 6 /* msg from async_core_post */ 210 | #define ASYNC_CORE_EVT_EXTEND 7 /* user defined event */ 211 | 212 | #define ASYNC_CORE_NODE_IN 1 /* accepted node */ 213 | #define ASYNC_CORE_NODE_OUT 2 /* connected out node */ 214 | #define ASYNC_CORE_NODE_LISTEN4 3 /* ipv4 listener */ 215 | #define ASYNC_CORE_NODE_LISTEN6 4 /* ipv6 listener */ 216 | #define ASYNC_CORE_NODE_ASSIGN 5 /* assigned fd ipv4 */ 217 | #define ASYNC_CORE_NODE_DGRAM 6 /* raw dgram fd */ 218 | 219 | #ifndef ASYNC_CORE_HID_BITS 220 | #define ASYNC_CORE_HID_BITS 16 /* size shift */ 221 | #endif 222 | 223 | #define ASYNC_CORE_HID_SIZE (1 << (ASYNC_CORE_HID_BITS)) 224 | #define ASYNC_CORE_HID_MASK ((ASYNC_CORE_HID_SIZE) - 1) 225 | #define ASYNC_CORE_HID_INDEX(hid) ((hid) & ASYNC_CORE_HID_MASK) 226 | 227 | 228 | 229 | /* Remote IP Validator: returns 1 to accept it, 0 to reject */ 230 | typedef int (*CAsyncValidator)(const struct sockaddr *remote, int len, 231 | CAsyncCore *core, long listenhid, void *user); 232 | 233 | /* Message Filter: can be installed to connection */ 234 | typedef int (*CAsyncFilter)(CAsyncCore *core, void *object, long hid, 235 | int cmd, const void *data, long size); 236 | 237 | /** 238 | * create CAsyncCore object: 239 | * if (flags & 1) disable lock, if (flags & 2) disable notify 240 | */ 241 | CAsyncCore* async_core_new(int flags); 242 | 243 | /* delete async core */ 244 | void async_core_delete(CAsyncCore *core); 245 | 246 | 247 | /** 248 | * wait for events for millisec ms. and process events, 249 | * if millisec equals zero, no wait. 250 | */ 251 | void async_core_wait(CAsyncCore *core, IUINT32 millisec); 252 | 253 | /* wake async_core_wait up, returns zero for success */ 254 | int async_core_notify(CAsyncCore *core); 255 | 256 | /** 257 | * read events, returns data length of the message, 258 | * and returns -1 for no event, -2 for buffer size too small, 259 | * returns data size when data equals NULL. 260 | */ 261 | long async_core_read(CAsyncCore *core, int *event, long *wparam, 262 | long *lparam, void *data, long size); 263 | 264 | 265 | /* send data to given hid */ 266 | long async_core_send(CAsyncCore *core, long hid, const void *ptr, long len); 267 | 268 | /* close given hid */ 269 | int async_core_close(CAsyncCore *core, long hid, int code); 270 | 271 | /* send vector */ 272 | long async_core_send_vector(CAsyncCore *core, long hid, 273 | const void * const vecptr[], 274 | const long veclen[], int count, int mask); 275 | 276 | 277 | /* new connection to the target address, returns hid */ 278 | long async_core_new_connect(CAsyncCore *core, const struct sockaddr *addr, 279 | int addrlen, int header); 280 | 281 | /* new listener, returns hid */ 282 | long async_core_new_listen(CAsyncCore *core, const struct sockaddr *addr, 283 | int addrlen, int header); 284 | 285 | /* new assign to a existing socket, returns hid */ 286 | long async_core_new_assign(CAsyncCore *core, int fd, int header, int estab); 287 | 288 | /* new dgram fd: mask=0:none, 1:read, 2:write, 3:r+w */ 289 | long async_core_new_dgram(CAsyncCore *core, const struct sockaddr *addr, 290 | int addrlen, int mode); 291 | 292 | 293 | /* queue an ASYNC_CORE_EVT_POST event and wake async_core_wait up */ 294 | int async_core_post(CAsyncCore *core, long wparam, long lparam, 295 | const void *data, long size); 296 | 297 | /* queue an arbitrary event and wake async_core_wait up */ 298 | int async_core_push(CAsyncCore *core, int event, long wparam, long lparam, 299 | const void *data, long size); 300 | 301 | /* get node mode: ASYNC_CORE_NODE_IN/OUT/LISTEN4/LISTEN6/ASSIGN */ 302 | int async_core_get_mode(const CAsyncCore *core, long hid); 303 | 304 | /* returns connection tag, -1 for hid not exist */ 305 | long async_core_get_tag(const CAsyncCore *core, long hid); 306 | 307 | /* set connection tag */ 308 | void async_core_set_tag(CAsyncCore *core, long hid, long tag); 309 | 310 | /* get send queue size */ 311 | long async_core_remain(const CAsyncCore *core, long hid); 312 | 313 | /* set default buffer limit and max packet size */ 314 | void async_core_limit(CAsyncCore *core, long limited, long maxsize); 315 | 316 | /* set disable read polling event: 1/on, 0/off */ 317 | int async_core_disable(CAsyncCore *core, long hid, int value); 318 | 319 | 320 | /* get first node */ 321 | long async_core_node_head(const CAsyncCore *core); 322 | 323 | /* get next node */ 324 | long async_core_node_next(const CAsyncCore *core, long hid); 325 | 326 | /* get prev node */ 327 | long async_core_node_prev(const CAsyncCore *core, long hid); 328 | 329 | 330 | #define ASYNC_CORE_OPTION_NODELAY 1 331 | #define ASYNC_CORE_OPTION_REUSEADDR 2 332 | #define ASYNC_CORE_OPTION_KEEPALIVE 3 333 | #define ASYNC_CORE_OPTION_SYSSNDBUF 4 334 | #define ASYNC_CORE_OPTION_SYSRCVBUF 5 335 | #define ASYNC_CORE_OPTION_LIMITED 6 336 | #define ASYNC_CORE_OPTION_MAXSIZE 7 337 | #define ASYNC_CORE_OPTION_PROGRESS 8 338 | #define ASYNC_CORE_OPTION_GETFD 9 339 | #define ASYNC_CORE_OPTION_REUSEPORT 10 340 | #define ASYNC_CORE_OPTION_UNIXREUSE 11 341 | #define ASYNC_CORE_OPTION_SENSITIVE 12 342 | #define ASYNC_CORE_OPTION_MASKSET 13 343 | #define ASYNC_CORE_OPTION_MASKGET 14 344 | #define ASYNC_CORE_OPTION_MASKADD 15 345 | #define ASYNC_CORE_OPTION_MASKDEL 16 346 | #define ASYNC_CORE_OPTION_SHUTDOWN 17 347 | #define ASYNC_CORE_OPTION_GET_HEADER 18 348 | #define ASYNC_CORE_OPTION_GET_PROTOCOL 19 349 | 350 | /* set connection socket option */ 351 | int async_core_option(CAsyncCore *core, long hid, int opt, long value); 352 | 353 | #define ASYNC_CORE_STATUS_STATE 0 354 | #define ASYNC_CORE_STATUS_IPV6 1 355 | #define ASYNC_CORE_STATUS_ESTAB 2 356 | 357 | /* get connection socket status */ 358 | long async_core_status(CAsyncCore *core, long hid, int opt); 359 | 360 | /* set connection rc4 send key */ 361 | int async_core_rc4_set_skey(CAsyncCore *core, long hid, 362 | const unsigned char *key, int keylen); 363 | 364 | /* set connection rc4 recv key */ 365 | int async_core_rc4_set_rkey(CAsyncCore *core, long hid, 366 | const unsigned char *key, int keylen); 367 | 368 | /* set remote ip validator */ 369 | void async_core_firewall(CAsyncCore *core, CAsyncValidator v, void *user); 370 | 371 | 372 | #define ASYNC_CORE_FILTER_INIT 0 /* called after install */ 373 | #define ASYNC_CORE_FILTER_RELEASE 1 /* called before delete */ 374 | #define ASYNC_CORE_FILTER_WRITE 2 /* upper level data send */ 375 | #define ASYNC_CORE_FILTER_INPUT 3 /* lower level data arrival */ 376 | 377 | /* setup filter */ 378 | void async_core_filter(CAsyncCore *core, long hid, 379 | CAsyncFilter filter, void *object); 380 | 381 | #define ASYNC_CORE_DISPATCH_PUSH 0 382 | #define ASYNC_CORE_DISPATCH_SEND 1 383 | #define ASYNC_CORE_DISPATCH_CLOSE 2 384 | 385 | /* dispatch: for filter only, don't call outside the filter */ 386 | int async_core_dispatch(CAsyncCore *core, long hid, int cmd, 387 | const void *ptr, long size); 388 | 389 | /* Filter Factory: async_core_protocol() will use this to create filter */ 390 | typedef CAsyncFilter (*CAsyncFactory)(CAsyncCore *core, long hid, 391 | int protocol, void **object); 392 | 393 | /* register options */ 394 | #define ASYNC_CORE_REG_GET_PARENT 0 395 | #define ASYNC_CORE_REG_SET_PARENT 1 396 | #define ASYNC_CORE_REG_GET_FACTORY 2 397 | #define ASYNC_CORE_REG_SET_FACTORY 3 398 | 399 | /* read/write registry */ 400 | void* async_core_registry(CAsyncCore *core, int op, int value, void *ptr); 401 | 402 | /* set protocol: use factory to create a CAsyncFilter and install it */ 403 | int async_core_protocol(CAsyncCore *core, long hid, int protocol); 404 | 405 | /* set timeout */ 406 | void async_core_timeout(CAsyncCore *core, long seconds); 407 | 408 | /* getsockname */ 409 | int async_core_sockname(const CAsyncCore *core, long hid, 410 | struct sockaddr *addr, int *size); 411 | 412 | /* getpeername */ 413 | int async_core_peername(const CAsyncCore *core, long hid, 414 | struct sockaddr *addr, int *size); 415 | 416 | /* get fd count */ 417 | long async_core_nfds(const CAsyncCore *core); 418 | 419 | 420 | 421 | /*===================================================================*/ 422 | /* Thread Safe Queue */ 423 | /*===================================================================*/ 424 | struct iQueueSafe; 425 | typedef struct iQueueSafe iQueueSafe; 426 | 427 | /* new queue */ 428 | iQueueSafe *queue_safe_new(iulong maxsize); 429 | 430 | /* delete queue */ 431 | void queue_safe_delete(iQueueSafe *q); 432 | 433 | /* put obj into queue, returns 1 for success, 0 for full */ 434 | int queue_safe_put(iQueueSafe *q, void *ptr, unsigned long millisec); 435 | 436 | /* get obj from queue, returns 1 for success, 0 for empty */ 437 | int queue_safe_get(iQueueSafe *q, void **ptr, unsigned long millisec); 438 | 439 | /* peek obj from queue, returns 1 for success, 0 for empty */ 440 | int queue_safe_peek(iQueueSafe *q, void **ptr, unsigned long millisec); 441 | 442 | 443 | /* put many objs into queue, returns how many obj have entered the queue */ 444 | int queue_safe_put_vec(iQueueSafe *q, const void * const vecptr[], 445 | int count, unsigned long millisec); 446 | 447 | /* get objs from queue, returns how many obj have been fetched */ 448 | int queue_safe_get_vec(iQueueSafe *q, void *vecptr[], int count, 449 | unsigned long millisec); 450 | 451 | /* peek objs from queue, returns how many obj have been peeken */ 452 | int queue_safe_peek_vec(iQueueSafe *q, void *vecptr[], int count, 453 | unsigned long millisec); 454 | 455 | /* get size */ 456 | iulong queue_safe_size(iQueueSafe *q); 457 | 458 | 459 | 460 | /*-------------------------------------------------------------------*/ 461 | /* PROXY */ 462 | /*-------------------------------------------------------------------*/ 463 | struct ISOCKPROXY 464 | { 465 | int type; /* http? sock4? sock5? */ 466 | int next; /* state */ 467 | int socket; /* socket */ 468 | int offset; /* data pointer offset */ 469 | int totald; /* total send */ 470 | int authen; /* wheather auth */ 471 | int errorc; /* error code */ 472 | int block; /* is blocking */ 473 | struct sockaddr remote; /* remote address */ 474 | struct sockaddr proxyd; /* proxy address */ 475 | char data[1024]; /* buffer */ 476 | }; 477 | 478 | 479 | #define ISOCKPROXY_TYPE_NONE 0 /* none proxy */ 480 | #define ISOCKPROXY_TYPE_HTTP 1 /* http proxy */ 481 | #define ISOCKPROXY_TYPE_SOCKS4 2 /* socks4 */ 482 | #define ISOCKPROXY_TYPE_SOCKS5 3 /* socks5 */ 483 | 484 | /** 485 | * initialize ISOCKPROXY 486 | * type is: ISOCKPROXY_TYPE_NONE, ISOCKPROXY_TYPE_HTTP, 487 | * ISOCKPROXY_TYPE_SOCKS4, ISOCKPROXY_TYPE_SOCKS5 488 | */ 489 | int iproxy_init(struct ISOCKPROXY *proxy, int sock, int type, 490 | const struct sockaddr *remote, const struct sockaddr *proxyd, 491 | const char *user, const char *pass, int mode); 492 | 493 | /** 494 | * update state 495 | * returns 1 for success, below zero for error, zero for try again later 496 | */ 497 | int iproxy_process(struct ISOCKPROXY *proxy); 498 | 499 | 500 | /*===================================================================*/ 501 | /* loop running per fix interval */ 502 | /*===================================================================*/ 503 | 504 | void ifix_interval_start(IUINT32* time); 505 | 506 | void ifix_interval_running(IUINT32 *time, long interval); 507 | 508 | #ifdef __cplusplus 509 | } 510 | #endif 511 | 512 | 513 | 514 | #endif 515 | 516 | 517 | 518 | -------------------------------------------------------------------------------- /system/inetkcp.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inetkcp.h - fast ARQ protocol implementation 4 | // 5 | // skywind3000 (at) gmail.com, 2009 6 | // 7 | // NOTE: 8 | // for more information, please see the readme file 9 | // 10 | //===================================================================== 11 | #ifndef __INETKCP_H__ 12 | #define __INETKCP_H__ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "imemdata.h" 19 | 20 | 21 | 22 | //--------------------------------------------------------------------- 23 | // segment 24 | //--------------------------------------------------------------------- 25 | struct IKCPSEG 26 | { 27 | struct ILISTHEAD node; 28 | IUINT32 conv; 29 | IUINT32 cmd; 30 | IUINT32 frg; 31 | IUINT32 wnd; 32 | IUINT32 ts; 33 | IUINT32 sn; 34 | IUINT32 una; 35 | IUINT32 len; 36 | IUINT32 resendts; 37 | IUINT32 rto; 38 | IUINT32 fastack; 39 | IUINT32 xmit; 40 | char data[1]; 41 | }; 42 | 43 | 44 | //--------------------------------------------------------------------- 45 | // IKCPCB 46 | //--------------------------------------------------------------------- 47 | struct IKCPCB 48 | { 49 | IUINT32 conv, mtu, mss, state; 50 | IUINT32 snd_una, snd_nxt, rcv_nxt; 51 | IUINT32 ts_recent, ts_lastack, ssthresh; 52 | IINT32 rx_rttval, rx_srtt, rx_rto, rx_minrto; 53 | IUINT32 snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe; 54 | IUINT32 current, interval, ts_flush, xmit; 55 | IUINT32 nrcv_buf, nsnd_buf; 56 | IUINT32 nrcv_que, nsnd_que; 57 | IUINT32 nodelay, updated; 58 | IUINT32 ts_probe, probe_wait; 59 | IUINT32 dead_link, incr, rx_rtt; 60 | struct ILISTHEAD snd_queue; 61 | struct ILISTHEAD rcv_queue; 62 | struct ILISTHEAD snd_buf; 63 | struct ILISTHEAD rcv_buf; 64 | ib_vector *acklist; 65 | IUINT32 ackcount; 66 | void *user; 67 | char *buffer; 68 | int fastresend; 69 | int fastlimit; 70 | int nocwnd, stream; 71 | int logmask; 72 | int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user); 73 | void (*writelog)(const char *log, struct IKCPCB *kcp, void *user); 74 | }; 75 | 76 | 77 | typedef struct IKCPCB ikcpcb; 78 | 79 | #define IKCP_LOG_OUTPUT 1 80 | #define IKCP_LOG_INPUT 2 81 | #define IKCP_LOG_SEND 4 82 | #define IKCP_LOG_RECV 8 83 | #define IKCP_LOG_IN_DATA 16 84 | #define IKCP_LOG_IN_ACK 32 85 | #define IKCP_LOG_IN_PROBE 64 86 | #define IKCP_LOG_IN_WINS 128 87 | #define IKCP_LOG_OUT_DATA 256 88 | #define IKCP_LOG_OUT_ACK 512 89 | #define IKCP_LOG_OUT_PROBE 1024 90 | #define IKCP_LOG_OUT_WINS 2048 91 | 92 | #ifdef __cplusplus 93 | extern "C" { 94 | #endif 95 | 96 | //--------------------------------------------------------------------- 97 | // interface 98 | //--------------------------------------------------------------------- 99 | 100 | // create a new kcp control object, 'conv' must equal in two endpoint 101 | // from the same connection. 'user' will be passed to the output callback 102 | // output callback can be setup like this: 'kcp->output = my_udp_output' 103 | ikcpcb* ikcp_create(IUINT32 conv, void *user); 104 | 105 | // release kcp control object 106 | void ikcp_release(ikcpcb *kcp); 107 | 108 | // user/upper level recv: returns size, returns below zero for EAGAIN 109 | int ikcp_recv(ikcpcb *kcp, char *buffer, int len); 110 | 111 | // user/upper level send, returns below zero for error 112 | int ikcp_send(ikcpcb *kcp, const char *buffer, int len); 113 | 114 | // update state (call it repeatedly, every 10ms-100ms), or you can ask 115 | // ikcp_check when to call it again (without ikcp_input/_send calling). 116 | // 'current' - current timestamp in millisec. 117 | void ikcp_update(ikcpcb *kcp, IUINT32 current); 118 | 119 | // Determine when should you invoke ikcp_update: 120 | // returns when you should invoke ikcp_update in millisec, if there 121 | // is no ikcp_input/_send calling. you can call ikcp_update in that 122 | // time, instead of call update repeatly. 123 | // Important to reduce unnacessary ikcp_update invoking. use it to 124 | // schedule ikcp_update (eg. implementing an epoll-like mechanism, 125 | // or optimize ikcp_update when handling massive kcp connections) 126 | IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current); 127 | 128 | // when you received a low level packet (eg. UDP packet), call it 129 | int ikcp_input(ikcpcb *kcp, const char *data, long size); 130 | void ikcp_flush(ikcpcb *kcp); 131 | 132 | int ikcp_peeksize(const ikcpcb *kcp); 133 | 134 | // change MTU size, default is 1400 135 | int ikcp_setmtu(ikcpcb *kcp, int mtu); 136 | 137 | // set maximum window size: sndwnd=32, rcvwnd=32 by default 138 | int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd); 139 | 140 | // get how many packet is waiting to be sent 141 | int ikcp_waitsnd(const ikcpcb *kcp); 142 | 143 | // fastest: ikcp_nodelay(kcp, 1, 20, 2, 1) 144 | // nodelay: 0:disable(default), 1:enable 145 | // interval: internal update timer interval in millisec, default is 100ms 146 | // resend: 0:disable fast resend(default), 1:enable fast resend 147 | // nc: 0:normal congestion control(default), 1:disable congestion control 148 | int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc); 149 | 150 | 151 | void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...); 152 | 153 | 154 | #ifdef __cplusplus 155 | } 156 | #endif 157 | 158 | #endif 159 | 160 | 161 | -------------------------------------------------------------------------------- /system/inetnot.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inetnot.h - AsyncNotify implementation 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | 10 | #ifndef __INETNOT_H__ 11 | #define __INETNOT_H__ 12 | 13 | #include "imemdata.h" 14 | #include "inetcode.h" 15 | 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | 22 | //===================================================================== 23 | // CAsyncNotify 24 | //===================================================================== 25 | struct CAsyncNotify; 26 | typedef struct CAsyncNotify CAsyncNotify; 27 | 28 | 29 | //===================================================================== 30 | // interfaces 31 | //===================================================================== 32 | 33 | // create object 34 | CAsyncNotify* async_notify_new(int serverid); 35 | 36 | // delete object 37 | void async_notify_delete(CAsyncNotify *notify); 38 | 39 | 40 | #define ASYNC_NOTIFY_EVT_DATA 1 // (wp=sid, lp=cmd) 41 | #define ASYNC_NOTIFY_EVT_NEW_IN 2 // (wp=sid, lp=hid) 42 | #define ASYNC_NOTIFY_EVT_NEW_OUT 4 // (wp=sid, lp=hid) 43 | #define ASYNC_NOTIFY_EVT_CLOSED_IN 8 // (wp=sid, lp=hid) 44 | #define ASYNC_NOTIFY_EVT_CLOSED_OUT 16 // (wp=sid, lp=hid) 45 | #define ASYNC_NOTIFY_EVT_ERROR 32 // (wp=sid, lp=why) 46 | #define ASYNC_NOTIFY_EVT_CORE 64 47 | 48 | // wait events 49 | void async_notify_wait(CAsyncNotify *notify, IUINT32 millisec); 50 | 51 | // wake-up from waiting 52 | void async_notify_wake(CAsyncNotify *notify); 53 | 54 | // read events, returns data length of the message, 55 | // and returns -1 for no event, -2 for buffer size too small, 56 | // returns data size when data equals NULL. 57 | long async_notify_read(CAsyncNotify *notify, int *event, long *wparam, 58 | long *lparam, void *data, long maxsize); 59 | 60 | 61 | // new listen: return id(-1 error, -2 port conflict), flag&1(reuse) 62 | long async_notify_listen(CAsyncNotify *notify, const struct sockaddr *addr, 63 | int addrlen, int flag); 64 | 65 | // remove listening port 66 | int async_notify_remove(CAsyncNotify *notify, long listenid, int code); 67 | 68 | // setup self server id 69 | void async_notify_change(CAsyncNotify *notify, int new_server_id); 70 | 71 | 72 | // send message to server 73 | int async_notify_send(CAsyncNotify *notify, int sid, short cmd, 74 | const void *data, long size); 75 | 76 | // close server connection 77 | int async_notify_close(CAsyncNotify *notify, int sid, int mode, int code); 78 | 79 | // get listening port 80 | int async_notify_get_port(CAsyncNotify *notify, long listenid); 81 | 82 | 83 | // clear ip allow table 84 | void async_notify_allow_clear(CAsyncNotify *notify); 85 | 86 | // add or update ip in allow table 87 | void async_notify_allow_add(CAsyncNotify *notify, const void *ip, int size); 88 | 89 | // remove ip from table 90 | void async_notify_allow_del(CAsyncNotify *notify, const void *ip, int size); 91 | 92 | // ip table enable: enable is 0(disable allow table) otherwise(enable) 93 | void async_notify_allow_enable(CAsyncNotify *notify, int enable); 94 | 95 | 96 | // add or update a sid into sid2addr 97 | void async_notify_sid_add(CAsyncNotify *notify, int sid, 98 | const struct sockaddr *remote, int size); 99 | 100 | // add or update a sid into sid2addr 101 | void async_notify_sid_del(CAsyncNotify *notify, int sid); 102 | 103 | // list sids into an array 104 | int async_notify_sid_list(CAsyncNotify *notify, int *sids, int maxsize); 105 | 106 | // sid clear 107 | void async_notify_sid_clear(CAsyncNotify *notify); 108 | 109 | 110 | #define ASYNC_NOTIFY_OPT_PROFILE 0 111 | #define ASYNC_NOTIFY_OPT_TIMEOUT_IDLE 1 112 | #define ASYNC_NOTIFY_OPT_TIMEOUT_PING 2 113 | #define ASYNC_NOTIFY_OPT_SOCK_KEEPALIVE 3 114 | #define ASYNC_NOTIFY_OPT_SND_BUFSIZE 4 115 | #define ASYNC_NOTIFY_OPT_RCV_BUFSIZE 5 116 | #define ASYNC_NOTIFY_OPT_BUFFER_LIMIT 6 117 | #define ASYNC_NOTIFY_OPT_SIGN_TIMEOUT 7 118 | #define ASYNC_NOTIFY_OPT_RETRY_TIMEOUT 8 119 | #define ASYNC_NOTIFY_OPT_NET_TIMEOUT 9 120 | #define ASYNC_NOTIFY_OPT_EVT_MASK 10 121 | #define ASYNC_NOTIFY_OPT_LOG_MASK 11 122 | #define ASYNC_NOTIFY_OPT_GET_PING 12 123 | #define ASYNC_NOTIFY_OPT_GET_OUT_COUNT 13 124 | #define ASYNC_NOTIFY_OPT_GET_IN_COUNT 14 125 | 126 | #define ASYNC_NOTIFY_LOG_INFO 1 127 | #define ASYNC_NOTIFY_LOG_REJECT 2 128 | #define ASYNC_NOTIFY_LOG_ERROR 4 129 | #define ASYNC_NOTIFY_LOG_WARNING 8 130 | #define ASYNC_NOTIFY_LOG_DEBUG 16 131 | 132 | 133 | // config 134 | int async_notify_option(CAsyncNotify *notify, int type, long value); 135 | 136 | // set login token 137 | void async_notify_token(CAsyncNotify *notify, const char *token, int size); 138 | 139 | 140 | // set log function 141 | typedef void (*CAsyncNotify_WriteLog)(const char *text, void *user); 142 | 143 | // set new function and return old one 144 | void *async_notify_install(CAsyncNotify *notify, CAsyncNotify_WriteLog func); 145 | 146 | // set new function and return old one 147 | void *async_notify_user(CAsyncNotify *notify, void *user); 148 | 149 | 150 | #ifdef __cplusplus 151 | } 152 | #endif 153 | 154 | 155 | #endif 156 | 157 | 158 | -------------------------------------------------------------------------------- /system/inetsim.c: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inetsim.c - network simulator for IP-layer 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "inetsim.h" 16 | 17 | 18 | /*====================================================================*/ 19 | /* INTERFACE DEFINITION */ 20 | /*====================================================================*/ 21 | 22 | //--------------------------------------------------------------------- 23 | // 单向链路:初始化 24 | //--------------------------------------------------------------------- 25 | void isim_transfer_init(iSimTransfer *trans, long rtt, long lost, long amb, 26 | long limit, int mode) 27 | { 28 | assert(trans); 29 | trans->rtt = rtt; 30 | trans->lost = lost; 31 | trans->amb = amb; 32 | trans->limit = limit; 33 | trans->seed = 0; 34 | trans->size = 0; 35 | trans->current = 0; 36 | trans->cnt_send = 0; 37 | trans->cnt_drop = 0; 38 | trans->mode = mode; 39 | ilist_init(&trans->head); 40 | } 41 | 42 | //--------------------------------------------------------------------- 43 | // 单向链路:销毁 44 | //--------------------------------------------------------------------- 45 | void isim_transfer_destroy(iSimTransfer *trans) 46 | { 47 | assert(trans); 48 | while (!ilist_is_empty(&trans->head)) { 49 | struct ILISTHEAD *head = trans->head.next; 50 | iSimPacket *packet = ilist_entry(head, iSimPacket, head); 51 | ilist_del(head); 52 | free(packet); 53 | } 54 | trans->size = 0; 55 | trans->cnt_send = 0; 56 | trans->cnt_drop = 0; 57 | ilist_init(&trans->head); 58 | } 59 | 60 | //--------------------------------------------------------------------- 61 | // 单向链路:设置时间 62 | //--------------------------------------------------------------------- 63 | void isim_transfer_settime(iSimTransfer *trans, unsigned long time) 64 | { 65 | assert(trans); 66 | trans->current = time; 67 | } 68 | 69 | //--------------------------------------------------------------------- 70 | // 单向链路:随机数 71 | //--------------------------------------------------------------------- 72 | long isim_transfer_random(iSimTransfer *trans, long range) 73 | { 74 | unsigned long seed, value; 75 | 76 | assert(trans); 77 | 78 | if (range <= 0) return 0; 79 | 80 | seed = trans->seed; 81 | value = (((seed = seed * 214013L + 2531011L) >> 16) & 0xffff); 82 | trans->seed = seed; 83 | 84 | return value % range; 85 | } 86 | 87 | //--------------------------------------------------------------------- 88 | // 单向链路:发送数据 89 | //--------------------------------------------------------------------- 90 | long isim_transfer_send(iSimTransfer *trans, const void *data, long size) 91 | { 92 | iSimPacket *packet; 93 | ilist_head *p; 94 | long feature; 95 | long wave; 96 | 97 | trans->cnt_send++; 98 | 99 | // 判断是否超过限制 100 | if (trans->size >= trans->limit) { 101 | trans->cnt_drop++; 102 | return -1; 103 | } 104 | 105 | // 判断是否丢包 106 | if (trans->lost > 0) { 107 | if (isim_transfer_random(trans, 100) < trans->lost) { 108 | trans->cnt_drop++; 109 | return -2; 110 | } 111 | } 112 | 113 | // 分配新数据包 114 | packet = (iSimPacket*)malloc(sizeof(iSimPacket) + size); 115 | assert(packet); 116 | 117 | packet->data = ((unsigned char*)packet) + sizeof(iSimPacket); 118 | packet->size = size; 119 | 120 | memcpy(packet->data, data, size); 121 | 122 | // 计算到达时间 123 | wave = (trans->rtt * trans->amb) / 100; 124 | wave = (wave * (isim_transfer_random(trans, 200) - 100)) / 100; 125 | wave = wave + trans->rtt; 126 | 127 | if (wave < 0) feature = trans->current; 128 | else feature = trans->current + wave; 129 | 130 | packet->timestamp = feature; 131 | 132 | // 按到达时间先后插入时间链表 133 | for (p = trans->head.prev; p != &trans->head; p = p->prev) { 134 | iSimPacket *node = ilist_entry(p, iSimPacket, head); 135 | if (node->timestamp < packet->timestamp) break; 136 | } 137 | 138 | // 如果是顺序模式 139 | if (trans->mode != 0) p = trans->head.prev; 140 | 141 | ilist_add(&packet->head, p); 142 | trans->size++; 143 | 144 | return 0; 145 | } 146 | 147 | //--------------------------------------------------------------------- 148 | // 单向链路:接收数据 149 | //--------------------------------------------------------------------- 150 | long isim_transfer_recv(iSimTransfer *trans, void *data, long maxsize) 151 | { 152 | iSimPacket *packet; 153 | ilist_head *p; 154 | long size = 0; 155 | 156 | assert(trans); 157 | 158 | // 没有数据包 159 | if (ilist_is_empty(&trans->head)) { 160 | return -1; 161 | } 162 | 163 | p = trans->head.next; 164 | packet = ilist_entry(p, iSimPacket, head); 165 | 166 | // 还为到达接收时间 167 | if (trans->current < packet->timestamp) { 168 | return -2; 169 | } 170 | 171 | // 移除队列 172 | ilist_del(p); 173 | trans->size--; 174 | 175 | // 数据拷贝 176 | if (data) { 177 | size = packet->size; 178 | if (size > maxsize) size = maxsize; 179 | memcpy(data, packet->data, size); 180 | } 181 | 182 | // 释放内存 183 | free(packet); 184 | 185 | return size; 186 | } 187 | 188 | 189 | //--------------------------------------------------------------------- 190 | // isim_init: 191 | // 初始化网络模拟器 192 | // rtt - 往返时间平均数 193 | // lost - 丢包率百分比 (0 - 100) 194 | // amb - 时间振幅百分比 (0 - 100) 195 | // limit - 最多包缓存数量 196 | // mode - 0(后发包会先到) 1(后发包必然后到达) 197 | // 到达时间 = 当前时间 + rtt * 0.5 + rtt * (amb * 0.01) * random(-0.5, 0.5) 198 | // 公网极速 = rtt( 60), lost( 5), amb(30), limit(1000) 199 | // 公网快速 = rtt(120), lost(10), amb(40), limit(1000) 200 | // 公网普通 = rtt(200), lost(10), amb(50), limit(1000) 201 | // 公网慢速 = rtt(800), lost(20), amb(60), limit(1000) 202 | //--------------------------------------------------------------------- 203 | void isim_init(iSimNet *simnet, long rtt, long lost, long amb, long limit, int mode) 204 | { 205 | assert(simnet); 206 | isim_transfer_init(&simnet->t1, rtt >> 1, lost, amb, limit, mode); 207 | isim_transfer_init(&simnet->t2, rtt >> 1, lost, amb, limit, mode); 208 | simnet->p1.t1 = &simnet->t1; 209 | simnet->p1.t2 = &simnet->t2; 210 | simnet->p2.t1 = &simnet->t2; 211 | simnet->p2.t2 = &simnet->t1; 212 | } 213 | 214 | //--------------------------------------------------------------------- 215 | // 删除网络模拟器 216 | //--------------------------------------------------------------------- 217 | void isim_destroy(iSimNet *simnet) 218 | { 219 | assert(simnet); 220 | assert(simnet->p1.t1 && simnet->p1.t2); 221 | assert(simnet->p2.t1 && simnet->p2.t2); 222 | 223 | isim_transfer_destroy(&simnet->t1); 224 | isim_transfer_destroy(&simnet->t2); 225 | 226 | simnet->p1.t1 = NULL; 227 | simnet->p1.t2 = NULL; 228 | simnet->p2.t1 = NULL; 229 | simnet->p2.t2 = NULL; 230 | } 231 | 232 | //--------------------------------------------------------------------- 233 | // 设置时间 234 | //--------------------------------------------------------------------- 235 | void isim_settime(iSimNet *simnet, unsigned long current) 236 | { 237 | assert(simnet); 238 | isim_transfer_settime(&simnet->t1, current); 239 | isim_transfer_settime(&simnet->t2, current); 240 | } 241 | 242 | //--------------------------------------------------------------------- 243 | // 发送数据 244 | //--------------------------------------------------------------------- 245 | long isim_send(iSimPeer *peer, const void *data, long size) 246 | { 247 | return isim_transfer_send(peer->t1, data, size); 248 | } 249 | 250 | //--------------------------------------------------------------------- 251 | // 接收数据 252 | //--------------------------------------------------------------------- 253 | long isim_recv(iSimPeer *peer, void *data, long maxsize) 254 | { 255 | return isim_transfer_recv(peer->t2, data, maxsize); 256 | } 257 | 258 | //--------------------------------------------------------------------- 259 | // 取得端点:peerno = 0(端点1), 1(端点2) 260 | //--------------------------------------------------------------------- 261 | iSimPeer *isim_peer(iSimNet *simnet, int peerno) 262 | { 263 | assert(simnet); 264 | assert(peerno == 0 || peerno == 1); 265 | if (peerno == 0) return &simnet->p1; 266 | return &simnet->p2; 267 | } 268 | 269 | //--------------------------------------------------------------------- 270 | // 设置随机数种子 271 | //--------------------------------------------------------------------- 272 | void isim_seed(iSimNet *simnet, unsigned long seed1, unsigned long seed2) 273 | { 274 | assert(simnet); 275 | simnet->t1.seed = seed1; 276 | simnet->t2.seed = seed2; 277 | } 278 | 279 | -------------------------------------------------------------------------------- /system/inetsim.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inetsim.h - network simulator for IP-layer 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | 10 | #ifndef __INETSIM_H__ 11 | #define __INETSIM_H__ 12 | 13 | 14 | /*====================================================================*/ 15 | /* QUEUE DEFINITION */ 16 | /*====================================================================*/ 17 | #ifndef __ILIST_DEF__ 18 | #define __ILIST_DEF__ 19 | 20 | struct ILISTHEAD { 21 | struct ILISTHEAD *next, *prev; 22 | }; 23 | 24 | typedef struct ILISTHEAD ilist_head; 25 | 26 | 27 | /*--------------------------------------------------------------------*/ 28 | /* queue init */ 29 | /*--------------------------------------------------------------------*/ 30 | #define ILIST_HEAD_INIT(name) { &(name), &(name) } 31 | #define ILIST_HEAD(name) \ 32 | struct ILISTHEAD name = ILIST_HEAD_INIT(name) 33 | 34 | #define ILIST_INIT(ptr) ( \ 35 | (ptr)->next = (ptr), (ptr)->prev = (ptr)) 36 | 37 | #define IOFFSETOF(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER) 38 | 39 | #define ICONTAINEROF(ptr, type, member) ( \ 40 | (type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) ) 41 | 42 | #define ILIST_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member) 43 | 44 | 45 | /*--------------------------------------------------------------------*/ 46 | /* queue operation */ 47 | /*--------------------------------------------------------------------*/ 48 | #define ILIST_ADD(node, head) ( \ 49 | (node)->prev = (head), (node)->next = (head)->next, \ 50 | (head)->next->prev = (node), (head)->next = (node)) 51 | 52 | #define ILIST_ADD_TAIL(node, head) ( \ 53 | (node)->prev = (head)->prev, (node)->next = (head), \ 54 | (head)->prev->next = (node), (head)->prev = (node)) 55 | 56 | #define ILIST_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n)) 57 | 58 | #define ILIST_DEL(entry) (\ 59 | (entry)->next->prev = (entry)->prev, \ 60 | (entry)->prev->next = (entry)->next, \ 61 | (entry)->next = 0, (entry)->prev = 0) 62 | 63 | #define ILIST_DEL_INIT(entry) do { \ 64 | ILIST_DEL(entry); ILIST_INIT(entry); } while (0); 65 | 66 | #define ILIST_IS_EMPTY(entry) ((entry) == (entry)->next) 67 | 68 | #define ilist_init ILIST_INIT 69 | #define ilist_entry ILIST_ENTRY 70 | #define ilist_add ILIST_ADD 71 | #define ilist_add_tail ILIST_ADD_TAIL 72 | #define ilist_del ILIST_DEL 73 | #define ilist_del_init ILIST_DEL_INIT 74 | #define ilist_is_empty ILIST_IS_EMPTY 75 | 76 | #define ILIST_FOREACH(iterator, head, TYPE, MEMBER) \ 77 | for ((iterator) = ilist_entry((head)->next, TYPE, MEMBER); \ 78 | &((iterator)->MEMBER) != (head); \ 79 | (iterator) = ilist_entry((iterator)->MEMBER.next, TYPE, MEMBER)) 80 | 81 | #define ilist_foreach(iterator, head, TYPE, MEMBER) \ 82 | ILIST_FOREACH(iterator, head, TYPE, MEMBER) 83 | 84 | 85 | #ifdef _MSC_VER 86 | #pragma warning(disable:4311) 87 | #pragma warning(disable:4312) 88 | #pragma warning(disable:4996) 89 | #endif 90 | 91 | #endif 92 | 93 | 94 | 95 | /*====================================================================*/ 96 | /* GLOBAL DEFINITION */ 97 | /*====================================================================*/ 98 | 99 | // 模拟数据包 100 | struct ISIMPACKET 101 | { 102 | struct ILISTHEAD head; // 链表节点:按照时间排序 103 | unsigned long timestamp; // 时间戳:到达的时间 104 | unsigned long size; // 大小 105 | unsigned char *data; // 数据指针 106 | }; 107 | 108 | typedef struct ISIMPACKET iSimPacket; 109 | 110 | // 单向链路 111 | struct ISIMTRANSFER 112 | { 113 | struct ILISTHEAD head; // 时间排序链表 114 | unsigned long current; // 当前时间 115 | unsigned long seed; // 随机种子 116 | long size; // 包个数 117 | long limit; // 最大包数 118 | long rtt; // 平均往返时间(120, 200, ..) 119 | long lost; // 丢包率百分比(0-100) 120 | long amb; // 延迟振幅百分比(0-100) 121 | int mode; // 模式0(会前后到达)1(顺序到达) 122 | long cnt_send; // 发送了多少个包 123 | long cnt_drop; // 丢失了多少个包 124 | }; 125 | 126 | typedef struct ISIMTRANSFER iSimTransfer; 127 | 128 | // 网络端点 129 | struct ISIMPEER 130 | { 131 | iSimTransfer *t1; // 发送链路 132 | iSimTransfer *t2; // 接收链路 133 | }; 134 | 135 | typedef struct ISIMPEER iSimPeer; 136 | 137 | // 网络模拟器 138 | struct ISIMNET 139 | { 140 | iSimTransfer t1; // 链路1 141 | iSimTransfer t2; // 链路2 142 | iSimPeer p1; // 端点1 (t1, t2) 143 | iSimPeer p2; // 端点2 (t2, t1) 144 | }; 145 | 146 | typedef struct ISIMNET iSimNet; 147 | 148 | 149 | #ifdef __cplusplus 150 | extern "C" { 151 | #endif 152 | 153 | /*====================================================================*/ 154 | /* INTERFACE DEFINITION */ 155 | /*====================================================================*/ 156 | 157 | // 单向链路:初始化 158 | void isim_transfer_init(iSimTransfer *trans, long rtt, long lost, long amb, 159 | long limit, int mode); 160 | 161 | // 单向链路:销毁 162 | void isim_transfer_destroy(iSimTransfer *trans); 163 | 164 | // 单向链路:设置时间 165 | void isim_transfer_settime(iSimTransfer *trans, unsigned long time); 166 | 167 | // 单向链路:随机数 168 | long isim_transfer_random(iSimTransfer *trans, long range); 169 | 170 | // 单向链路:发送数据 171 | long isim_transfer_send(iSimTransfer *trans, const void *data, long size); 172 | 173 | // 单向链路:接收数据 174 | long isim_transfer_recv(iSimTransfer *trans, void *data, long maxsize); 175 | 176 | 177 | 178 | // isim_init: 179 | // 初始化网络模拟器 180 | // rtt - 往返时间平均数 181 | // lost - 丢包率百分比 (0 - 100) 182 | // amb - 时间振幅百分比 (0 - 100) 183 | // limit - 最多包缓存数量 184 | // mode - 0(后发包会先到) 1(后发包必然后到达) 185 | // 到达时间 = 当前时间 + rtt * 0.5 + rtt * (amb * 0.01) * random(-0.5, 0.5) 186 | // 公网极速 = rtt( 60), lost( 5), amb(30), limit(1000) 187 | // 公网快速 = rtt(120), lost(10), amb(40), limit(1000) 188 | // 公网普通 = rtt(200), lost(10), amb(50), limit(1000) 189 | // 公网慢速 = rtt(800), lost(20), amb(60), limit(1000) 190 | void isim_init(iSimNet *simnet, long rtt, long lost, long amb, long limit, int mode); 191 | 192 | // 删除网络模拟器 193 | void isim_destroy(iSimNet *simnet); 194 | 195 | // 设置时间 196 | void isim_settime(iSimNet *simnet, unsigned long current); 197 | 198 | 199 | // 发送数据 200 | long isim_send(iSimPeer *peer, const void *data, long size); 201 | 202 | // 接收数据 203 | long isim_recv(iSimPeer *peer, void *data, long maxsize); 204 | 205 | // 取得端点:peerno = 0(端点1), 1(端点2) 206 | iSimPeer *isim_peer(iSimNet *simnet, int peerno); 207 | 208 | // 设置随机数种子 209 | void isim_seed(iSimNet *simnet, unsigned long seed1, unsigned long seed2); 210 | 211 | 212 | 213 | #ifdef __cplusplus 214 | } 215 | #endif 216 | 217 | #endif 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /system/inettcp.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inettcp.h - simple tcp protocol implementation 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | 10 | #ifndef __INETNTCP_H__ 11 | #define __INETNTCP_H__ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "imemdata.h" 18 | 19 | 20 | //===================================================================== 21 | // GLOBAL DEFINITION 22 | //===================================================================== 23 | #ifndef __IUINT32_DEFINED 24 | #define __IUINT32_DEFINED 25 | typedef unsigned long IUINT32; 26 | #endif 27 | 28 | #ifndef __IUINT16_DEFINED 29 | #define __IUINT16_DEFINED 30 | typedef unsigned short IUINT16; 31 | #endif 32 | 33 | #ifndef __IUINT8_DEFINED 34 | #define __IUINT8_DEFINED 35 | typedef unsigned char IUINT8; 36 | #endif 37 | 38 | 39 | #define ITCP_LISTEN 0 40 | #define ITCP_SYN_SENT 1 41 | #define ITCP_SYN_RECV 2 42 | #define ITCP_ESTAB 3 43 | #define ITCP_CLOSED 4 44 | 45 | #define IOUTPUT_OK 0 46 | #define IOUTPUT_BLOCKING 1 47 | #define IOUTPUT_TOOLARGE 2 48 | #define IOUTPUT_FAILED 3 49 | 50 | #define ISOCKERR -1 51 | #define IEINVAL 1001 52 | #define IENOTCONN 1002 53 | #define IEWOULDBLOCK 1003 54 | #define IECONNABORTED 1004 55 | #define IECONNREST 1005 56 | #define IEFATAL 1006 57 | 58 | #define ILOG_STATE 1 59 | #define ILOG_INFO 2 60 | #define ILOG_WARN 4 61 | #define ILOG_WINDOW 8 62 | #define ILOG_PACKET 16 63 | #define ILOG_RTT 32 64 | #define ILOG_ACK 64 65 | #define ILOG_DEBUG 128 66 | 67 | #define ITCP_CIRCLE 68 | 69 | 70 | #ifndef ASSERT 71 | #define ASSERT(x) assert((x)) 72 | #endif 73 | 74 | //--------------------------------------------------------------------- 75 | // Data Segment 76 | //--------------------------------------------------------------------- 77 | struct ISEGMENT 78 | { 79 | IUINT32 conv, seq, ack; 80 | IUINT32 wnd; 81 | IUINT16 flags; 82 | IUINT32 tsval, tsecr; 83 | IUINT32 len; 84 | char *data; 85 | }; 86 | 87 | //--------------------------------------------------------------------- 88 | // Output Segment 89 | //--------------------------------------------------------------------- 90 | struct ISEGOUT 91 | { 92 | ilist_head head; 93 | IUINT32 seq; 94 | IUINT32 len; 95 | IUINT16 xmit; 96 | IUINT16 bctl; 97 | }; 98 | 99 | //--------------------------------------------------------------------- 100 | // Input Segment 101 | //--------------------------------------------------------------------- 102 | struct ISEGIN 103 | { 104 | ilist_head head; 105 | IUINT32 seq, len; 106 | }; 107 | 108 | typedef struct ISEGMENT ISEGMENT; 109 | typedef struct ISEGOUT ISEGOUT; 110 | typedef struct ISEGIN ISEGIN; 111 | 112 | 113 | 114 | //--------------------------------------------------------------------- 115 | // TCP CONTROL BLOCK 116 | //--------------------------------------------------------------------- 117 | struct ITCPCB 118 | { 119 | IUINT32 conv, state; 120 | IUINT32 current; 121 | IUINT32 last_traffic; 122 | IUINT32 buf_size; 123 | 124 | IUINT32 snd_una, snd_nxt, snd_wnd, last_send, slen; 125 | ilist_head slist; 126 | iring_t scache; 127 | char *sbuf; 128 | 129 | IUINT32 rcv_nxt, rcv_wnd, last_recv, rlen; 130 | ilist_head rlist; 131 | iring_t rcache; 132 | char *rbuf; 133 | 134 | IUINT32 mtu, mss, omtu, largest; 135 | 136 | IUINT32 rto_base; 137 | int be_outgoing; 138 | IUINT32 ts_recent, ts_lastack, ts_acklocal; 139 | 140 | ilist_head sfree; 141 | int free_cnt; 142 | int free_max; 143 | char *buffer; 144 | 145 | long rx_rttval, rx_srtt, rx_rto, rx_minrto, rx_rtt; 146 | long rx_ackdelay; 147 | 148 | int be_readable; 149 | int be_writeable; 150 | int keepalive; 151 | int shutdown; 152 | int nodelay; 153 | 154 | IUINT32 ssthresh, cwnd; 155 | IUINT32 dup_acks; 156 | IUINT32 recover; 157 | IUINT32 t_ack; 158 | 159 | void *user; 160 | void *extra; 161 | int errcode, logmask, id; 162 | char *errmsg; 163 | 164 | int (*output)(const char *buf, int len, struct ITCPCB *tcp, void *user); 165 | int (*onopen)(struct ITCPCB *, void *user); 166 | int (*onclose)(struct ITCPCB *, void *user, int code); 167 | int (*oncanread)(struct ITCPCB *, void *user); 168 | int (*oncanwrite)(struct ITCPCB *, void *user); 169 | int (*writelog)(const char *log); 170 | }; 171 | 172 | 173 | typedef struct ITCPCB itcpcb; 174 | 175 | #ifdef __cplusplus 176 | extern "C" { 177 | #endif 178 | 179 | //--------------------------------------------------------------------- 180 | // TCP USER INTERFACE 181 | //--------------------------------------------------------------------- 182 | itcpcb *itcp_create(IUINT32 conv, const void *user); 183 | void itcp_release(itcpcb *tcp); 184 | 185 | int itcp_connect(itcpcb *tcp); 186 | void itcp_close(itcpcb *tcp); 187 | 188 | long itcp_recv(itcpcb *tcp, char *buffer, long len); 189 | long itcp_send(itcpcb *tcp, const char *buffer, long len); 190 | 191 | void itcp_update(itcpcb *tcp, IUINT32 millisec); 192 | int itcp_check(itcpcb *tcp); 193 | int itcp_input(itcpcb *tcp, const char *data, long size); 194 | void itcp_setmtu(itcpcb *tcp, long mtu); 195 | 196 | int itcp_setbuf(itcpcb *tcp, long bufsize); 197 | 198 | long itcp_dsize(const itcpcb *tcp); 199 | long itcp_peek(itcpcb *tcp, char *buffer, long len); 200 | long itcp_canwrite(const itcpcb *tcp); 201 | 202 | void itcp_option(itcpcb *tcp, int nodelay, int keepalive); 203 | 204 | 205 | 206 | #ifdef __cplusplus 207 | } 208 | #endif 209 | 210 | 211 | #endif 212 | 213 | 214 | -------------------------------------------------------------------------------- /system/ineturl.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // ineturl.h - urllib 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | #ifndef __INETURL_H__ 10 | #define __INETURL_H__ 11 | 12 | #include "imemdata.h" 13 | #include "inetbase.h" 14 | #include "inetcode.h" 15 | 16 | 17 | //===================================================================== 18 | // IHTTPSOCK 19 | //===================================================================== 20 | 21 | //--------------------------------------------------------------------- 22 | // IHTTPSOCK DEFINITION 23 | //--------------------------------------------------------------------- 24 | #define IHTTPSOCK_STATE_CLOSED 0 25 | #define IHTTPSOCK_STATE_CONNECTING 1 26 | #define IHTTPSOCK_STATE_CONNECTED 2 27 | 28 | 29 | struct IHTTPSOCK 30 | { 31 | int state; 32 | int sock; 33 | char *buffer; 34 | int bufsize; 35 | int endless; 36 | int error; 37 | IINT64 blocksize; 38 | IINT64 received; 39 | IINT64 conntime; 40 | int proxy_type; 41 | char *proxy_user; 42 | char *proxy_pass; 43 | struct ISOCKPROXY *proxy; 44 | struct sockaddr proxyd; 45 | struct sockaddr remote; 46 | struct IMSTREAM sendmsg; 47 | struct IMSTREAM recvmsg; 48 | }; 49 | 50 | typedef struct IHTTPSOCK IHTTPSOCK; 51 | 52 | #ifdef __cplusplus 53 | extern "C" { 54 | #endif 55 | //--------------------------------------------------------------------- 56 | // IHTTPSOCK INTERFACE 57 | //--------------------------------------------------------------------- 58 | 59 | // create a http sock 60 | IHTTPSOCK *ihttpsock_new(struct IMEMNODE *nodes); 61 | 62 | // delete a http sock 63 | void ihttpsock_delete(IHTTPSOCK *httpsock); 64 | 65 | // update http sock state 66 | void ihttpsock_update(IHTTPSOCK *httpsock); 67 | 68 | 69 | // connect to remote address 70 | int ihttpsock_connect(IHTTPSOCK *httpsock, const struct sockaddr *remote); 71 | 72 | // close connection 73 | void ihttpsock_close(IHTTPSOCK *httpsock); 74 | 75 | // set proxy, call it befor calling ihttpsock_connect 76 | int ihttpsock_proxy(IHTTPSOCK *httpsock, int type, 77 | const struct sockaddr *addr, const char *user, const char *pass); 78 | 79 | // assign to a connected socket 80 | int ihttpsock_assign(IHTTPSOCK *httpsock, int sock); 81 | 82 | 83 | // returns zero if blocked 84 | // returns below zero if connection shutdown or error 85 | // returns received data size if data received 86 | long ihttpsock_recv(IHTTPSOCK *httpsock, void *data, long size); 87 | 88 | // send data 89 | long ihttpsock_send(IHTTPSOCK *httpsock, const void *data, long size); 90 | 91 | // poll socket 92 | int ihttpsock_poll(IHTTPSOCK *httpsock, int event, int millsec); 93 | 94 | // get data size in send buffer (nbytes of data which hasn't been sent) 95 | long ihttpsock_dsize(const IHTTPSOCK *httpsock); 96 | 97 | // change buffer size 98 | void ihttpsock_bufsize(IHTTPSOCK *httpsock, long bufsize); 99 | 100 | // get socket 101 | int ihttpsock_sock(const IHTTPSOCK *httpsock); 102 | 103 | 104 | // ihttpsock_block_* functions will returns these values or data size 105 | #define IHTTPSOCK_BLOCK_AGAIN -1 106 | #define IHTTPSOCK_BLOCK_DONE -2 107 | #define IHTTPSOCK_BLOCK_CLOSED -3 108 | 109 | // set block size 110 | int ihttpsock_block_set(IHTTPSOCK *httpsock, IINT64 blocksize); 111 | 112 | // returns equal or above zero for data size 113 | // returns IHTTPSOCK_BLOCK_AGAIN for block 114 | // returns IHTTPSOCK_BLOCK_DONE for job finished 115 | // returns IHTTPSOCK_BLOCK_CLOSED for connection shutdown or error 116 | long ihttpsock_block_recv(IHTTPSOCK *httpsock, void *data, long size); 117 | 118 | 119 | // returns equal or above zero for data value, 120 | // returns IHTTPSOCK_BLOCK_AGAIN for block 121 | // returns IHTTPSOCK_BLOCK_CLOSED for connection shutdown or error 122 | int ihttpsock_block_getch(IHTTPSOCK *httpsock); 123 | 124 | // returns IHTTPSOCK_BLOCK_AGAIN for block 125 | // returns IHTTPSOCK_BLOCK_DONE for job finished 126 | // returns IHTTPSOCK_BLOCK_CLOSED for connection shutdown or error 127 | int ihttpsock_block_gets(IHTTPSOCK *httpsock, ivalue_t *text); 128 | 129 | 130 | #ifdef __cplusplus 131 | } 132 | #endif 133 | 134 | 135 | //===================================================================== 136 | // IHTTPLIB 137 | //===================================================================== 138 | 139 | #define IHTTP_STATE_STOP 0 140 | #define IHTTP_STATE_CONNECTING 1 141 | #define IHTTP_STATE_CONNECTED 2 142 | 143 | #define IHTTP_SENDING_STATE_WAIT 0 144 | #define IHTTP_SENDING_STATE_HEADER 1 145 | #define IHTTP_SENDING_STATE_DATA 2 146 | #define IHTTP_RECVING_STATE_WAIT 0 147 | #define IHTTP_RECVING_STATE_HEADER 1 148 | #define IHTTP_RECVING_STATE_DATA 2 149 | 150 | #define IHTTP_CHUNK_STATE_HEAD 0 151 | #define IHTTP_CHUNK_STATE_DATA 1 152 | #define IHTTP_CHUNK_STATE_TAIL 2 153 | #define IHTTP_CHUNK_STATE_DONE 3 154 | 155 | #define IHTTP_RESULT_DONE 0 156 | #define IHTTP_RESULT_NOT_STARTED 1 157 | #define IHTTP_RESULT_NOT_COMPLETED 2 158 | #define IHTTP_RESULT_NOT_FIND 3 159 | #define IHTTP_RESULT_HTTP_ERROR 4 160 | #define IHTTP_RESULT_HTTP_UNSUPPORT 5 161 | #define IHTTP_RESULT_HTTP_OUTRANGE 6 162 | #define IHTTP_RESULT_HTTP_UNAUTH 7 163 | #define IHTTP_RESULT_HTTP_REDIR301 8 164 | #define IHTTP_RESULT_HTTP_REDIR302 9 165 | #define IHTTP_RESULT_ABORTED 10 166 | #define IHTTP_RESULT_SOCK_ERROR 11 167 | #define IHTTP_RESULT_INVALID_ADDR 12 168 | #define IHTTP_RESULT_CONNECT_FAIL 13 169 | #define IHTTP_RESULT_DISCONNECTED 14 170 | 171 | 172 | 173 | //--------------------------------------------------------------------- 174 | // URL Descriptor 175 | //--------------------------------------------------------------------- 176 | struct IHTTPLIB 177 | { 178 | int state; 179 | int result; 180 | int snext; 181 | int rnext; 182 | int cnext; 183 | int shutdown; 184 | int chunked; 185 | int httpver; 186 | int nosize; 187 | int code; 188 | int keepalive; 189 | int partial; 190 | int isredirect; 191 | int proxy_type; 192 | char *proxy_user; 193 | char *proxy_pass; 194 | IINT64 clength; 195 | IINT64 chunksize; 196 | IINT64 datasize; 197 | IINT64 range_start; 198 | IINT64 range_endup; 199 | IINT64 range_size; 200 | IHTTPSOCK *sock; 201 | ivalue_t host; 202 | ivalue_t line; 203 | ivalue_t ctype; 204 | ivalue_t sheader; 205 | ivalue_t rheader; 206 | ivalue_t location; 207 | ivalue_t buffer; 208 | struct sockaddr proxyd; 209 | }; 210 | 211 | typedef struct IHTTPLIB IHTTPLIB; 212 | 213 | 214 | 215 | #ifdef __cplusplus 216 | extern "C" { 217 | #endif 218 | //--------------------------------------------------------------------- 219 | // URL Interface 220 | //--------------------------------------------------------------------- 221 | IHTTPLIB *ihttplib_new(void); 222 | 223 | void ihttplib_delete(IHTTPLIB *http); 224 | 225 | int ihttplib_open(IHTTPLIB *http, const char *HOST); 226 | 227 | int ihttplib_close(IHTTPLIB *http); 228 | 229 | int ihttplib_proxy(IHTTPLIB *http, int type, const char *proxy, 230 | int port, const char *user, const char *pass); 231 | 232 | int ihttplib_update(IHTTPLIB *http, int wait); 233 | 234 | void ihttplib_header_reset(IHTTPLIB *http); 235 | 236 | void ihttplib_header_write(IHTTPLIB *http, const char *head); 237 | 238 | void ihttplib_header_send(IHTTPLIB *http); 239 | 240 | long ihttplib_send(IHTTPLIB *http, const void *data, long size); 241 | 242 | 243 | #define IHTTP_RECV_AGAIN -1 244 | #define IHTTP_RECV_DONE -2 245 | #define IHTTP_RECV_CLOSED -3 246 | #define IHTTP_RECV_NOTFIND -4 247 | #define IHTTP_RECV_ERROR -5 248 | #define IHTTP_RECV_TIMEOUT -6 249 | 250 | // returns IHTTP_RECV_AGAIN for block 251 | // returns IHTTP_RECV_DONE for okay 252 | // returns IHTTP_RECV_CLOSED for closed 253 | // returns IHTTP_RECV_NOTFIND for not find 254 | // returns IHTTP_RECV_ERROR for http error 255 | long ihttplib_recv(IHTTPLIB *http, void *data, long size); 256 | 257 | // returns data size in send buffer 258 | long ihttplib_dsize(IHTTPLIB *http); 259 | 260 | 261 | #define IHTTP_METHOD_GET 0 262 | #define IHTTP_METHOD_POST 1 263 | 264 | int ihttplib_request(IHTTPLIB *http, int method, const char *url, 265 | const void *body, long bodysize, const char *header); 266 | 267 | 268 | // returns IHTTP_RECV_AGAIN for block 269 | // returns IHTTP_RECV_DONE for okay 270 | // returns IHTTP_RECV_CLOSED for closed 271 | // returns IHTTP_RECV_NOTFIND for not find 272 | // returns IHTTP_RECV_ERROR for http error 273 | int ihttplib_getresponse(IHTTPLIB *http, ivalue_t *content, int waitms); 274 | 275 | 276 | #ifdef __cplusplus 277 | } 278 | #endif 279 | 280 | 281 | 282 | //===================================================================== 283 | // IURLLIB 284 | //===================================================================== 285 | struct IURLD 286 | { 287 | IHTTPLIB *http; 288 | int done; 289 | ivalue_t url; 290 | ivalue_t host; 291 | ivalue_t proxy; 292 | }; 293 | 294 | typedef struct IURLD IURLD; 295 | 296 | 297 | #ifdef __cplusplus 298 | extern "C" { 299 | #endif 300 | //--------------------------------------------------------------------- 301 | // URL Interface 302 | //--------------------------------------------------------------------- 303 | 304 | // open a url 305 | // POST mode: size >= 0 && data != NULL 306 | // GET mode: size < 0 || data == NULL 307 | // proxy format: a string: (type, addr, port [,user, passwd]) joined by "\n" 308 | // NULL for direct link. 'type' can be one of 'http', 'socks4' and 'socks5', 309 | // eg: type=http, proxyaddr=10.0.1.1, port=8080 -> "http\n10.0.1.1\n8080" 310 | // eg: "socks5\n10.0.0.1\n80\nuser1\npass1" "socks4\n127.0.0.1\n1081" 311 | IURLD *ineturl_open(const char *URL, const void *data, long size, 312 | const char *header, const char *proxy, int *errcode); 313 | 314 | void ineturl_close(IURLD *url); 315 | 316 | // returns IHTTP_RECV_AGAIN for block 317 | // returns IHTTP_RECV_DONE for okay 318 | // returns IHTTP_RECV_CLOSED for closed 319 | // returns IHTTP_RECV_NOTFIND for not find 320 | // returns IHTTP_RECV_ERROR for http error 321 | // returns > 0 for received data size 322 | long ineturl_read(IURLD *url, void *data, long size, int waitms); 323 | 324 | // writing extra post data 325 | // returns data size in send-buffer; 326 | long ineturl_write(IURLD *url, const void *data, long size); 327 | 328 | // flush: try to send data from buffer to network 329 | void ineturl_flush(IURLD *url); 330 | 331 | // check redirect 332 | int ineturl_location(IURLD *url, ivalue_t *location); 333 | 334 | 335 | #ifdef __cplusplus 336 | } 337 | #endif 338 | 339 | 340 | #ifdef __cplusplus 341 | extern "C" { 342 | #endif 343 | //--------------------------------------------------------------------- 344 | // TOOL AND DEMO 345 | //--------------------------------------------------------------------- 346 | 347 | // wget into a string 348 | // returns >= 0 for okay, below zero for errors: 349 | // returns IHTTP_RECV_CLOSED for closed 350 | // returns IHTTP_RECV_NOTFIND for not find 351 | // returns IHTTP_RECV_ERROR for http error 352 | int _urllib_wget(const char *URL, ivalue_t *ctx, const char *proxy, int time); 353 | 354 | 355 | // download to a file 356 | int _urllib_download(const char *URL, const char *filename); 357 | 358 | 359 | #ifdef __cplusplus 360 | } 361 | #endif 362 | 363 | 364 | 365 | #endif 366 | 367 | 368 | 369 | -------------------------------------------------------------------------------- /system/iposix.c: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // iposix.c - posix file system accessing 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | 10 | #include "iposix.h" 11 | 12 | #ifndef IDISABLE_FILE_SYSTEM_ACCESS 13 | //--------------------------------------------------------------------- 14 | // Global Definition 15 | //--------------------------------------------------------------------- 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) 26 | #include 27 | #endif 28 | 29 | #ifdef _WIN32 30 | #include 31 | #include 32 | #include 33 | #define ISYSNAME 'w' 34 | #else 35 | #ifndef __unix 36 | #define __unix 37 | #endif 38 | #define ISYSNAME 'u' 39 | #endif 40 | 41 | 42 | 43 | //--------------------------------------------------------------------- 44 | // Posix Stat 45 | //--------------------------------------------------------------------- 46 | #ifdef __unix 47 | typedef struct stat iposix_ostat_t; 48 | #define iposix_stat_proc stat 49 | #define iposix_lstat_proc lstat 50 | #define iposix_fstat_proc fstat 51 | #else 52 | typedef struct _stat iposix_ostat_t; 53 | #define iposix_stat_proc _stat 54 | #define iposix_lstat_proc _stat 55 | #define iposix_fstat_proc _fstat 56 | #endif 57 | 58 | 59 | #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) 60 | #if defined(_S_IFMT) && (!defined(S_IFMT)) 61 | #define S_IFMT _S_IFMT 62 | #endif 63 | 64 | #if defined(_S_IFDIR) && (!defined(S_IFDIR)) 65 | #define S_IFDIR _S_IFDIR 66 | #endif 67 | 68 | #if defined(_S_IFCHR) && (!defined(S_IFCHR)) 69 | #define S_IFCHR _S_IFCHR 70 | #endif 71 | 72 | #if defined(_S_IFIFO) && (!defined(S_IFIFO)) 73 | #define S_IFIFO _S_IFIFO 74 | #endif 75 | 76 | #if defined(_S_IFREG) && (!defined(S_IFREG)) 77 | #define S_IFREG _S_IFREG 78 | #endif 79 | 80 | #if defined(_S_IREAD) && (!defined(S_IREAD)) 81 | #define S_IREAD _S_IREAD 82 | #endif 83 | 84 | #if defined(_S_IWRITE) && (!defined(S_IWRITE)) 85 | #define S_IWRITE _S_IWRITE 86 | #endif 87 | 88 | #if defined(_S_IEXEC) && (!defined(S_IEXEC)) 89 | #define S_IEXEC _S_IEXEC 90 | #endif 91 | #endif 92 | 93 | #define IX_FMT(m, t) (((m) & S_IFMT) == (t)) 94 | 95 | 96 | // convert stat structure 97 | void iposix_stat_convert(iposix_stat_t *ostat, const iposix_ostat_t *x) 98 | { 99 | ostat->st_mode = 0; 100 | 101 | #ifdef S_IFDIR 102 | if (IX_FMT(x->st_mode, S_IFDIR)) ostat->st_mode |= ISTAT_IFDIR; 103 | #endif 104 | #ifdef S_IFCHR 105 | if (IX_FMT(x->st_mode, S_IFCHR)) ostat->st_mode |= ISTAT_IFCHR; 106 | #endif 107 | #ifdef S_IFBLK 108 | if (IX_FMT(x->st_mode, S_IFBLK)) ostat->st_mode |= ISTAT_IFBLK; 109 | #endif 110 | #ifdef S_IFREG 111 | if (IX_FMT(x->st_mode, S_IFREG)) ostat->st_mode |= ISTAT_IFREG; 112 | #endif 113 | #ifdef S_IFIFO 114 | if (IX_FMT(x->st_mode, S_IFIFO)) ostat->st_mode |= ISTAT_IFIFO; 115 | #endif 116 | #ifdef S_IFLNK 117 | if (IX_FMT(x->st_mode, S_IFLNK)) ostat->st_mode |= ISTAT_IFLNK; 118 | #endif 119 | #ifdef S_IFSOCK 120 | if (IX_FMT(x->st_mode, S_IFSOCK)) ostat->st_mode |= ISTAT_IFSOCK; 121 | #endif 122 | #ifdef S_IFWHT 123 | if (IX_FMT(x->st_mode, S_IFWHT)) ostat->st_mode |= ISTAT_IFWHT; 124 | #endif 125 | 126 | #ifdef S_IREAD 127 | if (x->st_mode & S_IREAD) ostat->st_mode |= ISTAT_IRUSR; 128 | #endif 129 | 130 | #ifdef S_IWRITE 131 | if (x->st_mode & S_IWRITE) ostat->st_mode |= ISTAT_IWUSR; 132 | #endif 133 | 134 | #ifdef S_IEXEC 135 | if (x->st_mode & S_IEXEC) ostat->st_mode |= ISTAT_IXUSR; 136 | #endif 137 | 138 | #ifdef S_IRUSR 139 | if (x->st_mode & S_IRUSR) ostat->st_mode |= ISTAT_IRUSR; 140 | if (x->st_mode & S_IWUSR) ostat->st_mode |= ISTAT_IWUSR; 141 | if (x->st_mode & S_IXUSR) ostat->st_mode |= ISTAT_IXUSR; 142 | #endif 143 | 144 | #ifdef S_IRGRP 145 | if (x->st_mode & S_IRGRP) ostat->st_mode |= ISTAT_IRGRP; 146 | if (x->st_mode & S_IWGRP) ostat->st_mode |= ISTAT_IWGRP; 147 | if (x->st_mode & S_IXGRP) ostat->st_mode |= ISTAT_IXGRP; 148 | #endif 149 | 150 | #ifdef S_IROTH 151 | if (x->st_mode & S_IROTH) ostat->st_mode |= ISTAT_IROTH; 152 | if (x->st_mode & S_IWOTH) ostat->st_mode |= ISTAT_IWOTH; 153 | if (x->st_mode & S_IXOTH) ostat->st_mode |= ISTAT_IXOTH; 154 | #endif 155 | 156 | ostat->st_size = (IUINT64)x->st_size; 157 | 158 | ostat->atime = (IUINT32)x->st_atime; 159 | ostat->mtime = (IUINT32)x->st_mtime; 160 | ostat->ctime = (IUINT32)x->st_mtime; 161 | 162 | ostat->st_ino = (IUINT64)x->st_ino; 163 | ostat->st_dev = (IUINT32)x->st_dev; 164 | ostat->st_nlink = (IUINT32)x->st_nlink; 165 | ostat->st_uid = (IUINT32)x->st_uid; 166 | ostat->st_gid = (IUINT32)x->st_gid; 167 | ostat->st_rdev = (IUINT32)x->st_rdev; 168 | 169 | #ifdef __unix 170 | // #define IHAVE_STAT_ST_BLKSIZE 171 | // #define IHAVE_STAT_ST_BLOCKS 172 | // #define IHAVE_STAT_ST_FLAGS 173 | #endif 174 | 175 | #if defined(__unix) 176 | #ifdef IHAVE_STAT_ST_BLOCKS 177 | ostat->st_blocks = (IUINT32)x->st_blocks; 178 | #endif 179 | #ifdef IHAVE_STAT_ST_BLKSIZE 180 | ostat->st_blksize = (IUINT32)x->st_blksize; 181 | #endif 182 | #if !defined(__CYGWIN__) && defined(IHAVE_STAT_ST_FLAGS) 183 | ostat->st_flags = (IUINT32)x->st_flags; 184 | #endif 185 | #endif 186 | } 187 | 188 | // returns 0 for success, -1 for error 189 | int iposix_stat_imp(const char *path, iposix_stat_t *ostat) 190 | { 191 | iposix_ostat_t xstat; 192 | int retval; 193 | retval = iposix_stat_proc(path, &xstat); 194 | if (retval != 0) return -1; 195 | iposix_stat_convert(ostat, &xstat); 196 | return 0; 197 | } 198 | 199 | // returns 0 for success, -1 for error 200 | int iposix_lstat_imp(const char *path, iposix_stat_t *ostat) 201 | { 202 | iposix_ostat_t xstat; 203 | int retval; 204 | retval = iposix_lstat_proc(path, &xstat); 205 | if (retval != 0) return -1; 206 | iposix_stat_convert(ostat, &xstat); 207 | return 0; 208 | } 209 | 210 | // returns 0 for success, -1 for error 211 | int iposix_fstat(int fd, iposix_stat_t *ostat) 212 | { 213 | iposix_ostat_t xstat; 214 | int retval; 215 | retval = iposix_fstat_proc(fd, &xstat); 216 | if (retval != 0) return -1; 217 | iposix_stat_convert(ostat, &xstat); 218 | return 0; 219 | } 220 | 221 | // normalize stat path 222 | static void iposix_path_stat(const char *src, char *dst) 223 | { 224 | int size = (int)strlen(src); 225 | if (size > IPOSIX_MAXPATH) size = IPOSIX_MAXPATH; 226 | memcpy(dst, src, size + 1); 227 | if (size > 1) { 228 | int trim = 1; 229 | if (size == 3) { 230 | if (isalpha((int)dst[0]) && dst[1] == ':' && 231 | (dst[2] == '/' || dst[2] == '\\')) trim = 0; 232 | } 233 | if (size == 1) { 234 | if (dst[0] == '/' || dst[0] == '\\') trim = 0; 235 | } 236 | if (trim) { 237 | if (dst[size - 1] == '/' || dst[size - 1] == '\\') { 238 | dst[size - 1] = 0; 239 | size--; 240 | } 241 | } 242 | } 243 | } 244 | 245 | 246 | // returns 0 for success, -1 for error 247 | int iposix_stat(const char *path, iposix_stat_t *ostat) 248 | { 249 | char buf[IPOSIX_MAXBUFF]; 250 | iposix_path_stat(path, buf); 251 | return iposix_stat_imp(buf, ostat); 252 | } 253 | 254 | // returns 0 for success, -1 for error 255 | int iposix_lstat(const char *path, iposix_stat_t *ostat) 256 | { 257 | char buf[IPOSIX_MAXBUFF]; 258 | iposix_path_stat(path, buf); 259 | return iposix_lstat_imp(buf, ostat); 260 | } 261 | 262 | // get current directory 263 | char *iposix_getcwd(char *path, int size) 264 | { 265 | #ifdef _WIN32 266 | return _getcwd(path, size); 267 | #else 268 | return getcwd(path, size); 269 | #endif 270 | } 271 | 272 | // create directory 273 | int iposix_mkdir(const char *path, int mode) 274 | { 275 | #ifdef _WIN32 276 | return _mkdir(path); 277 | #else 278 | if (mode < 0) mode = 0755; 279 | return mkdir(path, mode); 280 | #endif 281 | } 282 | 283 | // change directory 284 | int iposix_chdir(const char *path) 285 | { 286 | #ifdef _WIN32 287 | return _chdir(path); 288 | #else 289 | return chdir(path); 290 | #endif 291 | } 292 | 293 | // check access 294 | int iposix_access(const char *path, int mode) 295 | { 296 | #ifdef _WIN32 297 | return _access(path, mode); 298 | #else 299 | return access(path, mode); 300 | #endif 301 | } 302 | 303 | // returns 1 for true 0 for false, -1 for not exist 304 | int iposix_path_isdir(const char *path) 305 | { 306 | iposix_stat_t s; 307 | int hr = iposix_stat(path, &s); 308 | if (hr != 0) return -1; 309 | return (ISTAT_ISDIR(s.st_mode))? 1 : 0; 310 | } 311 | 312 | // returns 1 for true 0 for false, -1 for not exist 313 | int iposix_path_isfile(const char *path) 314 | { 315 | iposix_stat_t s; 316 | int hr = iposix_stat(path, &s); 317 | if (hr != 0) return -1; 318 | return (ISTAT_ISDIR(s.st_mode))? 0 : 1; 319 | } 320 | 321 | // returns 1 for true 0 for false, -1 for not exist 322 | int iposix_path_islink(const char *path) 323 | { 324 | iposix_stat_t s; 325 | int hr = iposix_stat(path, &s); 326 | if (hr != 0) return -1; 327 | return (ISTAT_ISLNK(s.st_mode))? 1 : 0; 328 | } 329 | 330 | // returns 1 for true 0 for false 331 | int iposix_path_exists(const char *path) 332 | { 333 | iposix_stat_t s; 334 | int hr = iposix_stat(path, &s); 335 | if (hr != 0) return 0; 336 | return 1; 337 | } 338 | 339 | // returns file size, -1 for error 340 | IINT64 iposix_path_getsize(const char *path) 341 | { 342 | iposix_stat_t s; 343 | int hr = iposix_stat(path, &s); 344 | if (hr != 0) return -1; 345 | return (IINT64)s.st_size; 346 | } 347 | 348 | 349 | //--------------------------------------------------------------------- 350 | // Posix Path 351 | //--------------------------------------------------------------------- 352 | 353 | // 是否是绝对路径,如果是的话返回1,否则返回0 354 | int iposix_path_isabs(const char *path) 355 | { 356 | if (path == NULL) return 0; 357 | if (path[0] == '/') return 1; 358 | if (path[0] == 0) return 0; 359 | #ifdef _WIN32 360 | if (path[0] == IPATHSEP) return 1; 361 | if (isalpha(path[0]) && path[1] == ':') { 362 | if (path[2] == '/' || path[2] == '\\') return 1; 363 | } 364 | #endif 365 | return 0; 366 | } 367 | 368 | 369 | 370 | //--------------------------------------------------------------------- 371 | // iposix_string_t - basic string definition 372 | //--------------------------------------------------------------------- 373 | typedef struct 374 | { 375 | char *p; 376 | int l; 377 | int m; 378 | } iposix_string_t; 379 | 380 | 381 | //--------------------------------------------------------------------- 382 | // iposix_string_t interface 383 | //--------------------------------------------------------------------- 384 | #define _istrlen(s) ((s)->l) 385 | #define _istrch(s, i) (((i) >= 0)? ((s)->p)[i] : ((s)->p)[(s)->l + (i)]) 386 | 387 | static char *_istrset(iposix_string_t *s, const char *p, int max) 388 | { 389 | assert((max > 0) && p && s); 390 | s->p = (char*)p; 391 | s->l = strlen(p); 392 | s->m = max; 393 | return (char*)p; 394 | } 395 | 396 | static char *_istrcat(iposix_string_t *s, const char *p) 397 | { 398 | char *p1; 399 | 400 | assert(s && p); 401 | for (p1 = (char*)p; p1[0]; p1++, s->l++) { 402 | if (s->l >= s->m) break; 403 | s->p[s->l] = p1[0]; 404 | } 405 | return s->p; 406 | } 407 | 408 | static char *_istrcpy(iposix_string_t *s, const char *p) 409 | { 410 | assert(s && p); 411 | s->l = 0; 412 | return _istrcat(s, p); 413 | } 414 | 415 | static char *_istrcats(iposix_string_t *s1, const iposix_string_t *s2) 416 | { 417 | int i; 418 | assert(s1 && s2); 419 | for (i = 0; i < s2->l; i++, s1->l++) { 420 | if (s1->l >= s1->m) break; 421 | s1->p[s1->l] = s2->p[i]; 422 | } 423 | return s1->p; 424 | } 425 | 426 | static char *_icstr(iposix_string_t *s) 427 | { 428 | assert(s); 429 | if (s->l >= s->m) s->l = s->m - 1; 430 | if (s->l < 0) s->l = 0; 431 | s->p[s->l] = 0; 432 | return s->p; 433 | } 434 | 435 | static char _istrc(const iposix_string_t *s, int pos) 436 | { 437 | if (pos >= 0) return (pos > s->l)? 0 : s->p[pos]; 438 | return (pos < -(s->l))? 0 : s->p[s->l + pos]; 439 | } 440 | 441 | static char _istrchop(iposix_string_t *s) 442 | { 443 | char ch = _istrc(s, -1); 444 | s->l--; 445 | if (s->l < 0) s->l = 0; 446 | return ch; 447 | } 448 | 449 | static char *_istrctok(iposix_string_t *s, const char *p) 450 | { 451 | int i, k; 452 | 453 | assert(s && p); 454 | 455 | for (; _istrlen(s) > 0; ) { 456 | for (i = 0, k = 0; p[i] && k == 0; i++) { 457 | if (_istrc(s, -1) == p[i]) k++; 458 | } 459 | if (k == 0) break; 460 | _istrchop(s); 461 | } 462 | for (; _istrlen(s) > 0; ) { 463 | for (i = 0, k = 0; p[i] && k == 0; i++) { 464 | if (_istrc(s, -1) == p[i]) k++; 465 | } 466 | if (k) break; 467 | _istrchop(s); 468 | } 469 | 470 | return s->p; 471 | } 472 | 473 | static int _istrcmp(iposix_string_t *s, const char *p) 474 | { 475 | int i; 476 | for (i = 0; i < s->l && ((char*)p)[i]; i++) 477 | if (_istrc(s, i) != ((char*)p)[i]) break; 478 | if (((char*)p)[i] == 0 && i == s->l) return 0; 479 | return 1; 480 | } 481 | 482 | static char *_istrcatc(iposix_string_t *s, char ch) 483 | { 484 | char text[2] = " "; 485 | assert(s); 486 | text[0] = ch; 487 | return _istrcat(s, text); 488 | } 489 | 490 | static int istrtok(const char *p1, int *pos, const char *p2) 491 | { 492 | int i, j, k, r; 493 | 494 | assert(p1 && pos && p2); 495 | 496 | for (i = *pos; p1[i]; i++) { 497 | for (j = 0, k = 0; p2[j] && k == 0; j++) { 498 | if (p1[i] == p2[j]) k++; 499 | } 500 | if (k == 0) break; 501 | } 502 | *pos = i; 503 | r = i; 504 | 505 | if (p1[i] == 0) return -1; 506 | for (; p1[i]; i++) { 507 | for (j = 0, k = 0; p2[j] && k == 0; j++) { 508 | if (p1[i] == p2[j]) k++; 509 | } 510 | if (k) break; 511 | } 512 | *pos = i; 513 | 514 | return r; 515 | } 516 | 517 | 518 | //--------------------------------------------------------------------- 519 | // normalize path 520 | //--------------------------------------------------------------------- 521 | char *iposix_path_normal(const char *srcpath, char *path, int maxsize) 522 | { 523 | int i, p, c, k, r; 524 | iposix_string_t s1, s2; 525 | char *p1, *p2; 526 | char pp2[3]; 527 | 528 | assert(srcpath && path && maxsize > 0); 529 | 530 | if (srcpath[0] == 0) { 531 | if (maxsize > 0) path[0] = 0; 532 | return path; 533 | } 534 | 535 | for (p1 = (char*)srcpath; p1[0] && isspace((int)p1[0]); p1++); 536 | 537 | path[0] = 0; 538 | _istrset(&s1, path, maxsize); 539 | 540 | if (IPATHSEP == '\\') { 541 | pp2[0] = '/'; 542 | pp2[1] = '\\'; 543 | pp2[2] = 0; 544 | } else { 545 | pp2[0] = '/'; 546 | pp2[1] = 0; 547 | } 548 | 549 | p2 = pp2; 550 | 551 | if (p1[0] && p1[1] == ':' && (ISYSNAME == 'u' || ISYSNAME == 'w')) { 552 | _istrcatc(&s1, *p1++); 553 | _istrcatc(&s1, *p1++); 554 | } 555 | 556 | if (IPATHSEP == '/') { 557 | if (p1[0] == '/') _istrcatc(&s1, *p1++); 558 | } 559 | else if (p1[0] == '/' || p1[0] == IPATHSEP) { 560 | _istrcatc(&s1, IPATHSEP); 561 | p1++; 562 | } 563 | 564 | r = (_istrc(&s1, -1) == IPATHSEP)? 1 : 0; 565 | srcpath = (const char*)p1; 566 | 567 | for (i = 0, c = 0, k = 0; (p = istrtok(srcpath, &i, p2)) >= 0; k++) { 568 | s2.p = (char*)(srcpath + p); 569 | s2.l = s2.m = i - p; 570 | //_iputs(&s2); printf("*\n"); 571 | if (_istrcmp(&s2, ".") == 0) continue; 572 | if (_istrcmp(&s2, "..") == 0) { 573 | if (c != 0) { 574 | _istrctok(&s1, (IPATHSEP == '\\')? "/\\:" : "/"); 575 | c--; 576 | continue; 577 | } 578 | if (c == 0 && r) { 579 | continue; 580 | } 581 | } else { 582 | c++; 583 | } 584 | _istrcats(&s1, &s2); 585 | _istrcatc(&s1, IPATHSEP); 586 | } 587 | if (_istrlen(&s1) == 0) { 588 | _istrcpy(&s1, "."); 589 | } else { 590 | if (_istrc(&s1, -1) == IPATHSEP && c > 0) _istrchop(&s1); 591 | } 592 | return _icstr(&s1); 593 | } 594 | 595 | 596 | //--------------------------------------------------------------------- 597 | // join path 598 | //--------------------------------------------------------------------- 599 | char *iposix_path_join(const char *p1, const char *p2, char *path, int len) 600 | { 601 | iposix_string_t s; 602 | int maxsize = len; 603 | char *p, r; 604 | 605 | assert(p1 && p2 && maxsize > 0); 606 | 607 | for (; p1[0] && isspace((int)p1[0]); p1++); 608 | for (; p2[0] && isspace((int)p2[0]); p2++); 609 | r = 0; 610 | p = (char*)p2; 611 | if (IPATHSEP == '/') { 612 | if (p[0] == '/') r = 1; 613 | } else { 614 | if (p[0] == '/' || p[0] == IPATHSEP) r = 1; 615 | } 616 | 617 | if (p[0] && p[1] == ':' && (ISYSNAME == 'u' || ISYSNAME == 'w')) 618 | return iposix_path_normal(p2, path, maxsize); 619 | 620 | if (r && (p1[0] == 0 || p1[1] != ':' || p1[2])) 621 | return iposix_path_normal(p2, path, maxsize); 622 | 623 | p = (char*)malloc(maxsize + 10); 624 | 625 | if (p == NULL) { 626 | return iposix_path_normal(p1, path, maxsize); 627 | } 628 | 629 | iposix_path_normal(p1, p, maxsize); 630 | _istrset(&s, p, maxsize); 631 | 632 | r = 1; 633 | if (_istrlen(&s) <= 2 && _istrc(&s, 1) == ':') r = 0; 634 | if (_istrc(&s, -1) == IPATHSEP) r = 0; 635 | if (_istrlen(&s) == 0) r = 0; 636 | if (r) _istrcatc(&s, IPATHSEP); 637 | 638 | _istrcat(&s, p2); 639 | iposix_path_normal(_icstr(&s), path, maxsize); 640 | free(p); 641 | 642 | return path; 643 | } 644 | 645 | 646 | // 绝对路径 647 | char *iposix_path_abspath_u(const char *srcpath, char *path, int maxsize) 648 | { 649 | char *base; 650 | base = (char*)malloc(IPOSIX_MAXBUFF * 2); 651 | if (base == NULL) return NULL; 652 | iposix_getcwd(base, IPOSIX_MAXPATH); 653 | iposix_path_join(base, srcpath, path, maxsize); 654 | free(base); 655 | return path; 656 | } 657 | 658 | #ifdef _WIN32 659 | char *iposix_path_abspath_w(const char *srcpath, char *path, int maxsize) 660 | { 661 | char *fname; 662 | DWORD hr = GetFullPathNameA(srcpath, maxsize, path, &fname); 663 | if (hr == 0) return NULL; 664 | return path; 665 | } 666 | #endif 667 | 668 | 669 | // 绝对路径 670 | char *iposix_path_abspath(const char *srcpath, char *path, int maxsize) 671 | { 672 | #ifdef _WIN32 673 | return iposix_path_abspath_w(srcpath, path, maxsize); 674 | #else 675 | return iposix_path_abspath_u(srcpath, path, maxsize); 676 | #endif 677 | } 678 | 679 | // 路径分割:从右向左找到第一个"/"分成两个字符串 680 | int iposix_path_split(const char *path, char *p1, int l1, char *p2, int l2) 681 | { 682 | int length, i, k; 683 | length = (int)strlen(path); 684 | 685 | for (i = length - 1; i >= 0; i--) { 686 | if (IPATHSEP == '/') { 687 | if (path[i] == '/') break; 688 | } else { 689 | if (path[i] == '/' || path[i] == '\\') break; 690 | } 691 | } 692 | 693 | if (p1) { 694 | if (i < 0) { 695 | if (l1 > 0) p1[0] = 0; 696 | } 697 | else if (i == 0) { 698 | p1[0] = '/'; 699 | p1[1] = 0; 700 | } 701 | else { 702 | int size = i < l1 ? i : l1; 703 | memcpy(p1, path, size); 704 | if (size < l1) p1[size] = 0; 705 | } 706 | } 707 | 708 | k = length - i - 1; 709 | 710 | if (p2) { 711 | if (k <= 0) { 712 | if (l2 > 0) p2[0] = 0; 713 | } else { 714 | int size = k < l2 ? k : l2; 715 | memcpy(p2, path + i + 1, k); 716 | if (size < l2) p2[size] = 0; 717 | } 718 | } 719 | 720 | return 0; 721 | } 722 | 723 | 724 | // 扩展分割:分割文件主名与扩展名 725 | int iposix_path_splitext(const char *path, char *p1, int l1, 726 | char *p2, int l2) 727 | { 728 | int length, i, k, size; 729 | length = (int)strlen(path); 730 | for (i = length - 1, k = length; i >= 0; i--) { 731 | if (path[i] == '.') { 732 | k = i; 733 | break; 734 | } 735 | else if (IPATHSEP == '/') { 736 | if (path[i] == '/') break; 737 | 738 | } 739 | else { 740 | if (path[i] == '/' || path[i] == '\\') break; 741 | } 742 | } 743 | 744 | if (p1) { 745 | 746 | size = k < l1 ? k : l1; 747 | if (size > 0) memcpy(p1, path, size); 748 | if (size < l1) p1[size] = 0; 749 | } 750 | 751 | size = length - k - 1; 752 | if (size < 0) size = 0; 753 | size = size < l2 ? size : l2; 754 | 755 | if (p2) { 756 | if (size > 0) memcpy(p2, path + k + 1, size); 757 | if (size < l2) p2[size] = 0; 758 | } 759 | 760 | return 0; 761 | } 762 | 763 | 764 | //--------------------------------------------------------------------- 765 | // platform special 766 | //--------------------------------------------------------------------- 767 | 768 | // cross os GetModuleFileName, returns size for success, -1 for error 769 | int iposix_path_exepath(char *ptr, int size) 770 | { 771 | int retval = -1; 772 | #if defined(_WIN32) 773 | DWORD hr = GetModuleFileNameA(NULL, ptr, (DWORD)size); 774 | if (hr > 0) retval = (int)hr; 775 | #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) 776 | int mib[4]; 777 | size_t cb = (size_t)size; 778 | int hr; 779 | mib[0] = CTL_KERN; 780 | mib[1] = KERN_PROC; 781 | mib[2] = KERN_PROC_PATHNAME; 782 | mib[3] = -1; 783 | hr = sysctl(mib, 4, ptr, &cb, NULL, 0); 784 | if (hr >= 0) retval = (int)cb; 785 | #elif defined(linux) || defined(__CYGWIN__) 786 | FILE *fp; 787 | fp = fopen("/proc/self/exename", "r"); 788 | if (fp) { 789 | retval = fread(ptr, 1, size, fp); 790 | fclose(fp); 791 | } else { 792 | retval = 0; 793 | } 794 | #else 795 | #endif 796 | if (retval >= 0 && retval < size) { 797 | ptr[retval] = '\0'; 798 | } else if (size > 0) { 799 | ptr[0] = '\0'; 800 | } 801 | 802 | if (size > 0) ptr[size - 1] = 0; 803 | 804 | return retval; 805 | } 806 | 807 | // 取得进程可执行文件的目录 808 | int iposix_path_execwd(char *ptr, int size) 809 | { 810 | char *buffer; 811 | int retval; 812 | 813 | if (ptr) { 814 | if (size > 0) ptr[0] = 0; 815 | } 816 | 817 | buffer = (char*)malloc(IPOSIX_MAXBUFF * 2); 818 | if (buffer == NULL) { 819 | return -1; 820 | } 821 | 822 | retval = iposix_path_exepath(buffer, IPOSIX_MAXBUFF * 2); 823 | 824 | if (retval < 0) { 825 | free(buffer); 826 | return -2; 827 | } 828 | 829 | iposix_path_split(buffer, ptr, size, NULL, IPOSIX_MAXPATH); 830 | 831 | free(buffer); 832 | 833 | return 0; 834 | } 835 | 836 | 837 | // 递归创建路径:直接从 ilog移植过来 838 | int iposix_path_mkdir(const char *path, int mode) 839 | { 840 | int i, len; 841 | char str[IPOSIX_MAXBUFF]; 842 | 843 | len = (int)strlen(path); 844 | if (len > IPOSIX_MAXPATH) len = IPOSIX_MAXPATH; 845 | 846 | memcpy(str, path, len); 847 | str[len] = 0; 848 | 849 | #ifdef _WIN32 850 | for (i = 0; i < len; i++) { 851 | if (str[i] == '/') str[i] = '\\'; 852 | } 853 | #endif 854 | 855 | for (i = 0; i < len; i++) { 856 | if (str[i] == '/' || str[i] == '\\') { 857 | str[i] = '\0'; 858 | if (iposix_access(str, F_OK) != 0) { 859 | iposix_mkdir(str, mode); 860 | } 861 | str[i] = IPATHSEP; 862 | } 863 | } 864 | 865 | if (len > 0 && iposix_access(str, 0) != 0) { 866 | iposix_mkdir(str, mode); 867 | } 868 | 869 | return 0; 870 | } 871 | 872 | 873 | // 精简版取得可执行路径 874 | const char *iposix_get_exepath(void) 875 | { 876 | static int inited = 0; 877 | static char *ptr = NULL; 878 | if (inited == 0) { 879 | char *buffer = (char*)malloc(IPOSIX_MAXBUFF); 880 | char *b2; 881 | int size; 882 | if (buffer == NULL) { 883 | inited = -1; 884 | return ""; 885 | } 886 | if (iposix_path_exepath(buffer, IPOSIX_MAXPATH) != 0) { 887 | free(buffer); 888 | inited = -1; 889 | return ""; 890 | } 891 | size = (int)strlen(buffer); 892 | b2 = (char*)malloc(size + 1); 893 | if (b2 == NULL) { 894 | free(buffer); 895 | inited = -1; 896 | return ""; 897 | } 898 | memcpy(b2, buffer, size + 1); 899 | free(buffer); 900 | ptr = b2; 901 | inited = 1; 902 | } 903 | if (inited < 0) return ""; 904 | return ptr; 905 | } 906 | 907 | // 精简版取得可执行目录 908 | const char *iposix_get_execwd(void) 909 | { 910 | static int inited = 0; 911 | static char ptr[IPOSIX_MAXBUFF + 10]; 912 | if (inited == 0) { 913 | if (iposix_path_execwd(ptr, IPOSIX_MAXPATH) != 0) { 914 | inited = -1; 915 | return ""; 916 | } 917 | inited = 1; 918 | } 919 | if (inited < 0) return ""; 920 | return ptr; 921 | } 922 | 923 | #ifdef _MSC_VER 924 | #pragma warning(disable:4996) 925 | #endif 926 | 927 | // 文件路径格式化: 928 | // out - 输出路径,长度不小于 IPOSIX_MAXPATH 929 | // base - 根路径 930 | // ... - 后续的相对路径 931 | // 返回 - out 932 | // 假设可执行路径位于 /home/abc/work,那么: 933 | // iposix_path_format(out, iposix_get_execwd(), "images/%s", "abc.jpg") 934 | // 结果就是 /home/abc/work/images/abc.jpg 935 | char *iposix_path_format(char *out, const char *root, const char *fmt, ...) 936 | { 937 | char buffer[IPOSIX_MAXBUFF]; 938 | va_list argptr; 939 | va_start(argptr, fmt); 940 | vsprintf(buffer, fmt, argptr); 941 | va_end(argptr); 942 | return iposix_path_join(root, buffer, out, IPOSIX_MAXPATH); 943 | } 944 | 945 | 946 | 947 | /*-------------------------------------------------------------------*/ 948 | /* System Utilities */ 949 | /*-------------------------------------------------------------------*/ 950 | #ifndef IDISABLE_SHARED_LIBRARY 951 | #if defined(__unix) 952 | #include 953 | #endif 954 | #endif 955 | 956 | void *iposix_shared_open(const char *dllname) 957 | { 958 | #ifndef IDISABLE_SHARED_LIBRARY 959 | #ifdef __unix 960 | return dlopen(dllname, RTLD_LAZY); 961 | #else 962 | return (void*)LoadLibraryA(dllname); 963 | #endif 964 | #else 965 | return NULL; 966 | #endif 967 | } 968 | 969 | void *iposix_shared_get(void *shared, const char *name) 970 | { 971 | #ifndef IDISABLE_SHARED_LIBRARY 972 | #ifdef __unix 973 | return dlsym(shared, name); 974 | #else 975 | return (void*)GetProcAddress((HINSTANCE)shared, name); 976 | #endif 977 | #else 978 | return NULL; 979 | #endif 980 | } 981 | 982 | void iposix_shared_close(void *shared) 983 | { 984 | #ifndef IDISABLE_SHARED_LIBRARY 985 | #ifdef __unix 986 | dlclose(shared); 987 | #else 988 | FreeLibrary((HINSTANCE)shared); 989 | #endif 990 | #endif 991 | } 992 | 993 | /* load file content */ 994 | void *iposix_file_load_content(const char *filename, long *size) 995 | { 996 | size_t length, remain; 997 | char *ptr, *out; 998 | FILE *fp; 999 | 1000 | if ((fp = fopen(filename, "rb")) == NULL) { 1001 | if (size) size[0] = 0; 1002 | return NULL; 1003 | } 1004 | 1005 | fseek(fp, 0, SEEK_END); 1006 | length = ftell(fp); 1007 | fseek(fp, 0, SEEK_SET); 1008 | 1009 | // avoid zero-size file returns null 1010 | ptr = (char*)malloc(length + 8); 1011 | 1012 | if (ptr == NULL) { 1013 | fclose(fp); 1014 | if (size) size[0] = 0; 1015 | return NULL; 1016 | } 1017 | 1018 | for (remain = length, out = ptr; remain > 0; ) { 1019 | size_t ret = fread(out, 1, remain, fp); 1020 | if (ret == 0) break; 1021 | remain -= ret; 1022 | out += ret; 1023 | } 1024 | 1025 | fclose(fp); 1026 | 1027 | if (size) size[0] = length; 1028 | 1029 | return ptr; 1030 | } 1031 | 1032 | 1033 | /* save file content */ 1034 | int iposix_file_save_content(const char *filename, const void *data, long size) 1035 | { 1036 | const char *ptr = (const char*)data; 1037 | FILE *fp; 1038 | int hr = 0; 1039 | if ((fp = fopen(filename, "wb")) == NULL) return -1; 1040 | for (; size > 0; ) { 1041 | long written = (long)fwrite(ptr, 1, size, fp); 1042 | if (written <= 0) { 1043 | hr = -2; 1044 | break; 1045 | } 1046 | size -= written; 1047 | ptr += written; 1048 | } 1049 | fclose(fp); 1050 | return hr; 1051 | } 1052 | 1053 | 1054 | 1055 | #endif 1056 | 1057 | 1058 | 1059 | 1060 | -------------------------------------------------------------------------------- /system/iposix.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // iposix.h - posix file system accessing 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #ifndef __IPOSIX_H__ 10 | #define __IPOSIX_H__ 11 | 12 | #ifdef HAVE_CONFIG_H 13 | #include "config.h" 14 | #endif 15 | 16 | 17 | /*-------------------------------------------------------------------*/ 18 | /* C99 Compatible */ 19 | /*-------------------------------------------------------------------*/ 20 | #if defined(linux) || defined(__linux) || defined(__linux__) 21 | #ifdef _POSIX_C_SOURCE 22 | #if _POSIX_C_SOURCE < 200112L 23 | #undef _POSIX_C_SOURCE 24 | #endif 25 | #endif 26 | 27 | #ifndef _POSIX_C_SOURCE 28 | #define _POSIX_C_SOURCE 200112L 29 | #endif 30 | 31 | #ifdef _GNU_SOURCE 32 | #undef _GNU_SOURCE 33 | #endif 34 | 35 | #ifdef _BSD_SOURCE 36 | #undef _BSD_SOURCE 37 | #endif 38 | 39 | #ifdef __BSD_VISIBLE 40 | #undef __BSD_VISIBLE 41 | #endif 42 | 43 | #ifdef _XOPEN_SOURCE 44 | #undef _XOPEN_SOURCE 45 | #endif 46 | 47 | #define _GNU_SOURCE 1 48 | #define _BSD_SOURCE 1 49 | #define __BSD_VISIBLE 1 50 | #define _XOPEN_SOURCE 600 51 | #endif 52 | 53 | 54 | #ifndef IDISABLE_FILE_SYSTEM_ACCESS 55 | //--------------------------------------------------------------------- 56 | // Global Definition 57 | //--------------------------------------------------------------------- 58 | #ifndef __INTEGER_32_BITS__ 59 | #define __INTEGER_32_BITS__ 60 | #if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) 61 | typedef __UINT32_TYPE__ ISTDUINT32; 62 | typedef __INT32_TYPE__ ISTDINT32; 63 | #elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) 64 | typedef __UINT_FAST32_TYPE__ ISTDUINT32; 65 | typedef __INT_FAST32_TYPE__ ISTDINT32; 66 | #elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 67 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 68 | defined(_M_AMD64) 69 | typedef unsigned int ISTDUINT32; 70 | typedef int ISTDINT32; 71 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 72 | defined(__i386) || defined(_M_X86) 73 | typedef unsigned long ISTDUINT32; 74 | typedef long ISTDINT32; 75 | #elif defined(__MACOS__) 76 | typedef UInt32 ISTDUINT32; 77 | typedef SInt32 ISTDINT32; 78 | #elif defined(__APPLE__) && defined(__MACH__) 79 | #include 80 | typedef u_int32_t ISTDUINT32; 81 | typedef int32_t ISTDINT32; 82 | #elif defined(__BEOS__) 83 | #include 84 | typedef u_int32_t ISTDUINT32; 85 | typedef int32_t ISTDINT32; 86 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 87 | typedef unsigned __int32 ISTDUINT32; 88 | typedef __int32 ISTDINT32; 89 | #elif defined(__GNUC__) && (__GNUC__ > 3) 90 | #include 91 | typedef uint32_t ISTDUINT32; 92 | typedef int32_t ISTDINT32; 93 | #else 94 | typedef unsigned long ISTDUINT32; 95 | typedef long ISTDINT32; 96 | #endif 97 | #endif 98 | 99 | 100 | #if (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOS__) 101 | #ifndef __unix 102 | #define __unix 1 103 | #endif 104 | #endif 105 | 106 | #if defined(__unix__) || defined(unix) || defined(__linux) 107 | #ifndef __unix 108 | #define __unix 1 109 | #endif 110 | #endif 111 | 112 | #include 113 | #ifdef __unix 114 | #include 115 | #define IPATHSEP '/' 116 | #else 117 | #include 118 | #if defined(_WIN32) 119 | #define IPATHSEP '\\' 120 | #else 121 | #define IPATHSEP '/' 122 | #endif 123 | #endif 124 | 125 | 126 | #ifndef __IINT8_DEFINED 127 | #define __IINT8_DEFINED 128 | typedef char IINT8; 129 | #endif 130 | 131 | #ifndef __IUINT8_DEFINED 132 | #define __IUINT8_DEFINED 133 | typedef unsigned char IUINT8; 134 | #endif 135 | 136 | #ifndef __IUINT16_DEFINED 137 | #define __IUINT16_DEFINED 138 | typedef unsigned short IUINT16; 139 | #endif 140 | 141 | #ifndef __IINT16_DEFINED 142 | #define __IINT16_DEFINED 143 | typedef short IINT16; 144 | #endif 145 | 146 | #ifndef __IINT32_DEFINED 147 | #define __IINT32_DEFINED 148 | typedef ISTDINT32 IINT32; 149 | #endif 150 | 151 | #ifndef __IUINT32_DEFINED 152 | #define __IUINT32_DEFINED 153 | typedef ISTDUINT32 IUINT32; 154 | #endif 155 | 156 | #ifndef __IINT64_DEFINED 157 | #define __IINT64_DEFINED 158 | #if defined(_MSC_VER) || defined(__BORLANDC__) 159 | typedef __int64 IINT64; 160 | #else 161 | typedef long long IINT64; 162 | #endif 163 | #endif 164 | 165 | #ifndef __IUINT64_DEFINED 166 | #define __IUINT64_DEFINED 167 | #if defined(_MSC_VER) || defined(__BORLANDC__) 168 | typedef unsigned __int64 IUINT64; 169 | #else 170 | typedef unsigned long long IUINT64; 171 | #endif 172 | #endif 173 | 174 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 175 | #ifndef _WIN32 176 | #define _WIN32 177 | #endif 178 | #endif 179 | 180 | 181 | #ifdef __cplusplus 182 | extern "C" { 183 | #endif 184 | 185 | //--------------------------------------------------------------------- 186 | // Posix Stat 187 | //--------------------------------------------------------------------- 188 | #define ISTAT_IFMT 0170000 // file type mask 189 | #define ISTAT_IFIFO 0010000 // named pipe (fifo) 190 | #define ISTAT_IFCHR 0020000 // charactor special 191 | #define ISTAT_IFDIR 0040000 // directory 192 | #define ISTAT_IFBLK 0060000 // block special 193 | #define ISTAT_IFREG 0100000 // regular 194 | #define ISTAT_IFLNK 0120000 // symbolic link 195 | #define ISTAT_IFSOCK 0140000 // socket 196 | #define ISTAT_IFWHT 0160000 // whiteout 197 | #define ISTAT_ISUID 0004000 // set user id on execution 198 | #define ISTAT_ISGID 0002000 // set group id on execution 199 | #define ISTAT_ISVXT 0001000 // swapped text even after use 200 | #define ISTAT_IRWXU 0000700 // owner RWX mask 201 | #define ISTAT_IRUSR 0000400 // owner read permission 202 | #define ISTAT_IWUSR 0000200 // owner writer permission 203 | #define ISTAT_IXUSR 0000100 // owner execution permission 204 | #define ISTAT_IRWXG 0000070 // group RWX mask 205 | #define ISTAT_IRGRP 0000040 // group read permission 206 | #define ISTAT_IWGRP 0000020 // group write permission 207 | #define ISTAT_IXGRP 0000010 // group execution permission 208 | #define ISTAT_IRWXO 0000007 // other RWX mask 209 | #define ISTAT_IROTH 0000004 // other read permission 210 | #define ISTAT_IWOTH 0000002 // other writer permission 211 | #define ISTAT_IXOTH 0000001 // other execution permission 212 | 213 | #define ISTAT_ISFMT(m, t) (((m) & ISTAT_IFMT) == (t)) 214 | #define ISTAT_ISDIR(m) ISTAT_ISFMT(m, ISTAT_IFDIR) 215 | #define ISTAT_ISCHR(m) ISTAT_ISFMT(m, ISTAT_IFCHR) 216 | #define ISTAT_ISBLK(m) ISTAT_ISFMT(m, ISTAT_IFBLK) 217 | #define ISTAT_ISREG(m) ISTAT_ISFMT(m, ISTAT_IFREG) 218 | #define ISTAT_ISFIFO(m) ISTAT_ISFMT(m, ISTAT_IFIFO) 219 | #define ISTAT_ISLNK(m) ISTAT_ISFMT(m, ISTAT_IFLNK) 220 | #define ISTAT_ISSOCK(m) ISTAT_ISFMT(m, ISTAT_IFSOCK) 221 | #define ISTAT_ISWHT(m) ISTAT_ISFMT(m, ISTAT_IFWHT) 222 | 223 | struct IPOSIX_STAT 224 | { 225 | IUINT32 st_mode; 226 | IUINT64 st_ino; 227 | IUINT32 st_dev; 228 | IUINT32 st_nlink; 229 | IUINT32 st_uid; 230 | IUINT32 st_gid; 231 | IUINT64 st_size; 232 | IUINT32 atime; 233 | IUINT32 mtime; 234 | IUINT32 ctime; 235 | IUINT32 st_blocks; 236 | IUINT32 st_blksize; 237 | IUINT32 st_rdev; 238 | IUINT32 st_flags; 239 | }; 240 | 241 | typedef struct IPOSIX_STAT iposix_stat_t; 242 | 243 | #define IPOSIX_MAXPATH 1024 244 | #define IPOSIX_MAXBUFF ((IPOSIX_MAXPATH) + 8) 245 | 246 | 247 | // returns 0 for success, -1 for error 248 | int iposix_stat(const char *path, iposix_stat_t *ostat); 249 | 250 | // returns 0 for success, -1 for error 251 | int iposix_lstat(const char *path, iposix_stat_t *ostat); 252 | 253 | // returns 0 for success, -1 for error 254 | int iposix_fstat(int fd, iposix_stat_t *ostat); 255 | 256 | // get current directory 257 | char *iposix_getcwd(char *path, int size); 258 | 259 | // create directory 260 | int iposix_mkdir(const char *path, int mode); 261 | 262 | // change directory 263 | int iposix_chdir(const char *path); 264 | 265 | #ifndef F_OK 266 | #define F_OK 0 267 | #endif 268 | 269 | #ifndef X_OK 270 | #define X_OK 1 271 | #endif 272 | 273 | #ifndef W_OK 274 | #define W_OK 2 275 | #endif 276 | 277 | #ifndef R_OK 278 | #define R_OK 4 279 | #endif 280 | 281 | // check access 282 | int iposix_access(const char *path, int mode); 283 | 284 | 285 | // returns 1 for true 0 for false, -1 for not exist 286 | int iposix_path_isdir(const char *path); 287 | 288 | // returns 1 for true 0 for false, -1 for not exist 289 | int iposix_path_isfile(const char *path); 290 | 291 | // returns 1 for true 0 for false, -1 for not exist 292 | int iposix_path_islink(const char *path); 293 | 294 | // returns 1 for true 0 for false 295 | int iposix_path_exists(const char *path); 296 | 297 | // returns file size, -1 for error 298 | IINT64 iposix_path_getsize(const char *path); 299 | 300 | 301 | //--------------------------------------------------------------------- 302 | // Posix Path 303 | //--------------------------------------------------------------------- 304 | 305 | // 是否是绝对路径,如果是的话返回1,否则返回0 306 | int iposix_path_isabs(const char *path); 307 | 308 | // 绝对路径 309 | char *iposix_path_abspath(const char *srcpath, char *path, int maxsize); 310 | 311 | // 归一化路径:去掉重复斜杠,以及处理掉".", ".."等。 312 | char *iposix_path_normal(const char *srcpath, char *path, int maxsize); 313 | 314 | // 连接路径 315 | char *iposix_path_join(const char *p1, const char *p2, char *path, int len); 316 | 317 | // 路径分割:从右向左找到第一个"/"分成两个字符串 318 | int iposix_path_split(const char *path, char *p1, int l1, char *p2, int l2); 319 | 320 | // 扩展分割:分割文件主名与扩展名 321 | int iposix_path_splitext(const char *path, char *p1, int l1, 322 | char *p2, int l2); 323 | 324 | 325 | //--------------------------------------------------------------------- 326 | // platform special 327 | //--------------------------------------------------------------------- 328 | 329 | // 取得进程可执行文件的文件名 330 | int iposix_path_exepath(char *ptr, int size); 331 | 332 | // 取得进程可执行文件的目录 333 | int iposix_path_execwd(char *ptr, int size); 334 | 335 | // 递归创建路径 336 | int iposix_path_mkdir(const char *path, int mode); 337 | 338 | // 精简版取得可执行路径 339 | const char *iposix_get_exepath(void); 340 | 341 | // 精简版取得可执行目录 342 | const char *iposix_get_execwd(void); 343 | 344 | 345 | // 文件路径格式化: 346 | // out - 输出路径,长度不小于 IPOSIX_MAXPATH 347 | // root - 根路径 348 | // ... - 后续的相对路径 349 | // 返回 - out 350 | // 假设可执行路径位于 /home/abc/work,那么: 351 | // iposix_path_format(out, iposix_get_execwd(), "images/%s", "abc.jpg") 352 | // 结果就是 /home/abc/work/images/abc.jpg 353 | char *iposix_path_format(char *out, const char *root, const char *fmt, ...); 354 | 355 | 356 | 357 | //--------------------------------------------------------------------- 358 | // System Utilities 359 | //--------------------------------------------------------------------- 360 | 361 | #ifndef IDISABLE_SHARED_LIBRARY 362 | 363 | /* LoadLibraryA */ 364 | void *iposix_shared_open(const char *dllname); 365 | 366 | /* GetProcAddress */ 367 | void *iposix_shared_get(void *shared, const char *name); 368 | 369 | /* FreeLibrary */ 370 | void iposix_shared_close(void *shared); 371 | 372 | #endif 373 | 374 | #ifndef IDISABLE_FILE_SYSTEM_ACCESS 375 | 376 | /* load file content, use free to dispose */ 377 | void *iposix_file_load_content(const char *filename, long *size); 378 | 379 | /* save file content */ 380 | int iposix_file_save_content(const char *filename, const void *data, long size); 381 | 382 | /* cross os GetModuleFileName, returns size for success, -1 for error */ 383 | int iposix_get_proc_pathname(char *ptr, int size); 384 | 385 | #endif 386 | 387 | 388 | 389 | #ifdef __cplusplus 390 | } 391 | #endif 392 | 393 | 394 | #endif 395 | 396 | 397 | #endif 398 | 399 | 400 | 401 | 402 | -------------------------------------------------------------------------------- /system/isecure.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // isecure.h - secure hash encrypt 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | // Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. 9 | // Copyright 2014 Melissa O'Neill 10 | // 11 | //===================================================================== 12 | #ifndef __ISECURE_H__ 13 | #define __ISECURE_H__ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | //===================================================================== 23 | // 32BIT INTEGER DEFINITION 24 | //===================================================================== 25 | #ifndef __INTEGER_32_BITS__ 26 | #define __INTEGER_32_BITS__ 27 | #if defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 28 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 29 | defined(_M_AMD64) 30 | typedef unsigned int ISTDUINT32; 31 | typedef int ISTDINT32; 32 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 33 | defined(__i386) || defined(_M_X86) 34 | typedef unsigned long ISTDUINT32; 35 | typedef long ISTDINT32; 36 | #elif defined(__MACOS__) 37 | typedef UInt32 ISTDUINT32; 38 | typedef SInt32 ISTDINT32; 39 | #elif defined(__APPLE__) && defined(__MACH__) 40 | #include 41 | typedef u_int32_t ISTDUINT32; 42 | typedef int32_t ISTDINT32; 43 | #elif defined(__BEOS__) 44 | #include 45 | typedef u_int32_t ISTDUINT32; 46 | typedef int32_t ISTDINT32; 47 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 48 | typedef unsigned __int32 ISTDUINT32; 49 | typedef __int32 ISTDINT32; 50 | #elif defined(__GNUC__) 51 | #include 52 | typedef uint32_t ISTDUINT32; 53 | typedef int32_t ISTDINT32; 54 | #else 55 | typedef unsigned long ISTDUINT32; 56 | typedef long ISTDINT32; 57 | #endif 58 | #endif 59 | 60 | 61 | //===================================================================== 62 | // Global Macros 63 | //===================================================================== 64 | #ifndef __IINT8_DEFINED 65 | #define __IINT8_DEFINED 66 | typedef char IINT8; 67 | #endif 68 | 69 | #ifndef __IUINT8_DEFINED 70 | #define __IUINT8_DEFINED 71 | typedef unsigned char IUINT8; 72 | #endif 73 | 74 | #ifndef __IUINT16_DEFINED 75 | #define __IUINT16_DEFINED 76 | typedef unsigned short IUINT16; 77 | #endif 78 | 79 | #ifndef __IINT16_DEFINED 80 | #define __IINT16_DEFINED 81 | typedef short IINT16; 82 | #endif 83 | 84 | #ifndef __IINT32_DEFINED 85 | #define __IINT32_DEFINED 86 | typedef ISTDINT32 IINT32; 87 | #endif 88 | 89 | #ifndef __IUINT32_DEFINED 90 | #define __IUINT32_DEFINED 91 | typedef ISTDUINT32 IUINT32; 92 | #endif 93 | 94 | #ifndef __IINT64_DEFINED 95 | #define __IINT64_DEFINED 96 | #if defined(_MSC_VER) || defined(__BORLANDC__) 97 | typedef __int64 IINT64; 98 | #else 99 | typedef long long IINT64; 100 | #endif 101 | #endif 102 | 103 | #ifndef __IUINT64_DEFINED 104 | #define __IUINT64_DEFINED 105 | #if defined(_MSC_VER) || defined(__BORLANDC__) 106 | typedef unsigned __int64 IUINT64; 107 | #else 108 | typedef unsigned long long IUINT64; 109 | #endif 110 | #endif 111 | 112 | #ifndef INLINE 113 | #if defined(__GNUC__) 114 | 115 | #if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) 116 | #define INLINE __inline__ __attribute__((always_inline)) 117 | #else 118 | #define INLINE __inline__ 119 | #endif 120 | 121 | #elif (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__WATCOMC__)) 122 | #define INLINE __inline 123 | #else 124 | #define INLINE 125 | #endif 126 | #endif 127 | 128 | #if (!defined(__cplusplus)) && (!defined(inline)) 129 | #define inline INLINE 130 | #endif 131 | 132 | 133 | //===================================================================== 134 | // DETECTION WORD ORDER 135 | //===================================================================== 136 | #ifndef IWORDS_BIG_ENDIAN 137 | #ifdef _BIG_ENDIAN_ 138 | #if _BIG_ENDIAN_ 139 | #define IWORDS_BIG_ENDIAN 1 140 | #endif 141 | #endif 142 | #ifndef IWORDS_BIG_ENDIAN 143 | #if defined(__hppa__) || \ 144 | defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ 145 | (defined(__MIPS__) && defined(__MISPEB__)) || \ 146 | defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ 147 | defined(__sparc__) || defined(__powerpc__) || \ 148 | defined(__mc68000__) || defined(__s390x__) || defined(__s390__) 149 | #define IWORDS_BIG_ENDIAN 1 150 | #endif 151 | #endif 152 | #ifndef IWORDS_BIG_ENDIAN 153 | #define IWORDS_BIG_ENDIAN 0 154 | #endif 155 | #endif 156 | 157 | #ifndef IASSERT 158 | #define IASSERT(x) assert(x) 159 | #endif 160 | 161 | 162 | #ifdef __cplusplus 163 | extern "C" { 164 | #endif 165 | 166 | //===================================================================== 167 | // Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. 168 | //===================================================================== 169 | typedef struct 170 | { 171 | IUINT32 i[2]; /* Number of _bits_ handled mod 2^64 */ 172 | IUINT32 buf[4]; /* Scratch buffer */ 173 | unsigned char in[64]; /* Input buffer */ 174 | } HASH_MD5_CTX; 175 | 176 | void HASH_MD5_Init(HASH_MD5_CTX *ctx, unsigned long RandomNumber); 177 | void HASH_MD5_Update(HASH_MD5_CTX *ctx, const void *input, unsigned int len); 178 | void HASH_MD5_Final(HASH_MD5_CTX *ctx, unsigned char digest[16]); 179 | 180 | 181 | 182 | //===================================================================== 183 | // From http://www.mirrors.wiretapped.net/security/cryptography 184 | //===================================================================== 185 | typedef struct { 186 | IUINT32 state[5]; 187 | IUINT32 count[2]; 188 | unsigned char buffer[64]; 189 | } HASH_SHA1_CTX; 190 | 191 | void HASH_SHA1_Init(HASH_SHA1_CTX *ctx); 192 | void HASH_SHA1_Update(HASH_SHA1_CTX *ctx, const void *input, unsigned int len); 193 | void HASH_SHA1_Final(HASH_SHA1_CTX *ctx, unsigned char digest[20]); 194 | 195 | 196 | //===================================================================== 197 | // UTILITIES 198 | //===================================================================== 199 | 200 | // convert digests to string 201 | char* hash_digest_to_string(const unsigned char *in, int size, char *out); 202 | 203 | // calculate md5sum and convert digests to string 204 | char* hash_md5sum(const void *in, unsigned int len, char *out); 205 | 206 | // calculate sha1sum and convert digests to string 207 | char* hash_sha1sum(const void *in, unsigned int len, char *out); 208 | 209 | // calculate crc32 and return result 210 | IUINT32 hash_crc32(const void *in, unsigned int len); 211 | 212 | // sum all bytes together 213 | IUINT32 hash_checksum(const void *in, unsigned int len); 214 | 215 | 216 | //===================================================================== 217 | // Diffie-Hellman key exchange 218 | // http://zh.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange 219 | // usage: 1. get an local asymmetric-key a from DH_Random 220 | // 2. calculate A=(5 ^ a) % p by DH_Exchange 221 | // 3. send A to remote 222 | // 4. obtain symmetrical-key by DH_Key(local_key, RemoteA) 223 | //===================================================================== 224 | 225 | // returns random local key 226 | IUINT64 DH_Random(); 227 | 228 | // calculate A/B which will be sent to remote 229 | IUINT64 DH_Exchange(IUINT64 local); 230 | 231 | // get final symmetrical-key from local key and remote A/B 232 | IUINT64 DH_Final(IUINT64 local, IUINT64 remote); 233 | 234 | // get qword from hex string 235 | void DH_STR_TO_U64(const char *str, IUINT64 *x); 236 | 237 | // hex string from qword, capacity of str must above 17 238 | void DH_U64_TO_STR(IUINT64 x, char *str); 239 | 240 | 241 | //===================================================================== 242 | // CRYPTO RC4 243 | //===================================================================== 244 | typedef struct { 245 | int x; 246 | int y; 247 | unsigned char box[256]; 248 | } CRYPTO_RC4_CTX; 249 | 250 | 251 | void CRYPTO_RC4_Init(CRYPTO_RC4_CTX *ctx, const void *key, int keylen); 252 | 253 | void CRYPTO_RC4_Apply(CRYPTO_RC4_CTX *ctx, const void *in, void *out, 254 | size_t size); 255 | 256 | void CRYPTO_RC4_Crypto(const void *key, int keylen, const void *in, 257 | void *out, size_t size, int ntimes); 258 | 259 | 260 | 261 | //===================================================================== 262 | // CRYPTO XTEA: https://en.wikipedia.org/wiki/XTEA 263 | //===================================================================== 264 | 265 | void CRYPTO_XTEA_Encipher(int nrounds, const IUINT32 key[4], IUINT32 v[2]); 266 | 267 | void CRYPTO_XTEA_Decipher(int nrounds, const IUINT32 key[4], IUINT32 v[2]); 268 | 269 | 270 | //===================================================================== 271 | // LCG: https://en.wikipedia.org/wiki/Linear_congruential_generator 272 | //===================================================================== 273 | 274 | // rand() in stdlib.h (c99), output range: 0 <= x <= 32767 275 | IUINT32 random_std_c99(IUINT32 *seed); 276 | 277 | // rand() in stdlib.h (msvc), output range: 0 <= x <= 32767 278 | IUINT32 random_std_msvc(IUINT32 *seed); 279 | 280 | // minstd_rand in C++, output range: 0 <= x < 0x7fffffff 281 | IUINT32 random_std_cpp(IUINT32 *seed); 282 | 283 | 284 | //===================================================================== 285 | // Statistically perfect random generator 286 | //===================================================================== 287 | typedef struct 288 | { 289 | IUINT32 seed; // random seed 290 | IUINT32 size; // array size 291 | IUINT32 avail; // available numbers 292 | IUINT32 *state; // states array 293 | } RANDOM_BOX; 294 | 295 | 296 | // initialize random box 297 | void RANDOM_BOX_Init(RANDOM_BOX *box, IUINT32 *state, IUINT32 size); 298 | 299 | // change seed 300 | void RANDOM_BOX_Seed(RANDOM_BOX *box, IUINT32 seed); 301 | 302 | // next random number within 0 <= x < size 303 | IUINT32 RANDOM_BOX_Next(RANDOM_BOX *box); 304 | 305 | 306 | //===================================================================== 307 | // PCG: PCG is a family of simple fast statistically good algorithms 308 | //===================================================================== 309 | typedef struct 310 | { 311 | IUINT64 state; // RNG state. All values are possible. 312 | IUINT64 inc; // Must *always* be odd. 313 | } RANDOM_PCG; 314 | 315 | // initialize pcg 316 | void RANDOM_PCG_Init(RANDOM_PCG *pcg, IUINT64 initstate, IUINT64 initseq); 317 | 318 | // next random number 319 | IUINT32 RANDOM_PCG_Next(RANDOM_PCG *pcg); 320 | 321 | // next random number within 0 <= x < bound 322 | IUINT32 RANDOM_PCG_RANGE(RANDOM_PCG *pcg, IUINT32 bound); 323 | 324 | 325 | #ifdef __cplusplus 326 | } 327 | #endif 328 | 329 | #endif 330 | 331 | 332 | -------------------------------------------------------------------------------- /system/itimer.c: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // itimer.c - Application Level Implementation of Linux Kernel Timer 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #include 10 | #include 11 | 12 | #include "itimer.h" 13 | 14 | //===================================================================== 15 | // Local Definition 16 | //===================================================================== 17 | #define ITIMER_NODE_STATE_OK 0x1981 18 | #define ITIMER_NODE_STATE_BAD 0x2014 19 | 20 | static void itimer_internal_add(itimer_core *core, itimer_node *node); 21 | static void itimer_internal_cascade(struct itimer_vec *vec, int index); 22 | static void itimer_internal_update(itimer_core *core, IUINT32 jiffies); 23 | 24 | 25 | //--------------------------------------------------------------------- 26 | // initialize timer core 27 | //--------------------------------------------------------------------- 28 | void itimer_core_init(itimer_core *core, IUINT32 jiffies) 29 | { 30 | union { struct itimer_vec *vn; struct itimer_vec_root *vr; } uv; 31 | int i; 32 | 33 | uv.vr = &core->tv1; 34 | core->timer_jiffies = jiffies; 35 | core->tvecs[0] = uv.vn; 36 | core->tvecs[1] = &core->tv2; 37 | core->tvecs[2] = &core->tv3; 38 | core->tvecs[3] = &core->tv4; 39 | core->tvecs[4] = &core->tv5; 40 | 41 | for (i = 0; i < ITVR_SIZE; i++) { 42 | ilist_init(&core->tv1.vec[i]); 43 | } 44 | 45 | for (i = 0; i < ITVN_SIZE; i++) { 46 | ilist_init(&core->tv2.vec[i]); 47 | ilist_init(&core->tv3.vec[i]); 48 | ilist_init(&core->tv4.vec[i]); 49 | ilist_init(&core->tv5.vec[i]); 50 | } 51 | } 52 | 53 | 54 | //--------------------------------------------------------------------- 55 | // destroy timer core 56 | //--------------------------------------------------------------------- 57 | void itimer_core_destroy(itimer_core *core) 58 | { 59 | int i, j; 60 | for (i = 0; i < 5; i++) { 61 | int count = (i == 0)? ITVR_SIZE : ITVN_SIZE; 62 | for (j = 0; j < count; j++) { 63 | ilist_head *root = &(core->tv1.vec[j]); 64 | if (i > 0) root = &(core->tvecs[i]->vec[j]); 65 | while (!ilist_is_empty(root)) { 66 | itimer_node *node = ilist_entry(root->next, 67 | itimer_node, head); 68 | if (!ilist_is_empty(&node->head)) { 69 | ilist_del_init(&node->head); 70 | } 71 | node->core = NULL; 72 | } 73 | } 74 | } 75 | } 76 | 77 | 78 | //--------------------------------------------------------------------- 79 | // run timer core 80 | //--------------------------------------------------------------------- 81 | void itimer_core_run(itimer_core *core, IUINT32 jiffies) 82 | { 83 | itimer_internal_update(core, jiffies); 84 | } 85 | 86 | 87 | //--------------------------------------------------------------------- 88 | // initialize node 89 | //--------------------------------------------------------------------- 90 | void itimer_node_init(itimer_node *node, void (*fn)(void*), void *data) 91 | { 92 | ilist_init(&node->head); 93 | node->expires = 0; 94 | node->state = ITIMER_NODE_STATE_OK; 95 | node->callback = fn; 96 | node->data = data; 97 | node->core = NULL; 98 | } 99 | 100 | 101 | //--------------------------------------------------------------------- 102 | // destroy node 103 | //--------------------------------------------------------------------- 104 | void itimer_node_destroy(itimer_node *node) 105 | { 106 | if (node->state != ITIMER_NODE_STATE_OK) { 107 | assert(node->state == ITIMER_NODE_STATE_OK); 108 | return ; 109 | } 110 | if (!ilist_is_empty(&node->head)) { 111 | ilist_del_init(&node->head); 112 | node->core = NULL; 113 | } 114 | node->state = ITIMER_NODE_STATE_BAD; 115 | node->callback = NULL; 116 | node->data = NULL; 117 | node->core = NULL; 118 | node->expires = 0; 119 | } 120 | 121 | 122 | //--------------------------------------------------------------------- 123 | // add node to core 124 | //--------------------------------------------------------------------- 125 | void itimer_node_add(itimer_core *core, itimer_node *node, IUINT32 expires) 126 | { 127 | if (node->state != ITIMER_NODE_STATE_OK) { 128 | assert(node->state == ITIMER_NODE_STATE_OK); 129 | return ; 130 | } 131 | 132 | if (!ilist_is_empty(&node->head)) { 133 | ilist_del_init(&node->head); 134 | node->core = NULL; 135 | } 136 | 137 | node->expires = expires; 138 | 139 | itimer_internal_add(core, node); 140 | } 141 | 142 | 143 | //--------------------------------------------------------------------- 144 | // remove node from core 145 | //--------------------------------------------------------------------- 146 | int itimer_node_del(itimer_core *core, itimer_node *node) 147 | { 148 | if (node->state != ITIMER_NODE_STATE_OK) { 149 | assert(node->state == ITIMER_NODE_STATE_OK); 150 | return -1; 151 | } 152 | if (!ilist_is_empty(&node->head)) { 153 | assert(node->core != NULL); 154 | ilist_del_init(&node->head); 155 | node->core = NULL; 156 | return 1; 157 | } 158 | return 0; 159 | } 160 | 161 | 162 | //--------------------------------------------------------------------- 163 | // modify node 164 | //--------------------------------------------------------------------- 165 | int itimer_node_mod(itimer_core *core, itimer_node *node, IUINT32 expires) 166 | { 167 | int ret = itimer_node_del(core, node); 168 | itimer_node_add(core, node, expires); 169 | return ret; 170 | } 171 | 172 | 173 | //--------------------------------------------------------------------- 174 | // itimer_internal_add 175 | //--------------------------------------------------------------------- 176 | static void itimer_internal_add(itimer_core *core, itimer_node *node) 177 | { 178 | IUINT32 expires = node->expires; 179 | IUINT32 idx = expires - core->timer_jiffies; 180 | ilist_head *vec = NULL; 181 | 182 | if (idx < ITVR_SIZE) { 183 | int i = expires & ITVR_MASK; 184 | vec = core->tv1.vec + i; 185 | } 186 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS))) { 187 | int i = (expires >> ITVR_BITS) & ITVN_MASK; 188 | vec = core->tv2.vec + i; 189 | } 190 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS * 2))) { 191 | int i = (expires >> (ITVR_BITS + ITVN_BITS)) & ITVN_MASK; 192 | vec = core->tv3.vec + i; 193 | } 194 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS * 3))) { 195 | int i = (expires >> (ITVR_BITS + ITVN_BITS * 2)) & ITVN_MASK; 196 | vec = core->tv4.vec + i; 197 | } 198 | else if ((IINT32)idx < 0) { 199 | vec = core->tv1.vec + (core->timer_jiffies & ITVR_MASK); 200 | } 201 | else { 202 | int i = (expires >> (ITVR_BITS + ITVN_BITS * 3)) & ITVN_MASK; 203 | vec = core->tv5.vec + i; 204 | } 205 | 206 | ilist_add_tail(&node->head, vec); 207 | node->core = core; 208 | } 209 | 210 | 211 | //--------------------------------------------------------------------- 212 | // itimer_internal_cascade 213 | //--------------------------------------------------------------------- 214 | static void itimer_internal_cascade(struct itimer_vec *tv, int index) 215 | { 216 | ilist_head queued; 217 | ilist_init(&queued); 218 | ilist_splice_init(tv->vec + index, &queued); 219 | while (!ilist_is_empty(&queued)) { 220 | itimer_node *node; 221 | node = ilist_entry(queued.next, itimer_node, head); 222 | ilist_del_init(&node->head); 223 | itimer_internal_add(node->core, node); 224 | } 225 | } 226 | 227 | 228 | //--------------------------------------------------------------------- 229 | // itimer_internal_update 230 | //--------------------------------------------------------------------- 231 | static void itimer_internal_update(itimer_core *core, IUINT32 jiffies) 232 | { 233 | #define ITIMER_INDEX(C, N) \ 234 | (((C)->timer_jiffies >> (ITVR_BITS + (N) * ITVN_BITS)) & ITVN_MASK) 235 | while ((IINT32)(jiffies - core->timer_jiffies) >= 0) { 236 | ilist_head queued; 237 | int index = core->timer_jiffies & ITVR_MASK; 238 | ilist_init(&queued); 239 | if (index == 0) { 240 | int i = ITIMER_INDEX(core, 0); 241 | itimer_internal_cascade(&core->tv2, i); 242 | if (i == 0) { 243 | i = ITIMER_INDEX(core, 1); 244 | itimer_internal_cascade(&core->tv3, i); 245 | if (i == 0) { 246 | i = ITIMER_INDEX(core, 2); 247 | itimer_internal_cascade(&core->tv4, i); 248 | if (i == 0) { 249 | i = ITIMER_INDEX(core, 3); 250 | itimer_internal_cascade(&core->tv5, i); 251 | } 252 | } 253 | } 254 | } 255 | core->timer_jiffies++; 256 | ilist_splice_init(core->tv1.vec + index, &queued); 257 | while (!ilist_is_empty(&queued)) { 258 | itimer_node *node; 259 | void (*fn)(void*); 260 | void *data; 261 | node = ilist_entry(queued.next, itimer_node, head); 262 | fn = node->callback; 263 | data = node->data; 264 | ilist_del_init(&node->head); 265 | node->core = NULL; 266 | if (fn) fn(data); 267 | } 268 | } 269 | #undef ITIMER_INDEX 270 | } 271 | 272 | 273 | 274 | //===================================================================== 275 | // Timer Manager 276 | //===================================================================== 277 | 278 | // initialize timer manager 279 | // interval - internal working interval 280 | void itimer_mgr_init(itimer_mgr *mgr, IUINT32 interval) 281 | { 282 | mgr->current = 0; 283 | mgr->interval = (interval < 1)? 1 : interval; 284 | mgr->jiffies = 0; 285 | mgr->millisec = 0; 286 | mgr->initialized = 0; 287 | itimer_core_init(&mgr->core, mgr->jiffies); 288 | } 289 | 290 | // destroy timer manager 291 | void itimer_mgr_destroy(itimer_mgr *mgr) 292 | { 293 | itimer_core_destroy(&mgr->core); 294 | } 295 | 296 | #ifndef ITIMER_MGR_LIMIT 297 | #define ITIMER_MGR_LIMIT 60000 // 60 seconds 298 | #endif 299 | 300 | // run timer events 301 | void itimer_mgr_run(itimer_mgr *mgr, IUINT32 millisec) 302 | { 303 | IUINT32 interval = mgr->interval; 304 | IINT32 limit = ITIMER_MGR_LIMIT + (IINT32)interval * 64; 305 | // first time to be called 306 | if (mgr->initialized == 0) { 307 | mgr->millisec = millisec; 308 | mgr->initialized = 1; 309 | } 310 | else { 311 | IINT32 diff = (IINT32)(millisec - mgr->millisec); 312 | // recover from long-time sleep 313 | if (diff > limit || diff < -limit) { 314 | mgr->millisec = millisec; 315 | } 316 | } 317 | // update core timer 318 | while ((IINT32)(millisec - mgr->millisec) >= 0) { 319 | itimer_core_run(&mgr->core, mgr->jiffies); 320 | mgr->jiffies++; 321 | mgr->current += mgr->interval; 322 | mgr->millisec += mgr->interval; 323 | } 324 | } 325 | 326 | // callback 327 | static void itimer_evt_cb(void *p) 328 | { 329 | itimer_evt *evt = (itimer_evt*)p; 330 | itimer_mgr *mgr = evt->mgr; 331 | IUINT32 current = mgr->current; 332 | int fire = 0; 333 | int stop = 0; 334 | 335 | // time compensation, comparision takes care of uint32 overflow 336 | while (((IINT32)(current - evt->slap)) >= 0) { 337 | evt->slap += evt->period; 338 | fire = 1; 339 | } 340 | 341 | // need invoke callback ? 342 | if (fire) { 343 | if (evt->repeat == 0) { 344 | fire = 0; 345 | stop = 1; 346 | } 347 | else if (evt->repeat > 0) { 348 | evt->repeat--; 349 | if (evt->repeat == 0) { 350 | stop = 1; 351 | } 352 | } 353 | } 354 | 355 | // reschedule or stop ? 356 | if (stop == 0) { 357 | IUINT32 interval = mgr->interval; 358 | IUINT32 expires = (evt->slap - current + interval - 1) / interval; 359 | if (expires >= 0x70000000) expires = 0x70000000; 360 | itimer_node_add(&mgr->core, &evt->node, mgr->jiffies + expires); 361 | } else { 362 | itimer_evt_stop(mgr, evt); 363 | } 364 | 365 | // need invoke callback ? 366 | if (fire) { 367 | if (evt->callback) { 368 | evt->callback(evt->data, evt->user); 369 | } 370 | } 371 | } 372 | 373 | // initialize timer event 374 | void itimer_evt_init(itimer_evt *evt, void (*fn)(void *data, void *user), 375 | void *data, void *user) 376 | { 377 | itimer_node_init(&evt->node, itimer_evt_cb, evt); 378 | evt->callback = fn; 379 | evt->data = data; 380 | evt->user = user; 381 | evt->mgr = NULL; 382 | evt->period = 0; 383 | evt->slap = 0; 384 | evt->repeat = 0; 385 | evt->running = 0; 386 | } 387 | 388 | // destroy timer event 389 | void itimer_evt_destroy(itimer_evt *evt) 390 | { 391 | itimer_node_destroy(&evt->node); 392 | evt->callback = NULL; 393 | evt->data = NULL; 394 | evt->user = NULL; 395 | evt->mgr = NULL; 396 | evt->period = 0; 397 | evt->slap = 0; 398 | evt->repeat = 0; 399 | evt->running = 0; 400 | } 401 | 402 | // start timer: repeat <= 0 (infinite repeat) 403 | void itimer_evt_start(itimer_mgr *mgr, itimer_evt *evt, 404 | IUINT32 period, int repeat) 405 | { 406 | IUINT32 interval = mgr->interval; 407 | IUINT32 expires; 408 | if (evt->mgr) { 409 | itimer_evt_stop(evt->mgr, evt); 410 | } 411 | evt->period = (period < 1)? 1 : period; 412 | evt->repeat = (repeat <= 0)? -1 : repeat; 413 | evt->slap = mgr->current + period; 414 | evt->mgr = mgr; 415 | expires = (evt->slap - mgr->current + interval - 1) / interval; 416 | if (expires >= 0x70000000) expires = 0x70000000; 417 | itimer_node_add(&mgr->core, &evt->node, mgr->jiffies + expires); 418 | evt->running = 0; 419 | } 420 | 421 | // stop timer 422 | void itimer_evt_stop(itimer_mgr *mgr, itimer_evt *evt) 423 | { 424 | if (evt->mgr) { 425 | itimer_node_del(&evt->mgr->core, &evt->node); 426 | evt->mgr = NULL; 427 | } 428 | evt->running = 0; 429 | } 430 | 431 | // returns 0 for stopped and 1 for running 432 | int itimer_evt_status(const itimer_evt *evt) 433 | { 434 | return (evt->mgr == NULL)? 0 : 1; 435 | } 436 | 437 | 438 | 439 | -------------------------------------------------------------------------------- /system/itimer.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // itimer.h - Application Level Implementation of Linux Kernel Timer 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #ifndef __ITIMER_H__ 10 | #define __ITIMER_H__ 11 | 12 | #include 13 | 14 | 15 | //===================================================================== 16 | // 32BIT INTEGER DEFINITION 17 | //===================================================================== 18 | #ifndef __INTEGER_32_BITS__ 19 | #define __INTEGER_32_BITS__ 20 | #if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) 21 | typedef __UINT32_TYPE__ ISTDUINT32; 22 | typedef __INT32_TYPE__ ISTDINT32; 23 | #elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) 24 | typedef __UINT_FAST32_TYPE__ ISTDUINT32; 25 | typedef __INT_FAST32_TYPE__ ISTDINT32; 26 | #elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 27 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 28 | defined(_M_AMD64) 29 | typedef unsigned int ISTDUINT32; 30 | typedef int ISTDINT32; 31 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 32 | defined(__i386) || defined(_M_X86) 33 | typedef unsigned long ISTDUINT32; 34 | typedef long ISTDINT32; 35 | #elif defined(__MACOS__) 36 | typedef UInt32 ISTDUINT32; 37 | typedef SInt32 ISTDINT32; 38 | #elif defined(__APPLE__) && defined(__MACH__) 39 | #include 40 | typedef u_int32_t ISTDUINT32; 41 | typedef int32_t ISTDINT32; 42 | #elif defined(__BEOS__) 43 | #include 44 | typedef u_int32_t ISTDUINT32; 45 | typedef int32_t ISTDINT32; 46 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 47 | typedef unsigned __int32 ISTDUINT32; 48 | typedef __int32 ISTDINT32; 49 | #elif defined(__GNUC__) && (__GNUC__ > 3) 50 | #include 51 | typedef uint32_t ISTDUINT32; 52 | typedef int32_t ISTDINT32; 53 | #else 54 | typedef unsigned long ISTDUINT32; 55 | typedef long ISTDINT32; 56 | #endif 57 | #endif 58 | 59 | 60 | //===================================================================== 61 | // Integer Definition 62 | //===================================================================== 63 | #ifndef __IINT8_DEFINED 64 | #define __IINT8_DEFINED 65 | typedef char IINT8; 66 | #endif 67 | 68 | #ifndef __IUINT8_DEFINED 69 | #define __IUINT8_DEFINED 70 | typedef unsigned char IUINT8; 71 | #endif 72 | 73 | #ifndef __IUINT16_DEFINED 74 | #define __IUINT16_DEFINED 75 | typedef unsigned short IUINT16; 76 | #endif 77 | 78 | #ifndef __IINT16_DEFINED 79 | #define __IINT16_DEFINED 80 | typedef short IINT16; 81 | #endif 82 | 83 | #ifndef __IINT32_DEFINED 84 | #define __IINT32_DEFINED 85 | typedef ISTDINT32 IINT32; 86 | #endif 87 | 88 | #ifndef __IUINT32_DEFINED 89 | #define __IUINT32_DEFINED 90 | typedef ISTDUINT32 IUINT32; 91 | #endif 92 | 93 | 94 | /*====================================================================*/ 95 | /* LIST DEFINITION */ 96 | /*====================================================================*/ 97 | #ifndef __ILIST_DEF__ 98 | #define __ILIST_DEF__ 99 | 100 | struct ILISTHEAD { 101 | struct ILISTHEAD *next, *prev; 102 | }; 103 | 104 | typedef struct ILISTHEAD ilist_head; 105 | 106 | 107 | /*--------------------------------------------------------------------*/ 108 | /* list init */ 109 | /*--------------------------------------------------------------------*/ 110 | #define ILIST_HEAD_INIT(name) { &(name), &(name) } 111 | #define ILIST_HEAD(name) \ 112 | struct ILISTHEAD name = ILIST_HEAD_INIT(name) 113 | 114 | #define ILIST_INIT(ptr) ( \ 115 | (ptr)->next = (ptr), (ptr)->prev = (ptr)) 116 | 117 | #define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 118 | 119 | #define ICONTAINEROF(ptr, type, member) ( \ 120 | (type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) ) 121 | 122 | #define ILIST_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member) 123 | 124 | 125 | /*--------------------------------------------------------------------*/ 126 | /* list operation */ 127 | /*--------------------------------------------------------------------*/ 128 | #define ILIST_ADD(node, head) ( \ 129 | (node)->prev = (head), (node)->next = (head)->next, \ 130 | (head)->next->prev = (node), (head)->next = (node)) 131 | 132 | #define ILIST_ADD_TAIL(node, head) ( \ 133 | (node)->prev = (head)->prev, (node)->next = (head), \ 134 | (head)->prev->next = (node), (head)->prev = (node)) 135 | 136 | #define ILIST_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n)) 137 | 138 | #define ILIST_DEL(entry) (\ 139 | (entry)->next->prev = (entry)->prev, \ 140 | (entry)->prev->next = (entry)->next, \ 141 | (entry)->next = 0, (entry)->prev = 0) 142 | 143 | #define ILIST_DEL_INIT(entry) do { \ 144 | ILIST_DEL(entry); ILIST_INIT(entry); } while (0) 145 | 146 | #define ILIST_IS_EMPTY(entry) ((entry) == (entry)->next) 147 | 148 | #define ilist_init ILIST_INIT 149 | #define ilist_entry ILIST_ENTRY 150 | #define ilist_add ILIST_ADD 151 | #define ilist_add_tail ILIST_ADD_TAIL 152 | #define ilist_del ILIST_DEL 153 | #define ilist_del_init ILIST_DEL_INIT 154 | #define ilist_is_empty ILIST_IS_EMPTY 155 | 156 | #define ILIST_FOREACH(iterator, head, TYPE, MEMBER) \ 157 | for ((iterator) = ilist_entry((head)->next, TYPE, MEMBER); \ 158 | &((iterator)->MEMBER) != (head); \ 159 | (iterator) = ilist_entry((iterator)->MEMBER.next, TYPE, MEMBER)) 160 | 161 | #define ilist_foreach(iterator, head, TYPE, MEMBER) \ 162 | ILIST_FOREACH(iterator, head, TYPE, MEMBER) 163 | 164 | #define ilist_foreach_entry(pos, head) \ 165 | for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next ) 166 | 167 | 168 | #define __ilist_splice(list, head) do { \ 169 | ilist_head *first = (list)->next, *last = (list)->prev; \ 170 | ilist_head *at = (head)->next; \ 171 | (first)->prev = (head), (head)->next = (first); \ 172 | (last)->next = (at), (at)->prev = (last); } while (0) 173 | 174 | #define ilist_splice(list, head) do { \ 175 | if (!ilist_is_empty(list)) __ilist_splice(list, head); } while (0) 176 | 177 | #define ilist_splice_init(list, head) do { \ 178 | ilist_splice(list, head); ilist_init(list); } while (0) 179 | 180 | 181 | #ifdef _MSC_VER 182 | #pragma warning(disable:4311) 183 | #pragma warning(disable:4312) 184 | #pragma warning(disable:4996) 185 | #endif 186 | 187 | #endif 188 | 189 | 190 | //===================================================================== 191 | // Timer Vector 192 | //===================================================================== 193 | #define ITVN_BITS 6 194 | #define ITVR_BITS 8 195 | #define ITVN_SIZE (1 << ITVN_BITS) 196 | #define ITVR_SIZE (1 << ITVR_BITS) 197 | #define ITVN_MASK (ITVN_SIZE - 1) 198 | #define ITVR_MASK (ITVR_SIZE - 1) 199 | 200 | struct itimer_vec { 201 | ilist_head vec[ITVN_SIZE]; 202 | }; 203 | 204 | struct itimer_vec_root { 205 | ilist_head vec[ITVR_SIZE]; 206 | }; 207 | 208 | struct itimer_core { 209 | IUINT32 timer_jiffies; 210 | struct itimer_vec *tvecs[6]; 211 | struct itimer_vec_root tv1; 212 | struct itimer_vec tv2; 213 | struct itimer_vec tv3; 214 | struct itimer_vec tv4; 215 | struct itimer_vec tv5; 216 | }; 217 | 218 | struct itimer_node { 219 | ilist_head head; 220 | IUINT32 expires; 221 | IUINT32 state; 222 | void *data; 223 | void (*callback)(void *data); 224 | struct itimer_core *core; 225 | }; 226 | 227 | 228 | //===================================================================== 229 | // global definition 230 | //===================================================================== 231 | typedef struct itimer_core itimer_core; 232 | typedef struct itimer_node itimer_node; 233 | 234 | #define itimer_core_jiffies(core) ((core)->jiffies) 235 | #define itimer_node_pending(node) (!iqueue_is_empty(&(node)->head)) 236 | 237 | 238 | #ifdef __cplusplus 239 | extern "C" { 240 | #endif 241 | 242 | //===================================================================== 243 | // Core Timer 244 | //===================================================================== 245 | 246 | // initialize timer core 247 | void itimer_core_init(itimer_core *core, IUINT32 jiffies); 248 | 249 | // destroy timer core 250 | void itimer_core_destroy(itimer_core *core); 251 | 252 | // run timer core 253 | void itimer_core_run(itimer_core *core, IUINT32 jiffies); 254 | 255 | 256 | // initialize node 257 | void itimer_node_init(itimer_node *node, void (*fn)(void*), void *data); 258 | 259 | // destroy node 260 | void itimer_node_destroy(itimer_node *node); 261 | 262 | // add node to core 263 | void itimer_node_add(itimer_core *core, itimer_node *node, IUINT32 expires); 264 | 265 | // remove node from core 266 | int itimer_node_del(itimer_core *core, itimer_node *node); 267 | 268 | // modify node 269 | int itimer_node_mod(itimer_core *core, itimer_node *node, IUINT32 expires); 270 | 271 | 272 | 273 | //===================================================================== 274 | // Timer Manager 275 | //===================================================================== 276 | struct itimer_mgr 277 | { 278 | IUINT32 interval; 279 | IUINT32 current; 280 | IUINT32 millisec; 281 | IUINT32 jiffies; 282 | int initialized; 283 | itimer_core core; 284 | }; 285 | 286 | struct itimer_evt 287 | { 288 | IUINT32 period; 289 | IUINT32 slap; 290 | int repeat; 291 | int running; 292 | void (*callback)(void *data, void *user); 293 | void *data; 294 | void *user; 295 | struct itimer_mgr *mgr; 296 | itimer_node node; 297 | }; 298 | 299 | // type defines 300 | typedef struct itimer_mgr itimer_mgr; 301 | typedef struct itimer_evt itimer_evt; 302 | 303 | // initialize timer manager 304 | // interval - internal working interval 305 | void itimer_mgr_init(itimer_mgr *mgr, IUINT32 interval); 306 | 307 | // destroy timer manager 308 | void itimer_mgr_destroy(itimer_mgr *mgr); 309 | 310 | // run timer events: 311 | // millisec - current time stamp 312 | void itimer_mgr_run(itimer_mgr *mgr, IUINT32 millisec); 313 | 314 | 315 | // initialize timer event 316 | void itimer_evt_init(itimer_evt *evt, void (*fn)(void *data, void *user), 317 | void *data, void *user); 318 | 319 | // destroy timer event 320 | void itimer_evt_destroy(itimer_evt *evt); 321 | 322 | // start timer: repeat <= 0 (infinite repeat) 323 | void itimer_evt_start(itimer_mgr *mgr, itimer_evt *evt, 324 | IUINT32 period, int repeat); 325 | 326 | // stop timer 327 | void itimer_evt_stop(itimer_mgr *mgr, itimer_evt *evt); 328 | 329 | // returns 0 for stopped and 1 for running 330 | int itimer_evt_status(const itimer_evt *evt); 331 | 332 | 333 | #ifdef __cplusplus 334 | } 335 | #endif 336 | 337 | #endif 338 | 339 | 340 | -------------------------------------------------------------------------------- /system/itoolbox.c: -------------------------------------------------------------------------------- 1 | #include "itoolbox.h" 2 | 3 | 4 | 5 | 6 | 7 | //===================================================================== 8 | // Posix IPV4/IPV6 Compatible Socket Address 9 | //===================================================================== 10 | 11 | /* setup address */ 12 | void iposix_addr_init(iPosixAddress *addr, int family) 13 | { 14 | if (family == AF_INET) { 15 | memset(&(addr->sin4), 0, sizeof(struct sockaddr_in)); 16 | addr->sin4.sin_family = family; 17 | } 18 | #ifdef AF_INET6 19 | else if (family == AF_INET6) { 20 | memset(&(addr->sin6), 0, sizeof(struct sockaddr_in6)); 21 | addr->sin6.sin6_family = family; 22 | } 23 | #endif 24 | else { 25 | memset(addr, 0, sizeof(iPosixAddress)); 26 | addr->sin4.sin_family = family; 27 | } 28 | } 29 | 30 | 31 | void iposix_addr_set_ip(iPosixAddress *addr, const void *ip) 32 | { 33 | if (addr->sin4.sin_family == AF_INET) { 34 | memcpy(iposix_addr_v4_u8(addr), ip, 4); 35 | } 36 | #ifdef AF_INET6 37 | else if (addr->sin6.sin6_family == AF_INET6) { 38 | memcpy(iposix_addr_v6_u8(addr), ip, 4); 39 | } 40 | #endif 41 | } 42 | 43 | void iposix_addr_set_port(iPosixAddress *addr, int port) 44 | { 45 | if (addr->sin4.sin_family == AF_INET) { 46 | addr->sin4.sin_port = htons(port); 47 | } 48 | #ifdef AF_INET6 49 | else if (addr->sin6.sin6_family == AF_INET6) { 50 | addr->sin6.sin6_port = htons(port); 51 | } 52 | #endif 53 | } 54 | 55 | int iposix_addr_get_family(const iPosixAddress *addr) 56 | { 57 | return iposix_addr_family(addr); 58 | } 59 | 60 | int iposix_addr_get_ip(const iPosixAddress *addr, void *ip) 61 | { 62 | int size = 4; 63 | if (addr->sin4.sin_family == AF_INET) { 64 | if (ip) { 65 | memcpy(ip, iposix_addr_v4_cu8(addr), 4); 66 | } 67 | } 68 | #ifdef AF_INET6 69 | else if (addr->sin6.sin6_family == AF_INET6) { 70 | size = 16; 71 | if (ip) { 72 | memcpy(ip, iposix_addr_v6_cu8(addr), 16); 73 | } 74 | } 75 | #endif 76 | return size; 77 | } 78 | 79 | int iposix_addr_get_port(const iPosixAddress *addr) 80 | { 81 | int port = 0; 82 | if (addr->sin4.sin_family == AF_INET) { 83 | port = ntohs(addr->sin4.sin_port); 84 | } 85 | #ifdef AF_INET6 86 | else if (addr->sin4.sin_family == AF_INET6) { 87 | port = ntohs(addr->sin6.sin6_port); 88 | } 89 | #endif 90 | return port; 91 | } 92 | 93 | int iposix_addr_get_size(const iPosixAddress *addr) 94 | { 95 | return iposix_addr_size(addr); 96 | } 97 | 98 | int iposix_addr_set_ip_text(iPosixAddress *addr, const char *text) 99 | { 100 | if (addr->sin4.sin_family == AF_INET) { 101 | return isockaddr_set_ip_text(&(addr->sa), text); 102 | } 103 | #ifdef AF_INET6 104 | else if (addr->sin6.sin6_family == AF_INET6) { 105 | int isname = 1, i; 106 | for (i = 0; text[i]; i++) { 107 | if (text[i] == ':') { 108 | isname = 0; 109 | break; 110 | } 111 | } 112 | if (isname == 0) { 113 | return isockaddr_pton(AF_INET6, text, &(addr->sin6.sin6_addr)); 114 | } 115 | else { 116 | iPosixRes *res = iposix_res_get(text, 6); 117 | int hr = 0; 118 | if (res == NULL) return -1; 119 | if (res->size < 1) { 120 | hr = -2; 121 | } else { 122 | memcpy(iposix_addr_v6_u8(addr), res->address[0], 16); 123 | } 124 | iposix_res_free(res); 125 | return hr; 126 | } 127 | } 128 | #endif 129 | return -1; 130 | } 131 | 132 | char *iposix_addr_get_ip_text(const iPosixAddress *addr, char *text) 133 | { 134 | if (addr->sin4.sin_family == AF_INET) { 135 | isockaddr_ntop(AF_INET, &(addr->sin4.sin_addr), text, 32); 136 | } 137 | #ifdef AF_INET6 138 | else if (addr->sin6.sin6_family == AF_INET6) { 139 | isockaddr_ntop(AF_INET6, &(addr->sin6.sin6_addr), text, 256); 140 | } 141 | #endif 142 | return text; 143 | } 144 | 145 | 146 | int iposix_addr_make(iPosixAddress *addr, int family, const char *t, int p) 147 | { 148 | int af_inet6 = -2; 149 | #ifdef AF_INET6 150 | af_inet6 = (int)AF_INET6; 151 | #endif 152 | if (family < 0 || (family != AF_INET && family != af_inet6)) { 153 | int ipv6 = 0, i; 154 | for (i = 0; t[i]; i++) { 155 | if (t[i] == ':') ipv6 = 1; 156 | } 157 | family = AF_INET; 158 | if (ipv6) { 159 | #ifdef AF_INET6 160 | family = AF_INET6; 161 | #else 162 | return -1; 163 | #endif 164 | } 165 | } 166 | #ifndef AF_INET6 167 | if (family != AF_INET) { 168 | if (family != PF_INET) { 169 | return -1; 170 | } 171 | } 172 | #endif 173 | iposix_addr_init(addr, family); 174 | iposix_addr_set_ip_text(addr, t); 175 | iposix_addr_set_port(addr, p); 176 | return 0; 177 | } 178 | 179 | char *iposix_addr_str(const iPosixAddress *addr, char *text) 180 | { 181 | static char buffer[256 + 10]; 182 | int family = iposix_addr_get_family(addr); 183 | if (text == NULL) text = buffer; 184 | if (family == AF_INET) { 185 | return isockaddr_str(&addr->sa, text); 186 | } 187 | #ifdef AF_INET6 188 | else if (family == AF_INET6) { 189 | char *ptr = text; 190 | int port; 191 | *ptr++ = '['; 192 | iposix_addr_get_ip_text(addr, ptr); 193 | ptr += (int)strlen(ptr); 194 | *ptr++ = ']'; 195 | *ptr++ = ':'; 196 | port = iposix_addr_get_port(addr); 197 | sprintf(ptr, "%d", port); 198 | return text; 199 | } 200 | #endif 201 | return NULL; 202 | } 203 | 204 | 205 | int iposix_addr_compare(const iPosixAddress *a1, const iPosixAddress *a2) 206 | { 207 | int f1 = iposix_addr_family(a1); 208 | int f2 = iposix_addr_family(a2); 209 | if (f1 < f2) return -3; 210 | else if (f1 > f2) return 3; 211 | if (f1 == AF_INET) { 212 | int hr = memcmp(&(a1->sin4.sin_addr), &(a2->sin4.sin_addr), 213 | sizeof(a1->sin4.sin_addr)); 214 | if (hr < 0) return -2; 215 | if (hr > 0) return 2; 216 | } 217 | #ifdef AF_INET6 218 | else if (f1 == AF_INET6) { 219 | int hr = memcmp(&(a1->sin6.sin6_addr), &(a2->sin6.sin6_addr), 220 | sizeof(a1->sin6.sin6_addr)); 221 | if (hr < 0) return -2; 222 | if (hr > 0) return 2; 223 | } 224 | #endif 225 | int p1 = iposix_addr_get_port(a1); 226 | int p2 = iposix_addr_get_port(a2); 227 | if (p1 < p2) return -1; 228 | if (p1 > p2) return 1; 229 | return 0; 230 | } 231 | 232 | 233 | //===================================================================== 234 | // DNS Resolve 235 | //===================================================================== 236 | 237 | // create new iPosixRes 238 | iPosixRes *iposix_res_new(int size) 239 | { 240 | iPosixRes *res = NULL; 241 | int required = (16 + sizeof(void*) + sizeof(int)) * size; 242 | char *ptr; 243 | int i; 244 | ptr = (char*)malloc(sizeof(iPosixRes) + required + 16); 245 | res = (iPosixRes*)ptr; 246 | if (res == NULL) { 247 | return NULL; 248 | } 249 | ptr += sizeof(iPosixRes); 250 | res->address = (unsigned char**)ptr; 251 | ptr += sizeof(void*) * size; 252 | res->family = (int*)ptr; 253 | ptr += sizeof(int) * size; 254 | res->size = size; 255 | ptr = (char*)((((size_t)ptr) + 15) & (~((size_t)15))); 256 | for (i = 0; i < size; i++) { 257 | res->address[i] = (unsigned char*)ptr; 258 | ptr += 16; 259 | } 260 | return res; 261 | } 262 | 263 | 264 | // delete res 265 | void iposix_res_free(iPosixRes *res) 266 | { 267 | assert(res); 268 | res->size = 0; 269 | res->family = NULL; 270 | res->address = NULL; 271 | free(res); 272 | } 273 | 274 | // omit duplications 275 | void iposix_res_unique(iPosixRes *res) 276 | { 277 | int avail = 0, i; 278 | for (i = 0; i < res->size; i++) { 279 | IUINT32 *pi = (IUINT32*)res->address[i]; 280 | int dup = 0, j; 281 | if (res->family[i] != AF_INET) { 282 | #ifdef AF_INET6 283 | if (res->family[i] != AF_INET6) 284 | #endif 285 | dup++; 286 | } 287 | for (j = 0; j < avail && dup == 0; j++) { 288 | IUINT32 *pj = (IUINT32*)res->address[j]; 289 | if (res->family[j] == res->family[i]) { 290 | if (res->family[j] == AF_INET) { 291 | if (pi[0] == pj[0]) { 292 | dup++; 293 | } 294 | } 295 | #ifdef AF_INET6 296 | if (res->family[j] == AF_INET6) { 297 | if (pi[0] == pj[0] && pi[1] == pj[1] && 298 | pi[2] == pj[2] && pi[3] == pj[3]) { 299 | dup++; 300 | } 301 | } 302 | #endif 303 | } 304 | } 305 | if (dup == 0) { 306 | if (avail != i) { 307 | res->family[avail] = res->family[i]; 308 | memcpy(res->address[avail], res->address[i], 16); 309 | } 310 | avail++; 311 | } 312 | } 313 | res->size = avail; 314 | } 315 | 316 | 317 | // ipv = 0/any, 4/ipv4, 6/ipv6 318 | iPosixRes *iposix_res_get(const char *hostname, int ipv) 319 | { 320 | iPosixRes *res = NULL; 321 | struct addrinfo hints, *r, *p; 322 | int status, count; 323 | memset(&hints, 0, sizeof(hints)); 324 | if (ipv == 4) { 325 | hints.ai_family = AF_INET; 326 | } 327 | else if (ipv == 6) { 328 | #ifdef AF_INET6 329 | hints.ai_family = AF_INET6; 330 | #else 331 | return NULL; 332 | #endif 333 | } 334 | else if (ipv != 4 && ipv != 6) { 335 | #ifdef AF_UNSPEC 336 | hints.ai_family = AF_UNSPEC; 337 | #else 338 | return NULL; 339 | #endif 340 | } 341 | hints.ai_socktype = SOCK_STREAM; 342 | status = getaddrinfo(hostname, NULL, &hints, &r); 343 | if (status != 0) return NULL; 344 | for (p = r, count = 0; p != NULL; p = p->ai_next) { 345 | if (ipv == 4) { 346 | if (p->ai_family == AF_INET) count++; 347 | } 348 | else if (ipv == 6) { 349 | #ifdef AF_INET6 350 | if (p->ai_family == AF_INET6) count++; 351 | #endif 352 | } 353 | else { 354 | if (p->ai_family == AF_INET) count++; 355 | #ifdef AF_INET6 356 | else if (p->ai_family == AF_INET6) count++; 357 | #endif 358 | } 359 | } 360 | res = iposix_res_new(count); 361 | if (res == NULL) { 362 | freeaddrinfo(r); 363 | return NULL; 364 | } 365 | for (p = r, count = 0; p != NULL; p = p->ai_next) { 366 | int skip = 1; 367 | if (ipv == 4) { 368 | if (p->ai_family == AF_INET) skip = 0; 369 | } 370 | else if (ipv == 6) { 371 | #ifdef AF_INET6 372 | if (p->ai_family == AF_INET6) skip = 0; 373 | #endif 374 | } 375 | else { 376 | if (p->ai_family == AF_INET) skip = 0; 377 | #ifdef AF_INET6 378 | else if (p->ai_family == AF_INET6) skip = 0; 379 | #endif 380 | } 381 | if (skip) { 382 | continue; 383 | } 384 | res->family[count] = p->ai_family; 385 | if (p->ai_family == AF_INET) { 386 | struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; 387 | memcpy(res->address[count], &(ipv4->sin_addr), 4); 388 | } 389 | else { 390 | #ifdef AF_INET6 391 | struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; 392 | memcpy(res->address[count], &(ipv6->sin6_addr), 16); 393 | #else 394 | memset(res->address[count], 0, 16); 395 | #endif 396 | } 397 | count++; 398 | } 399 | freeaddrinfo(r); 400 | return res; 401 | } 402 | 403 | 404 | int iposix_addr_version(const char *text) 405 | { 406 | int i; 407 | for (i = 0; text[i]; i++) { 408 | if (text[i] == ':') return 6; 409 | } 410 | return 4; 411 | } 412 | 413 | 414 | //===================================================================== 415 | // Protocol Reader 416 | //===================================================================== 417 | struct CAsyncReader 418 | { 419 | int mode; 420 | int complete; 421 | ilong need; 422 | unsigned char spliter; 423 | struct IMSTREAM cache; 424 | struct IMSTREAM input; 425 | }; 426 | 427 | 428 | CAsyncReader *async_reader_new(ib_memnode *fnode) 429 | { 430 | CAsyncReader *reader; 431 | reader = (CAsyncReader*)ikmem_malloc(sizeof(CAsyncReader)); 432 | if (reader == NULL) return NULL; 433 | ims_init(&reader->input, fnode, 0, 0); 434 | ims_init(&reader->cache, fnode, 0, 0); 435 | reader->spliter = (unsigned char)'\n'; 436 | reader->mode = ISTREAM_READ_BYTE; 437 | reader->need = 0; 438 | reader->complete = 0; 439 | return reader; 440 | } 441 | 442 | void async_reader_delete(CAsyncReader *reader) 443 | { 444 | if (reader != NULL) { 445 | ims_destroy(&reader->input); 446 | ims_destroy(&reader->cache); 447 | memset(reader, 0, sizeof(CAsyncReader)); 448 | ikmem_free(reader); 449 | } 450 | } 451 | 452 | static void async_reader_redirect(struct IMSTREAM *dst, struct IMSTREAM *src) 453 | { 454 | while (ims_dsize(src) > 0) { 455 | ilong size; 456 | void *ptr; 457 | size = ims_flat(src, &ptr); 458 | if (size > 0) { 459 | ims_write(dst, ptr, size); 460 | ims_drop(src, size); 461 | } 462 | } 463 | } 464 | 465 | static void async_reader_reset(CAsyncReader *reader) 466 | { 467 | if (ims_dsize(&reader->cache) > 0) { 468 | struct IMSTREAM tmp; 469 | ims_init(&tmp, reader->cache.fixed_pages, 0, 0); 470 | async_reader_redirect(&tmp, &reader->input); 471 | async_reader_redirect(&reader->input, &reader->cache); 472 | async_reader_redirect(&reader->input, &tmp); 473 | ims_destroy(&tmp); 474 | reader->complete = 0; 475 | assert(ims_dsize(&reader->cache) == 0); 476 | } 477 | } 478 | 479 | void async_reader_mode(CAsyncReader *reader, int mode, ilong what) 480 | { 481 | if (mode == ISTREAM_READ_LINE) { 482 | if (reader->mode == mode && 483 | reader->spliter == (unsigned char)what) 484 | return; 485 | reader->spliter = (unsigned char)what; 486 | } 487 | else if (mode == ISTREAM_READ_BLOCK) { 488 | reader->need = what; 489 | if (reader->mode == mode) return; 490 | } 491 | else { 492 | assert(mode == ISTREAM_READ_BYTE); 493 | if (reader->mode == mode) return; 494 | } 495 | reader->mode = mode; 496 | async_reader_reset(reader); 497 | } 498 | 499 | long async_reader_read(CAsyncReader *reader, void *data, long maxsize) 500 | { 501 | unsigned char *out = (unsigned char*)data; 502 | ilong size = 0; 503 | ilong remain = 0; 504 | if (reader->mode == ISTREAM_READ_BYTE) { 505 | void *pointer; 506 | remain = ims_flat(&reader->input, &pointer); 507 | if (remain == 0) return -1; 508 | if (data == NULL) return 1; 509 | if (maxsize < 1) return -2; 510 | out[0] = *((unsigned char*)pointer); 511 | ims_drop(&reader->input, 1); 512 | return 1; 513 | } 514 | else if (reader->mode == ISTREAM_READ_LINE) { 515 | if (reader->complete) { 516 | remain = ims_dsize(&reader->cache); 517 | if (data == NULL) return (long)remain; 518 | if (maxsize < remain) return -2; 519 | ims_read(&reader->cache, data, remain); 520 | reader->complete = 0; 521 | return (long)remain; 522 | } else { 523 | unsigned char spliter = reader->spliter; 524 | while (1) { 525 | void *pointer; 526 | unsigned char *src; 527 | ilong i; 528 | remain = ims_flat(&reader->input, &pointer); 529 | if (remain == 0) return -1; 530 | src = (unsigned char*)pointer; 531 | for (i = 0; i < remain; i++) { 532 | if (src[i] == spliter) break; 533 | } 534 | if (i >= remain) { 535 | ims_write(&reader->cache, src, remain); 536 | ims_drop(&reader->input, remain); 537 | } else { 538 | ims_write(&reader->cache, src, i + 1); 539 | ims_drop(&reader->input, i + 1); 540 | size = ims_dsize(&reader->cache); 541 | if (data == NULL) { 542 | reader->complete = 1; 543 | return (long)size; 544 | } 545 | if (maxsize < size) { 546 | reader->complete = 1; 547 | return -2; 548 | } 549 | ims_read(&reader->cache, data, size); 550 | reader->complete = 0; 551 | return (long)size; 552 | } 553 | } 554 | } 555 | } 556 | else if (reader->mode == ISTREAM_READ_BLOCK) { 557 | remain = ims_dsize(&reader->input); 558 | size = reader->need; 559 | if (remain < size) return -1; 560 | if (data == NULL) return (long)size; 561 | if (maxsize < size) return -2; 562 | ims_read(&reader->input, data, size); 563 | return (long)size; 564 | } 565 | return -1; 566 | } 567 | 568 | void async_reader_feed(CAsyncReader *reader, const void *data, long len) 569 | { 570 | if (len > 0 && data != NULL) { 571 | ims_write(&reader->input, data, len); 572 | } 573 | } 574 | 575 | 576 | void async_reader_clear(CAsyncReader *reader) 577 | { 578 | reader->mode = ISTREAM_READ_BYTE; 579 | reader->need = 0; 580 | reader->complete = 0; 581 | reader->spliter = (unsigned char)'\n'; 582 | ims_clear(&reader->input); 583 | ims_clear(&reader->cache); 584 | } 585 | 586 | 587 | //===================================================================== 588 | // utils 589 | //===================================================================== 590 | 591 | int isocket_pair_ex(int *pair) 592 | { 593 | int fds[2] = { -1, -1 }; 594 | int hr = 0; 595 | #ifdef __unix 596 | #ifndef __AVM2__ 597 | if (pipe(fds) == 0) hr = 0; 598 | else hr = errno; 599 | #endif 600 | #else 601 | if (isocket_pair(fds, 1) != 0) { 602 | int ok = 0, i; 603 | for (i = 0; i < 15; i++) { 604 | isleep(10); 605 | if (isocket_pair(fds, 1) == 0) { 606 | ok = 1; 607 | break; 608 | } 609 | } 610 | hr = ok? 0 : -1; 611 | if (ok) { 612 | ikeepalive(fds[0], 50, 300, 10); 613 | ikeepalive(fds[1], 50, 300, 10); 614 | } 615 | } 616 | #endif 617 | if (hr != 0) { 618 | if (pair) { 619 | pair[0] = -1; 620 | pair[1] = -1; 621 | } 622 | return hr; 623 | } 624 | if (pair) { 625 | pair[0] = fds[0]; 626 | pair[1] = fds[1]; 627 | } 628 | return 0; 629 | } 630 | 631 | 632 | //===================================================================== 633 | // can be used to wakeup select 634 | //===================================================================== 635 | struct CSelectNotify 636 | { 637 | int fds[2]; 638 | int event; 639 | IMUTEX_TYPE lock_pipe; 640 | IMUTEX_TYPE lock_select; 641 | char *buffer; 642 | int capacity; 643 | }; 644 | 645 | 646 | CSelectNotify* select_notify_new(void) 647 | { 648 | CSelectNotify *sn = (CSelectNotify*)ikmem_malloc(sizeof(CSelectNotify)); 649 | if (!sn) { 650 | return NULL; 651 | } 652 | if (isocket_pair_ex(sn->fds) != 0) { 653 | ikmem_free(sn); 654 | return NULL; 655 | } 656 | sn->event = 0; 657 | sn->buffer = NULL; 658 | sn->capacity = 0; 659 | IMUTEX_INIT(&sn->lock_pipe); 660 | IMUTEX_INIT(&sn->lock_select); 661 | return sn; 662 | } 663 | 664 | void select_notify_delete(CSelectNotify *sn) 665 | { 666 | if (sn) { 667 | IMUTEX_LOCK(&sn->lock_pipe); 668 | IMUTEX_LOCK(&sn->lock_select); 669 | if (sn->fds[0]) iclose(sn->fds[0]); 670 | if (sn->fds[1]) iclose(sn->fds[1]); 671 | sn->fds[0] = -1; 672 | sn->fds[1] = -1; 673 | if (sn->buffer) ikmem_free(sn->buffer); 674 | sn->buffer = NULL; 675 | sn->capacity = 0; 676 | IMUTEX_UNLOCK(&sn->lock_select); 677 | IMUTEX_UNLOCK(&sn->lock_pipe); 678 | IMUTEX_DESTROY(&sn->lock_pipe); 679 | IMUTEX_DESTROY(&sn->lock_select); 680 | ikmem_free(sn); 681 | } 682 | } 683 | 684 | int select_notify_wait(CSelectNotify *sn, const int *fds, 685 | const int *event, int *revent, int count, long millisec) 686 | { 687 | int hr = 0, n = 0, i; 688 | int need, unit, require; 689 | int *new_fds; 690 | int *new_event; 691 | int *new_revent; 692 | char *ptr; 693 | IMUTEX_LOCK(&sn->lock_select); 694 | n = (count + 1 + 31) & (~31); 695 | need = iselect(NULL, NULL, NULL, n, 0, NULL); 696 | unit = (sizeof(int) * n + 31) & (~31); 697 | require = need + unit * 3; 698 | if (require > sn->capacity) { 699 | if (sn->buffer) ikmem_free(sn->buffer); 700 | sn->buffer = (char*)ikmem_malloc(require); 701 | if (sn->buffer == NULL) { 702 | sn->capacity = 0; 703 | IMUTEX_UNLOCK(&sn->lock_select); 704 | return -1000; 705 | } 706 | sn->capacity = require; 707 | } 708 | ptr = sn->buffer; 709 | new_fds = (int*)ptr; 710 | ptr += unit; 711 | new_event = (int*)ptr; 712 | ptr += unit; 713 | new_revent = (int*)ptr; 714 | ptr += unit; 715 | for (i = 0; i < count; i++) { 716 | new_fds[i] = fds[i]; 717 | new_event[i] = event[i]; 718 | } 719 | new_fds[count] = sn->fds[0]; 720 | new_event[count] = IPOLL_IN; 721 | hr = iselect(new_fds, new_event, new_revent, count + 1, millisec, ptr); 722 | if (revent) { 723 | for (i = 0; i < count; i++) { 724 | revent[i] = new_revent[i]; 725 | } 726 | } 727 | IMUTEX_LOCK(&sn->lock_pipe); 728 | if (sn->event) { 729 | char dummy[10]; 730 | int fd = sn->fds[0]; 731 | #ifdef __unix 732 | read(fd, dummy, 8); 733 | #else 734 | irecv(fd, dummy, 8, 0); 735 | #endif 736 | sn->event = 0; 737 | } 738 | IMUTEX_UNLOCK(&sn->lock_pipe); 739 | IMUTEX_UNLOCK(&sn->lock_select); 740 | return hr; 741 | } 742 | 743 | 744 | int select_notify_wake(CSelectNotify *sn) 745 | { 746 | int fd = sn->fds[1]; 747 | int hr = 0; 748 | IMUTEX_LOCK(&sn->lock_pipe); 749 | if (sn->event == 0) { 750 | char dummy = 1; 751 | #ifdef __unix 752 | #ifndef __AVM2__ 753 | hr = write(fd, &dummy, 1); 754 | #endif 755 | #else 756 | hr = send(fd, &dummy, 1, 0); 757 | #endif 758 | if (hr == 1) { 759 | sn->event = 1; 760 | hr = 0; 761 | } 762 | } 763 | IMUTEX_UNLOCK(&sn->lock_pipe); 764 | return hr; 765 | } 766 | 767 | 768 | //===================================================================== 769 | // Terminal Colors 770 | //===================================================================== 771 | 772 | // 设置颜色:低4位是文字颜色,高4位是背景颜色 773 | // 具体编码可以搜索 ansi color或者 774 | // http://en.wikipedia.org/wiki/ANSI_escape_code 775 | void console_set_color(int color) 776 | { 777 | #ifdef _WIN32 778 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 779 | WORD result = 0; 780 | if (color & 1) result |= FOREGROUND_RED; 781 | if (color & 2) result |= FOREGROUND_GREEN; 782 | if (color & 4) result |= FOREGROUND_BLUE; 783 | if (color & 8) result |= FOREGROUND_INTENSITY; 784 | if (color & 16) result |= BACKGROUND_RED; 785 | if (color & 32) result |= BACKGROUND_GREEN; 786 | if (color & 64) result |= BACKGROUND_BLUE; 787 | if (color & 128) result |= BACKGROUND_INTENSITY; 788 | SetConsoleTextAttribute(hConsole, (WORD)result); 789 | #else 790 | int foreground = color & 7; 791 | int background = (color >> 4) & 7; 792 | int bold = color & 8; 793 | printf("\033[%s3%d;4%dm", bold? "01;" : "", foreground, background); 794 | #endif 795 | } 796 | 797 | // 设置光标位置左上角是,行与列都是从1开始计数的 798 | void console_cursor(int row, int col) 799 | { 800 | #ifdef _WIN32 801 | COORD point; 802 | point.X = col - 1; 803 | point.Y = row - 1; 804 | SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), point); 805 | #else 806 | printf("\033[%d;%dH", row, col); 807 | #endif 808 | } 809 | 810 | // 恢复屏幕颜色 811 | void console_reset(void) 812 | { 813 | #ifdef _WIN32 814 | console_set_color(7); 815 | #else 816 | printf("\033[0m"); 817 | #endif 818 | } 819 | 820 | // 清屏 821 | void console_clear(int color) 822 | { 823 | #ifdef _WIN32 824 | COORD coordScreen = { 0, 0 }; 825 | DWORD cCharsWritten; 826 | CONSOLE_SCREEN_BUFFER_INFO csbi; 827 | DWORD dwConSize; 828 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 829 | GetConsoleScreenBufferInfo(hConsole, &csbi); 830 | dwConSize = csbi.dwSize.X * csbi.dwSize.Y; 831 | FillConsoleOutputCharacter(hConsole, TEXT(' '), 832 | dwConSize, 833 | coordScreen, 834 | &cCharsWritten); 835 | GetConsoleScreenBufferInfo(hConsole, &csbi); 836 | FillConsoleOutputAttribute(hConsole, 837 | csbi.wAttributes, 838 | dwConSize, 839 | coordScreen, 840 | &cCharsWritten); 841 | SetConsoleCursorPosition(hConsole, coordScreen); 842 | #else 843 | printf("\033[2J"); 844 | #endif 845 | } 846 | 847 | 848 | //===================================================================== 849 | // utilities 850 | //===================================================================== 851 | 852 | 853 | char* hash_signature_md5( 854 | char *out, // output string with size above 64 bytes 855 | const void *in, // input data 856 | int in_size, // input size 857 | const char *secret, // secret token 858 | int secret_size, // secret size 859 | IUINT32 timestamp) // time stamp in unix epoch seconds 860 | { 861 | HASH_MD5_CTX md5; 862 | unsigned char buffer[32]; 863 | if (secret_size < 0) { 864 | secret_size = (int)strlen(secret); 865 | } 866 | iencode32u_lsb((char*)buffer, timestamp); 867 | HASH_MD5_Init(&md5, 0); 868 | HASH_MD5_Update(&md5, "SIGNATURE", 9); 869 | HASH_MD5_Update(&md5, in, (unsigned int)in_size); 870 | HASH_MD5_Update(&md5, secret, (unsigned int)secret_size); 871 | HASH_MD5_Update(&md5, buffer, 4); 872 | HASH_MD5_Final(&md5, buffer + 4); 873 | hash_digest_to_string(buffer, 20, out); 874 | return out; 875 | } 876 | 877 | 878 | // extract timestamp from signature 879 | IUINT32 hash_signature_time(const char *signature) 880 | { 881 | unsigned char head[4]; 882 | IUINT32 timestamp; 883 | int i; 884 | for (i = 0; i < 4; i++) { 885 | char ch = signature[i]; 886 | int index = 0; 887 | if (ch >= '0' && ch <= '9') { 888 | index = (int)(ch - '0'); 889 | } 890 | else if (ch >= 'a' && ch <= 'f') { 891 | index = (int)(ch - 'a') + 10; 892 | } 893 | else if (ch >= 'A' && ch <= 'F') { 894 | index = (int)(ch - 'A') + 10; 895 | } 896 | head[i] = (unsigned char)(index & 15); 897 | } 898 | idecode32u_lsb((char*)head, ×tamp); 899 | return (IUINT32)timestamp; 900 | } 901 | 902 | 903 | 904 | -------------------------------------------------------------------------------- /system/itoolbox.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // itoolbox.h - 4 | // 5 | // Created by skywind on 2019/06/12 6 | // Last Modified: 2019/06/12 20:18:52 7 | // 8 | //===================================================================== 9 | #ifndef _ITOOLBOX_H_ 10 | #define _ITOOLBOX_H_ 11 | 12 | #include "imembase.h" 13 | #include "imemdata.h" 14 | #include "inetbase.h" 15 | #include "inetcode.h" 16 | #include "isecure.h" 17 | 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | //===================================================================== 24 | // Posix IPV4/IPV6 Compatible Socket Address 25 | //===================================================================== 26 | typedef union _iPosixAddress { 27 | struct sockaddr sa; 28 | struct sockaddr_in sin4; 29 | #ifdef AF_INET6 30 | struct sockaddr_in6 sin6; 31 | #endif 32 | } iPosixAddress; 33 | 34 | 35 | // get family from generic sockaddr 36 | #define iposix_addr_family(pa) ((pa)->sa.sa_family) 37 | 38 | #define iposix_addr_v4_ptr(pa) (&((pa)->sin4.sin_addr.s_addr)) 39 | #define iposix_addr_v4_vec(type, pa) ((type*)iposix_addr_v4_ptr(pa)) 40 | #define iposix_addr_v4_port(pa) ((pa)->sin4.sin_port) 41 | #define iposix_addr_v4_u8(pa) iposix_addr_v4_vec(unsigned char, pa) 42 | #define iposix_addr_v4_cu8(pa) iposix_addr_v4_vec(const unsigned char, pa) 43 | 44 | #ifdef AF_INET6 45 | #define iposix_addr_v6_ptr(pa) (((pa)->sin6.sin6_addr.s6_addr)) 46 | #define iposix_addr_v6_vec(type, pa) ((type*)iposix_addr_v6_ptr(pa)) 47 | #define iposix_addr_v6_port(pa) ((pa)->sin6.sin6_port) 48 | #define iposix_addr_v6_u8(pa) iposix_addr_v6_vec(unsigned char, pa) 49 | #define iposix_addr_v6_cu8(pa) iposix_addr_v6_vec(const unsigned char, pa) 50 | 51 | #define iposix_addr_size(pa) \ 52 | ((iposix_addr_family(pa) == AF_INET6)? \ 53 | sizeof(struct sockaddr_in6) : sizeof(struct sockaddr)) 54 | #else 55 | #define iposix_addr_size(pa) (sizeof(struct sockaddr)) 56 | #endif 57 | 58 | 59 | void iposix_addr_init(iPosixAddress *addr, int family); 60 | void iposix_addr_set_ip(iPosixAddress *addr, const void *ip); 61 | void iposix_addr_set_port(iPosixAddress *addr, int port); 62 | 63 | int iposix_addr_get_family(const iPosixAddress *addr); 64 | int iposix_addr_get_ip(const iPosixAddress *addr, void *ip); 65 | int iposix_addr_get_port(const iPosixAddress *addr); 66 | int iposix_addr_get_size(const iPosixAddress *addr); 67 | 68 | int iposix_addr_set_ip_text(iPosixAddress *addr, const char *text); 69 | char *iposix_addr_get_ip_text(const iPosixAddress *addr, char *text); 70 | 71 | int iposix_addr_make(iPosixAddress *addr, int family, const char *t, int p); 72 | char *iposix_addr_str(const iPosixAddress *addr, char *text); 73 | 74 | int iposix_addr_compare(const iPosixAddress *a1, const iPosixAddress *a2); 75 | int iposix_addr_version(const char *text); 76 | 77 | 78 | //===================================================================== 79 | // DNS Resolve 80 | //===================================================================== 81 | typedef struct _iPosixRes 82 | { 83 | int size; 84 | int *family; 85 | unsigned char **address; 86 | } iPosixRes; 87 | 88 | // create new iPosixRes 89 | iPosixRes *iposix_res_new(int size); 90 | 91 | // remove res 92 | void iposix_res_free(iPosixRes *res); 93 | 94 | // omit duplications 95 | void iposix_res_unique(iPosixRes *res); 96 | 97 | 98 | // ipv = 0/any, 4/ipv4, 6/ipv6 99 | iPosixRes *iposix_res_get(const char *hostname, int ipv); 100 | 101 | 102 | //===================================================================== 103 | // Protocol Reader 104 | //===================================================================== 105 | struct CAsyncReader; 106 | typedef struct CAsyncReader CAsyncReader; 107 | 108 | CAsyncReader *async_reader_new(ib_memnode *fnode); 109 | 110 | void async_reader_delete(CAsyncReader *reader); 111 | 112 | 113 | #define ISTREAM_READ_BYTE 0 114 | #define ISTREAM_READ_LINE 1 115 | #define ISTREAM_READ_BLOCK 2 116 | 117 | void async_reader_mode(CAsyncReader *reader, int mode, ilong what); 118 | 119 | long async_reader_read(CAsyncReader *reader, void *data, long maxsize); 120 | 121 | void async_reader_feed(CAsyncReader *reader, const void *data, long len); 122 | 123 | void async_reader_clear(CAsyncReader *reader); 124 | 125 | 126 | //===================================================================== 127 | // utils 128 | //===================================================================== 129 | 130 | int isocket_pair_ex(int *pair); 131 | 132 | // can be used to wakeup select 133 | struct CSelectNotify; 134 | typedef struct CSelectNotify CSelectNotify; 135 | 136 | CSelectNotify* select_notify_new(void); 137 | 138 | void select_notify_delete(CSelectNotify *sn); 139 | 140 | int select_notify_wait(CSelectNotify *sn, const int *fds, 141 | const int *event, int *revent, int count, long millisec); 142 | 143 | int select_notify_wake(CSelectNotify *sn); 144 | 145 | 146 | //===================================================================== 147 | // Terminal Control 148 | //===================================================================== 149 | 150 | // colors 151 | #define CTEXT_BLACK 0 152 | #define CTEXT_RED 1 153 | #define CTEXT_GREEN 2 154 | #define CTEXT_YELLOW 3 155 | #define CTEXT_BLUE 4 156 | #define CTEXT_MAGENTA 5 157 | #define CTEXT_CYAN 6 158 | #define CTEXT_WHITE 7 159 | #define CTEXT_BOLD 8 160 | #define CTEXT_BOLD_RED 9 161 | #define CTEXT_BOLD_GREEN 10 162 | #define CTEXT_BOLD_YELLO 11 163 | #define CTEXT_BOLD_BLUE 12 164 | #define CTEXT_BOLD_MAGENTA 13 165 | #define CTEXT_BOLD_CYAN 14 166 | #define CTEXT_BOLD_WHITE 15 167 | 168 | // 背景颜色定义 169 | #define CBG_BLACK 0 170 | #define CBG_RED (1 << 4) 171 | #define CBG_GREEN (2 << 4) 172 | #define CBG_YELLO (3 << 4) 173 | #define CBG_BLUE (4 << 4) 174 | #define CBG_MAGENTA (5 << 4) 175 | #define CBG_CYAN (6 << 4) 176 | #define CBG_WHITE (7 << 4) 177 | 178 | 179 | // 设置颜色:低4位是文字颜色,高4位是背景颜色 180 | // 具体编码可以搜索 ansi color或者 181 | // http://en.wikipedia.org/wiki/ANSI_escape_code 182 | void console_set_color(int color); 183 | 184 | 185 | // 设置光标位置左上角是,行与列都是从1开始计数的 186 | void console_cursor(int row, int col); 187 | 188 | // 恢复屏幕颜色 189 | void console_reset(void); 190 | 191 | // 清屏 192 | void console_clear(int color); 193 | 194 | 195 | //===================================================================== 196 | // utilities 197 | //===================================================================== 198 | 199 | // generate a 40 bytes signature 200 | char* hash_signature_md5( 201 | char *out, // output string with size above 41 bytes 202 | const void *in, // input data 203 | int size, // input size 204 | const char *secret, // secret token 205 | int secret_size, // secret size 206 | IUINT32 timestamp); // time stamp in unix epoch seconds 207 | 208 | // extract timestamp from signature 209 | IUINT32 hash_signature_time(const char *signature); 210 | 211 | 212 | 213 | #ifdef __cplusplus 214 | } 215 | #endif 216 | 217 | #endif 218 | 219 | 220 | --------------------------------------------------------------------------------