#include "stdafx.h" #include "L2Packet_NetLayer.h" #include // network function pointers table #define l2pnet_ft_size 11 void *l2pnet_ft[l2pnet_ft_size] = {0, 0,0,0, 0,0,0, 0,0,0, 0}; CRITICAL_SECTION l2pnet_cs; // winsock2 functions HINSTANCE l2pnet_hws2_32; void *ws2_func[l2pnet_ft_size] = {0, 0,0,0, 0,0,0, 0,0,0, 0}; char l2pnet_static_inet_ntoa_buffer[32]; typedef int (__stdcall *select_func)( int, fd_set *, fd_set *, fd_set *, const struct timeval *); typedef int (__stdcall *WSAGetLastError_func)(void); typedef void (__stdcall *WSASetLastError_func)( int ); typedef int (__stdcall *WSAStartup_func)( WORD, WSADATA * ); typedef int (__stdcall *WSACleanup_func)(void); //typedef void *(__stdcall *gethostbyname_func)( const char * ); typedef int (__stdcall *getaddrinfo_func)( const char *, const char *, void *, void * ); /* Success returns zero. Failure returns error code */ typedef void (__stdcall *freeaddrinfo_func)( void * ); //select_func select_winsock = NULL; /** Initializes L2Packets network layer. ** By default network functions L2PNet_* will be used, ** which use corresponding Winsock2 functions. ** returns 1 on success, 0 on error */ int L2PNet_InitDefault() { // global vars init int i = 0; TCHAR mes[128] = {0}; l2pnet_static_inet_ntoa_buffer[0] = 0; InitializeCriticalSection( &l2pnet_cs ); // for( i=0; i= l2pnet_ft_size) ) return; EnterCriticalSection( &l2pnet_cs ); l2pnet_ft[funcNo] = func_addr; // O_o LeaveCriticalSection( &l2pnet_cs ); } /** Creates TCP socket ** returns 0xFFFFFFFF on error, on success - [1..0xFFFFFFFE] :) */ unsigned int L2PNet_TCPsocket_create( bool bUse_NonBlock_IO_Mode ) { unsigned int sock = 0xFFFFFFFF; if( l2pnet_ft[L2PFUNC_SOCKET] ) { //ret = ( (int (__stdcall*)( unsigned int, void *, int ) )connect_orig)( sock, sockaddr, addrlen ); sock = ( (unsigned int (*)(bool))(l2pnet_ft[L2PFUNC_SOCKET]) )( bUse_NonBlock_IO_Mode ); } else { sock = ( (SOCKET (__stdcall*)(int,int,int))(ws2_func[L2PFUNC_SOCKET]))( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if( (sock != 0xFFFFFFFF) && bUse_NonBlock_IO_Mode ) { void *s_ioctl = (void *)GetProcAddress( l2pnet_hws2_32, "ioctlsocket" ); if( s_ioctl ) { // If iMode = 0, blocking is enabled; // If iMode != 0, non-blocking mode is enabled. unsigned int iMode = 1; int res = ((int (__stdcall*)(SOCKET,int,unsigned int *))(s_ioctl))( sock, FIONBIO, &iMode ); if( res != 0 ) DebugBreak(); } else { MessageBox( NULL, TEXT("L2Packets cannot find ioctlsocket in ws2_32.dll!"), TEXT("L2Packets Error!"), MB_ICONSTOP ); } } } return sock; } /** Waits for socket to be ready for read or write ** returns 1 on success, 0 on timeout, -1 on error */ int L2PNet_select( unsigned int sock, // socket descriptor unsigned int dwSelFlags, // flags what to wait for: L2PNET_SELECT_READ/WRITE long lWaitMilliSecs, // wait timeout in milliseconds int *pbReadyForRead, // will be 1, if ready to read, 0 otherwise (may be NULL) int *pbReadyForWrite ) // will be 1, if ready to write, 0 otherwise (may be NULL) { int ret = -1; if( l2pnet_ft[L2PFUNC_SELECT] ) { ret = ( (int (*)(unsigned int, unsigned int, long, int*, int*))(l2pnet_ft[L2PFUNC_SELECT]) ) ( sock, dwSelFlags, lWaitMilliSecs, pbReadyForRead, pbReadyForWrite ); } else { if( dwSelFlags == 0 ) return -1; if( pbReadyForRead ) (*pbReadyForRead) = 0; if( pbReadyForWrite ) (*pbReadyForWrite) = 0; struct fd_set readFds; struct fd_set writeFds; struct fd_set *prfds = NULL, *pwfds = NULL; FD_ZERO(&readFds); FD_ZERO(&writeFds); if( dwSelFlags & L2PNET_SELECT_READ ) { FD_SET( sock, &readFds ); prfds = &readFds; } if( dwSelFlags & L2PNET_SELECT_WRITE ) { FD_SET( sock, &writeFds ); pwfds = &writeFds; } long microsecs = lWaitMilliSecs * 1000; // 1 millisec = 1 000 microsec long secs = microsecs / 1000000; // 1 000 000 microsecs -= secs * 1000000; struct timeval tv; tv.tv_sec = secs; tv.tv_usec = microsecs; ret = ( (int (__stdcall*)(int, fd_set *, fd_set *, fd_set *, const struct timeval *)) (ws2_func[L2PFUNC_SELECT]))( 0, prfds, pwfds, NULL, &tv ); if( ret == 0 ) return 0; // timeout failed if( ret == -1 ) return -1; // select error if( L2PNet_FD_ISSET( sock, &readFds ) && pbReadyForRead ) (*pbReadyForRead) = 1; // ready to recv if( L2PNet_FD_ISSET( sock, &writeFds ) && pbReadyForWrite ) (*pbReadyForWrite) = 1; // ready to write } return ret; } /** Check state for multiple sockets */ int L2PNet_select_multi( unsigned int *socks_array, // socket descriptors array unsigned int socks_count, // socket descriptors array item count unsigned int dwSelFlags, // flags what to wait for: L2PNET_SELECT_READ/WRITE long lWaitMilliSecs, // wait timeout in milliseconds int *pbReadyForRead, // array! will be 1, if ready to read, 0 otherwise int *pbReadyForWrite ) // array! will be 1, if ready to write, 0 otherwise { if( (!socks_array) || (socks_count==0) || (dwSelFlags == 0) ) return -1; if( pbReadyForRead ) memset( pbReadyForRead, 0, sizeof(int)*socks_count ); if( pbReadyForWrite ) memset( pbReadyForWrite, 0, sizeof(int)*socks_count ); struct fd_set readFds; struct fd_set writeFds; struct fd_set *prfds = NULL, *pwfds = NULL; FD_ZERO(&readFds); FD_ZERO(&writeFds); unsigned int i = 0; int ret = 0; if( dwSelFlags & L2PNET_SELECT_READ ) { for( i=0; i> 8) | \ (((w) & 0x00FF) << 8)) /* WORD host to network byte order conversion for little endian machines */ #define WH2N(w) \ ((((w) & 0xFF00) >> 8) | \ (((w) & 0x00FF) << 8)) /* DWORD network to host byte order conversion for little endian machines */ #define DN2H(dw) \ ((((dw) & 0xFF000000L) >> 24) | \ (((dw) & 0x00FF0000L) >> 8) | \ (((dw) & 0x0000FF00L) << 8) | \ (((dw) & 0x000000FFL) << 24)) /* DWORD host to network byte order conversion for little endian machines */ #define DH2N(dw) \ ((((dw) & 0xFF000000L) >> 24) | \ (((dw) & 0x00FF0000L) >> 8) | \ (((dw) & 0x0000FF00L) << 8) | \ (((dw) & 0x000000FFL) << 24)) unsigned long L2PNet_htonl( unsigned long hostlong ) { return DH2N(hostlong); } unsigned short L2PNet_htons( unsigned short hostshort ) { return WH2N(hostshort); } unsigned long L2PNet_ntohl( unsigned long netlong ) { return DN2H(netlong); } unsigned short L2PNet_ntohs( unsigned short netshort ) { return WN2H(netshort); } /* * FUNCTION: Converts a string containing an IPv4 address to an unsigned long * ARGUMENTS: * cp = Pointer to string with address to convert * RETURNS: * Binary representation of IPv4 address, or INADDR_NONE */ unsigned long L2PNet_inet_addr( const char *cp ) { unsigned int i; char *p; unsigned long u = 0; p = (char *)cp; if( !p ) return INADDR_NONE; if( strlen( p ) == 0 ) return INADDR_NONE; if( p[0] == 0 ) return INADDR_NONE; if( strcmp( p, " " ) == 0 ) return 0; for( i = 0; i <= 3; i++ ) { u += ( strtoul( p, &p, 0 ) << (i * 8) ); if( strlen( p ) == 0 ) return u; if( p[0] != '.' ) return INADDR_NONE; p++; } return u; } char *L2PNet_inet_ntoa( struct in_addr in ) { char b[10]; char *p = l2pnet_static_inet_ntoa_buffer; _itoa( in.S_un.S_addr & 0xFF, b, 10 ); strcpy( p, b ); _itoa( (in.S_un.S_addr >> 8) & 0xFF, b, 10 ); strcat( p, "." ); strcat( p, b ); _itoa( (in.S_un.S_addr >> 16) & 0xFF, b, 10 ); strcat( p, "." ); strcat( p, b ); _itoa( (in.S_un.S_addr >> 24) & 0xFF, b, 10 ); strcat( p, "." ); strcat( p, b ); return l2pnet_static_inet_ntoa_buffer; } /*typedef struct fd_set { u_int fd_count; // how many are SET SOCKET fd_array[FD_SETSIZE]; // an array of SOCKETs } fd_set;*/ int L2PNet_FD_ISSET( unsigned int sock, struct fd_set *set ) { unsigned int i; for ( i = 0; i < set->fd_count; i++ ) if ( set->fd_array[i] == sock ) return 1; return 0; } bool L2PNet_resolveHostname( const char *hostname, struct in_addr *pinAddr ) { in_addr addr; addr.s_addr = L2PNet_inet_addr( hostname ); if( addr.s_addr == INADDR_NONE ) { getaddrinfo_func getaddrinfo_ws2 = (getaddrinfo_func)GetProcAddress( l2pnet_hws2_32, "getaddrinfo" ); if( getaddrinfo_ws2 ) { addrinfo addr_hints; memset( &addr_hints, 0, sizeof(addr_hints) ); addr_hints.ai_family = AF_INET; addr_hints.ai_socktype = SOCK_STREAM; addrinfo *retAddr = NULL; int ret = getaddrinfo_ws2( hostname, NULL, &addr_hints, &retAddr ); if( ret == 0 ) // OK { if( retAddr ) { pinAddr->s_addr = ((sockaddr_in *)retAddr->ai_addr)->sin_addr.s_addr; freeaddrinfo_func freeaddr_ws2 = (freeaddrinfo_func)GetProcAddress( l2pnet_hws2_32, "freeaddrinfo" ); if( freeaddr_ws2 ) freeaddr_ws2( retAddr ); return true; } else { pinAddr->s_addr = INADDR_NONE; return false; } } else { pinAddr->s_addr = INADDR_NONE; return false; } } else { pinAddr->s_addr = INADDR_NONE; return false; } } else // hostname is already IP address { pinAddr->s_addr = addr.s_addr; } return true; }