Initial MSVC 2008 projects workspace
This commit is contained in:
318
l2packets/net_io/L2PacketReceiver.cpp
Normal file
318
l2packets/net_io/L2PacketReceiver.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
#include "stdafx.h"
|
||||
#include "L2Packet_NetLayer.h"
|
||||
#include "L2PacketReceiver.h"
|
||||
|
||||
//unsigned char l2p_packetReceive_dummyBuffer[2] = {0,0};
|
||||
|
||||
#ifdef L2PNET_ENABLE_OLD_RECVSEND
|
||||
|
||||
unsigned char *L2PacketReceive(
|
||||
unsigned int sock,
|
||||
long tv_sec, long tv_usec,
|
||||
unsigned int *rcvdLen )
|
||||
{
|
||||
if( !rcvdLen ) return NULL;
|
||||
(*rcvdLen) = 0;
|
||||
SOCKET s = (SOCKET)sock;
|
||||
if( s == INVALID_SOCKET ) return NULL;
|
||||
unsigned int plen = 0;
|
||||
int r = 0, rr = 0;
|
||||
unsigned char *packbuf = NULL;
|
||||
unsigned char *bufptr = NULL;
|
||||
//unsigned int buffree = 0;
|
||||
|
||||
// first try to receive packet len
|
||||
r = sock_tcp_wait_ready_to_recv( s, tv_sec, tv_usec );
|
||||
if( r <= 0 ) return NULL;
|
||||
r = recv( s, (char *)(&plen), 1, 0 );
|
||||
if( r == 0 ) return l2p_packetReceive_dummyBuffer;
|
||||
if( r != 1 ) return NULL;
|
||||
(*rcvdLen) = 1;
|
||||
|
||||
r = sock_tcp_wait_ready_to_recv( s, tv_sec, tv_usec );
|
||||
if( r <= 0 ) return NULL;
|
||||
r = recv( s, (char *)(&plen) + 1, 1, 0 );
|
||||
if( r == 0 ) return l2p_packetReceive_dummyBuffer;
|
||||
if( r != 1 ) return NULL;
|
||||
(*rcvdLen) = 2;
|
||||
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketReceive(): Received plen byte 2; plen is: %04X (%d)\n",
|
||||
plen, plen );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
|
||||
if( plen == 0 ) return NULL;
|
||||
|
||||
packbuf = (unsigned char *)malloc( plen + 2 );
|
||||
if( !packbuf ) return NULL;
|
||||
bufptr = packbuf + 2;
|
||||
memcpy( packbuf, &plen, 2 );
|
||||
|
||||
unsigned int nBytesRcvd = 2; // packet len already received
|
||||
unsigned int nTimeouts = 0;
|
||||
unsigned int maxTimeouts = 5;
|
||||
while( nBytesRcvd < plen )
|
||||
{
|
||||
r = sock_tcp_wait_ready_to_recv( s, tv_sec, tv_usec );
|
||||
if( r > 0 ) // select() OK
|
||||
{
|
||||
rr = recv( s, (char *)bufptr, (plen-nBytesRcvd), 0 );
|
||||
if( rr > 0 ) // recv() OK, received rr bytes
|
||||
{
|
||||
bufptr += rr;
|
||||
nBytesRcvd += rr;
|
||||
nTimeouts = 0;
|
||||
}
|
||||
else if( rr == 0 ) // recv() returns 0 when connection closed by remote host?
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketReceive(): recv() returned 0; received %u bytes\n",
|
||||
nBytesRcvd );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts ) break;
|
||||
}
|
||||
else if( rr == -1 ) // recv() error?
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketReceive(): recv returned -1; total received %u bytes\n",
|
||||
nBytesRcvd );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts ) break;
|
||||
}
|
||||
}
|
||||
else if ( r == 0 ) // select() timeout
|
||||
{
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts )
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketReceive(): select too many timeouts, > maximum of %d\n",
|
||||
maxTimeouts );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
}
|
||||
}
|
||||
else if( r == -1 )
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketReceive(): select ERROR!\n" );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts )
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketReceive(): select too many timeouts, > maximum of %d\n",
|
||||
maxTimeouts );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
}
|
||||
}
|
||||
} // while
|
||||
|
||||
if( nBytesRcvd == plen )
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketReceive(): Received full packet len %u\n", plen );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
(*rcvdLen) = plen;
|
||||
return packbuf;
|
||||
}
|
||||
else if( nBytesRcvd < plen )
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketReceive(): ERROR: packet not received full (%u < %u)\n",
|
||||
nBytesRcvd, plen );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
free( packbuf );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketReceive(): ERROR: Unknown error!\n" );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
|
||||
free( packbuf );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* L2PNET_ENABLE_OLD_RECVSEND */
|
||||
|
||||
|
||||
/**
|
||||
L2PacketReceive_malloc
|
||||
* Reads L2 packet from socket sock
|
||||
* Reads 1st 2 bytes, treates them as packet len, and then reads len bytes
|
||||
* places all received data (including 1st 2 bytes) in allocated by malloc() buffer.
|
||||
* Sets (*rcvdLen) to number of bytes received
|
||||
|
||||
* On read timeout (lWaitMiliSecs) returns NULL
|
||||
* On error returns NULL
|
||||
* returns pointer to buffer on success. caller should free returned buffer by free()
|
||||
*/
|
||||
unsigned char *L2PacketReceive_malloc( SOCKET sock, long lWaitMilliSecs, unsigned int *rcvdLen )
|
||||
{
|
||||
if( !rcvdLen ) return NULL;
|
||||
(*rcvdLen) = 0;
|
||||
if( sock == 0xFFFFFFFF ) return NULL;
|
||||
unsigned int plen = 0;
|
||||
int r = 0, rr = 0;
|
||||
unsigned char *packbuf = NULL;
|
||||
unsigned char *bufptr = NULL;
|
||||
|
||||
int rdyR = 0, rdyS = 0;
|
||||
|
||||
// first try to receive packet len
|
||||
r = L2PNet_select( sock, L2PNET_SELECT_READ, lWaitMilliSecs, &rdyR, &rdyS );
|
||||
if( r <= 0 ) return NULL;
|
||||
r = L2PNet_recv( sock, (unsigned char *)(&plen), 1 );
|
||||
if( r != 1 ) return NULL;
|
||||
(*rcvdLen) = 1;
|
||||
|
||||
r = L2PNet_select( sock, L2PNET_SELECT_READ, lWaitMilliSecs, &rdyR, &rdyS );
|
||||
if( r <= 0 ) return NULL;
|
||||
r = L2PNet_recv( sock, (unsigned char *)(&plen) + 1, 1 );
|
||||
if( r != 1 ) return NULL;
|
||||
(*rcvdLen) = 2;
|
||||
|
||||
if( plen == 0 ) return NULL;
|
||||
|
||||
packbuf = (unsigned char *)malloc( plen + 2 ); // possible speed loss <--------
|
||||
if( !packbuf ) return NULL;
|
||||
packbuf[0] = ((unsigned char *)&plen)[0];
|
||||
packbuf[1] = ((unsigned char *)&plen)[1];
|
||||
bufptr = packbuf + 2;
|
||||
|
||||
unsigned int nBytesRcvd = 2; // packet len already received
|
||||
unsigned int nTimeouts = 0;
|
||||
unsigned int maxTimeouts = 5;
|
||||
while( nBytesRcvd < plen )
|
||||
{
|
||||
(*rcvdLen) = nBytesRcvd;
|
||||
r = L2PNet_select( sock, L2PNET_SELECT_READ, lWaitMilliSecs, &rdyR, &rdyS );
|
||||
if( r > 0 ) // select() OK
|
||||
{
|
||||
rr = L2PNet_recv( sock, (unsigned char *)bufptr, (plen - nBytesRcvd) );
|
||||
if( rr > 0 ) // recv() OK, received rr bytes
|
||||
{
|
||||
bufptr += rr;
|
||||
nBytesRcvd += rr;
|
||||
nTimeouts = 0;
|
||||
}
|
||||
else if( rr <= 0 ) // recv() returns 0 when connection closed by remote host? or returns -1 on error
|
||||
{
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts ) break;
|
||||
}
|
||||
}
|
||||
else if ( r <= 0 ) // select() timeout or error
|
||||
{
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts ) break;
|
||||
}
|
||||
} // while
|
||||
|
||||
if( nBytesRcvd == plen ) // successful return
|
||||
{
|
||||
(*rcvdLen) = plen;
|
||||
return packbuf;
|
||||
}
|
||||
else if( nBytesRcvd < plen ) // received less than should, error
|
||||
{
|
||||
free( packbuf );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// other error
|
||||
free( packbuf );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
L2PacketReceive_buffer
|
||||
* Reads L2 packet from socket sock
|
||||
* Reads 1st 2 bytes, treates them as packet len, and then reads len bytes
|
||||
* places all received data (including 1st 2 bytes) in buffer recvBuffer.
|
||||
* Sets (*rcvdLen) to number of bytes received
|
||||
|
||||
* On read timeout (lWaitMiliSecs) returns 0
|
||||
* On error returns -1
|
||||
* returns 1 on success
|
||||
|
||||
* recvBuffer must point to big enough memory block (10 Kb min)
|
||||
*/
|
||||
int L2PacketReceive_buffer( SOCKET sock, long lWaitMilliSecs, unsigned int *rcvdLen, unsigned char *recvBuffer )
|
||||
{
|
||||
if( !rcvdLen || !recvBuffer ) return 0; // assert
|
||||
(*rcvdLen) = 0; // zero bytes received
|
||||
recvBuffer[0] = recvBuffer[1] = 0; // zero 1st 2 bytes in packet
|
||||
if( sock == 0xFFFFFFFF ) return 0; // assert
|
||||
unsigned int plen = 0; // receiving packet len
|
||||
int r = 0, rr = 0; // net functions results return codes
|
||||
unsigned char *bufptr = NULL; // current receive buffer pointer
|
||||
int rdyR = 0, rdyS = 0; // ready to recv, ready to send
|
||||
|
||||
// first try to receive packet len. receive 1st byte
|
||||
r = L2PNet_select( sock, L2PNET_SELECT_READ, lWaitMilliSecs, &rdyR, &rdyS );
|
||||
if( r <= 0 ) return r;
|
||||
r = L2PNet_recv( sock, (unsigned char *)(&plen), 1 );
|
||||
if( r <= 0 ) return r;
|
||||
(*rcvdLen) = 1;
|
||||
// receive 2nd byte
|
||||
r = L2PNet_select( sock, L2PNET_SELECT_READ, lWaitMilliSecs, &rdyR, &rdyS );
|
||||
if( r <= 0 ) return r;
|
||||
r = L2PNet_recv( sock, (unsigned char *)(&plen) + 1, 1 );
|
||||
if( r <= 0 ) return r;
|
||||
(*rcvdLen) = 2;
|
||||
|
||||
if( plen == 0 ) return 0; // protocol error - packet length 0 cannot be! minimum is 2
|
||||
|
||||
// set packet len in packet
|
||||
recvBuffer[0] = ((unsigned char *)&plen)[0];
|
||||
recvBuffer[1] = ((unsigned char *)&plen)[1];
|
||||
bufptr = recvBuffer + 2; // update current bufer pos to pass 1st 2 bytes
|
||||
|
||||
unsigned int nBytesRcvd = 2; // packet len already received
|
||||
unsigned int nTimeouts = 0; // number of timeouts on receive process
|
||||
unsigned int maxTimeouts = 5; // max.number of timeouts
|
||||
|
||||
// receive loop
|
||||
while( nBytesRcvd < plen )
|
||||
{
|
||||
(*rcvdLen) = nBytesRcvd;
|
||||
r = L2PNet_select( sock, L2PNET_SELECT_READ, lWaitMilliSecs, &rdyR, &rdyS );
|
||||
if( r > 0 ) // select() OK
|
||||
{
|
||||
rr = L2PNet_recv( sock, (unsigned char *)bufptr, (plen - nBytesRcvd) );
|
||||
if( rr > 0 ) // recv() OK, received rr bytes
|
||||
{
|
||||
bufptr += rr;
|
||||
nBytesRcvd += rr;
|
||||
nTimeouts = 0;
|
||||
}
|
||||
else if( rr <= 0 ) // recv() returns 0 when connection closed by remote host? or returns -1 on error
|
||||
{
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts ) break;
|
||||
}
|
||||
}
|
||||
else if ( r <= 0 ) // select() timeout or error
|
||||
{
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts ) break;
|
||||
}
|
||||
} // while
|
||||
|
||||
if( nBytesRcvd == plen ) // successful return
|
||||
{
|
||||
(*rcvdLen) = plen;
|
||||
return 1;
|
||||
}
|
||||
else if( nBytesRcvd < plen ) // received less than should, error
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// other error
|
||||
return -1;
|
||||
}
|
48
l2packets/net_io/L2PacketReceiver.h
Normal file
48
l2packets/net_io/L2PacketReceiver.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef L2PACKETREADER_H_
|
||||
#define L2PACKETREADER_H_
|
||||
|
||||
//#define L2P_NETWORK_DEBUGOUT
|
||||
|
||||
#ifdef L2PNET_ENABLE_OLD_RECVSEND
|
||||
unsigned char *L2PacketReceive(
|
||||
unsigned int sock,
|
||||
long tv_sec, long tv_usec,
|
||||
unsigned int *rcvdLen );
|
||||
|
||||
#endif /* L2PNET_ENABLE_OLD_RECVSEND */
|
||||
|
||||
/** L2PacketReceive_malloc:\n
|
||||
* Reads L2 packet from socket sock\n
|
||||
* Reads 1st 2 bytes, treates them as packet len, and then reads len bytes\n
|
||||
* places all received data (including 1st 2 bytes) in allocated by malloc() buffer.\n
|
||||
* Sets (*rcvdLen) to number of bytes received\n
|
||||
\n
|
||||
* On read timeout (lWaitMiliSecs) returns NULL\n
|
||||
* On error returns NULL\n
|
||||
* \return pointer to buffer on success. caller should free returned buffer by free(). On error returns NULL
|
||||
* \warning caller must free returned buffer by call to free()
|
||||
* \param sock - socket
|
||||
* \param lWaitMilliSecs - wait timeout
|
||||
* \param rcvdLen - (*rcvdLen) will be set to number of bytes successfuly received
|
||||
*/
|
||||
unsigned char *L2PacketReceive_malloc( SOCKET sock, long lWaitMilliSecs, unsigned int *rcvdLen );
|
||||
|
||||
/** L2PacketReceive_buffer\n
|
||||
* Reads L2 packet from socket sock\n
|
||||
* Reads 1st 2 bytes, treates them as packet len, and then reads len bytes\n
|
||||
* places all received data (including 1st 2 bytes) in buffer recvBuffer.\n
|
||||
* Sets (*rcvdLen) to number of bytes received\n
|
||||
\n
|
||||
* On read timeout (lWaitMiliSecs) returns 0\n
|
||||
* On error returns -1\n
|
||||
* \return 1 on success\n
|
||||
|
||||
* \warning recvBuffer must point to big enough memory block (10 Kb should be enough in all cases)\n
|
||||
* \param sock - socket
|
||||
* \param lWaitMilliSecs - wait timeout
|
||||
* \param rcvdLen - (*rcvdLen) will be set to number of bytes successfuly received
|
||||
* \param recvBuffer - buffer in which data will be placed
|
||||
*/
|
||||
int L2PacketReceive_buffer( SOCKET sock, long lWaitMilliSecs, unsigned int *rcvdLen, unsigned char *recvBuffer );
|
||||
|
||||
#endif /*L2PACKETREADER_H_*/
|
201
l2packets/net_io/L2PacketSender.cpp
Normal file
201
l2packets/net_io/L2PacketSender.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
#include "stdafx.h"
|
||||
#include "L2Packet_NetLayer.h"
|
||||
#include "../base/L2BasePacket.h"
|
||||
#include "L2PacketSender.h"
|
||||
|
||||
// return values:
|
||||
// > 0 on OK
|
||||
// 0 on timeout
|
||||
// -1 on error
|
||||
|
||||
// 1st 2 bytes of rawPacket must be packet size (as in all L2 protocol)
|
||||
/*int L2PacketSend_1byte( const unsigned char *rawPacket,
|
||||
unsigned int sock,
|
||||
long tv_sec, long tv_usec,
|
||||
unsigned int *sentLen )
|
||||
{
|
||||
if( !sentLen ) return -1;
|
||||
(*sentLen) = 0;
|
||||
if( !rawPacket ) return -1;
|
||||
SOCKET s = (SOCKET)sock;
|
||||
if( s == INVALID_SOCKET ) return -1;
|
||||
|
||||
int r = 0;
|
||||
unsigned int sentb = 0;
|
||||
unsigned int plen = 0;
|
||||
unsigned char *plenaddr = (unsigned char *)&plen;
|
||||
plenaddr[0] = rawPacket[0];
|
||||
plenaddr[1] = rawPacket[1];
|
||||
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketSend(): Sending %u len packet (0x%02X)\n", plen, plen );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
|
||||
int nTimeouts = 0;
|
||||
int maxTimeouts = 5;
|
||||
while( sentb < plen )
|
||||
{
|
||||
(*sentLen) = sentb;
|
||||
r = sock_tcp_wait_ready_to_send( s, tv_sec, tv_usec );
|
||||
if( r < 0 ) return r; // select returned error
|
||||
if( r == 0 ) // timeout
|
||||
{
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts )
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketSend(): select timeouts too many times (> %d)\n", maxTimeouts );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// if we're here, select OK
|
||||
nTimeouts = 0; // zero timeouts count
|
||||
r = send( s, (const char *)(rawPacket + sentb), 1, 0 );
|
||||
if( r > 0 ) sentb += r;
|
||||
else
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketSend(): send() returned %d!\n", r );
|
||||
if( r < 0 ) return r;
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
}
|
||||
(*sentLen) = sentb;
|
||||
}
|
||||
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketSend(): All %u (0x%02X) bytes sent\n", plen, plen );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
|
||||
return sentb;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef L2PNET_ENABLE_OLD_RECVSEND
|
||||
|
||||
// 1st 2 bytes of rawPacket must be packet size (as in all L2 protocol)
|
||||
int L2PacketSend( const unsigned char *rawPacket,
|
||||
unsigned int sock,
|
||||
long tv_sec, long tv_usec,
|
||||
unsigned int *sentLen )
|
||||
{
|
||||
if( !sentLen ) return -1;
|
||||
(*sentLen) = 0;
|
||||
if( !rawPacket ) return -1;
|
||||
SOCKET s = (SOCKET)sock;
|
||||
if( s == INVALID_SOCKET ) return -1;
|
||||
|
||||
int r = 0;
|
||||
unsigned int sentb = 0; // sent bytes
|
||||
unsigned int plen = 0;
|
||||
unsigned char *plenaddr = (unsigned char *)&plen;
|
||||
plenaddr[0] = rawPacket[0];
|
||||
plenaddr[1] = rawPacket[1];
|
||||
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketSend(): Sending %u len packet (0x%02X)\n", plen, plen );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
|
||||
int nTimeouts = 0;
|
||||
int maxTimeouts = 5;
|
||||
while( sentb < plen )
|
||||
{
|
||||
(*sentLen) = sentb;
|
||||
r = sock_tcp_wait_ready_to_send( s, tv_sec, tv_usec );
|
||||
if( r < 0 ) return r; // select returned error
|
||||
if( r == 0 ) // timeout
|
||||
{
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts )
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketSend(): select timeouts too many times (> %d)\n", maxTimeouts );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
return 0;
|
||||
}
|
||||
continue; // continue loop on select() timeout
|
||||
}
|
||||
// if we're here, select OK
|
||||
nTimeouts = 0; // zero timeouts count
|
||||
// we sent [sentb] bytes, left to send: [plen-sentb]
|
||||
r = send( s, (const char *)(rawPacket + sentb), (plen-sentb), 0 );
|
||||
if( r > 0 ) sentb += r;
|
||||
else
|
||||
{
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketSend(): send() returned %d!\n", r );
|
||||
if( r < 0 ) return r;
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
}
|
||||
(*sentLen) = sentb;
|
||||
}
|
||||
|
||||
#ifdef L2P_NETWORK_DEBUGOUT
|
||||
printf( "L2PacketSend(): All %u (0x%02X) bytes sent\n", plen, plen );
|
||||
#endif // L2P_NETWORK_DEBUGOUT
|
||||
|
||||
return sentb;
|
||||
}
|
||||
|
||||
#endif /* L2PNET_ENABLE_OLD_RECVSEND */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int L2PacketSend2( const unsigned char *rawPacket, unsigned int sock, long lWaitMilliSecs, unsigned int *sentLen )
|
||||
{
|
||||
if( !sentLen ) return -1;
|
||||
(*sentLen) = 0;
|
||||
if( !rawPacket ) return -1;
|
||||
if( sock == 0xFFFFFFFF ) return -1;
|
||||
|
||||
int r = 0;
|
||||
unsigned int sentb = 0; // sent bytes
|
||||
unsigned int plen = 0;
|
||||
unsigned char *plenaddr = (unsigned char *)&plen;
|
||||
plenaddr[0] = rawPacket[0];
|
||||
plenaddr[1] = rawPacket[1];
|
||||
|
||||
int rdyR = 0, rdyW = 0;
|
||||
|
||||
int nTimeouts = 0;
|
||||
int maxTimeouts = 5;
|
||||
while( sentb < plen )
|
||||
{
|
||||
(*sentLen) = sentb;
|
||||
//r = sock_tcp_wait_ready_to_send( s, tv_sec, tv_usec );
|
||||
r = L2PNet_select( sock, L2PNET_SELECT_WRITE, lWaitMilliSecs, &rdyR, &rdyW );
|
||||
if( r < 0 ) return r; // select returned error
|
||||
if( r == 0 ) // timeout
|
||||
{
|
||||
nTimeouts++;
|
||||
if( nTimeouts > maxTimeouts )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
continue; // continue loop on select() timeout
|
||||
}
|
||||
// if we're here, select OK
|
||||
nTimeouts = 0; // zero timeouts count
|
||||
// we sent [sentb] bytes, left to send: [plen-sentb]
|
||||
r = L2PNet_send( sock, (const unsigned char *)(rawPacket + sentb), (plen - sentb) );
|
||||
if( r > 0 ) sentb += r;
|
||||
else
|
||||
{
|
||||
if( r < 0 ) return r;
|
||||
}
|
||||
(*sentLen) = sentb;
|
||||
}
|
||||
|
||||
return sentb;
|
||||
}
|
||||
|
||||
int L2PacketSend( unsigned int sock, L2BasePacket *pack, long lWaitMilliSecs, unsigned int *sentLen )
|
||||
{
|
||||
return L2PacketSend2( pack->getBytesPtr(), sock, lWaitMilliSecs, sentLen );
|
||||
}
|
46
l2packets/net_io/L2PacketSender.h
Normal file
46
l2packets/net_io/L2PacketSender.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef L2PACKETSENDER_H_
|
||||
#define L2PACKETSENDER_H_
|
||||
|
||||
//#define L2P_NETWORK_DEBUGOUT
|
||||
|
||||
// return values:
|
||||
// > 0 on OK
|
||||
// 0 on timeout
|
||||
// -1 on error
|
||||
|
||||
// 1st 2 bytes of rawPacket must be packet size (as in all L2 protocol)
|
||||
/*int L2PacketSend_1byte( const unsigned char *rawPacket,
|
||||
unsigned int sock,
|
||||
long tv_sec, long tv_usec,
|
||||
unsigned int *sentLen );*/
|
||||
|
||||
#ifdef L2PNET_ENABLE_OLD_RECVSEND
|
||||
|
||||
// 1st 2 bytes of rawPacket must be packet size (as in all L2 protocol)
|
||||
int L2PacketSend( const unsigned char *rawPacket,
|
||||
unsigned int sock,
|
||||
long tv_sec, long tv_usec,
|
||||
unsigned int *sentLen );
|
||||
|
||||
#endif /* L2PNET_ENABLE_OLD_RECVSEND */
|
||||
|
||||
/** Sends packet to socket sock
|
||||
* \param rawPacket - bytes array of raw packet data
|
||||
* \param sock - socket
|
||||
* \param lWaitMilliSecs - send timeout
|
||||
* \param sentLen - (*sentLen) will be set to number of bytes successfully sent
|
||||
* \return values: > 0 on OK, 0 on timeout, -1 on error
|
||||
*/
|
||||
int L2PacketSend2( const unsigned char *rawPacket, unsigned int sock, long lWaitMilliSecs, unsigned int *sentLen );
|
||||
|
||||
/** Sends packet to socket sock.\n
|
||||
* Equivalent to call L2PacketSend2( pack->getBytesPtr(), sock, lWaitMilliSecs, sentLen );
|
||||
* \param sock - socket
|
||||
* \param pack - packet object
|
||||
* \param lWaitMilliSecs - send timeout
|
||||
* \param sentLen - (*sentLen) will be set to number of bytes successfully sent
|
||||
* \return values: > 0 on OK, 0 on timeout, -1 on error
|
||||
*/
|
||||
int L2PacketSend( unsigned int sock, L2BasePacket *pack, long lWaitMilliSecs, unsigned int *sentLen );
|
||||
|
||||
#endif /*L2PACKETSENDER_H_*/
|
634
l2packets/net_io/L2Packet_NetLayer.cpp
Normal file
634
l2packets/net_io/L2Packet_NetLayer.cpp
Normal file
@@ -0,0 +1,634 @@
|
||||
#include "stdafx.h"
|
||||
#include "L2Packet_NetLayer.h"
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
// 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; i++ ) l2pnet_ft[i] = NULL;
|
||||
l2pnet_hws2_32 = GetModuleHandle( TEXT("ws2_32.dll") );
|
||||
if( !l2pnet_hws2_32 )
|
||||
{
|
||||
l2pnet_hws2_32 = LoadLibrary( TEXT("ws2_32.dll") );
|
||||
if( !l2pnet_hws2_32 )
|
||||
{
|
||||
MessageBox( NULL, TEXT("L2Packets cannot load ws2_32.dll!\nFailing application!"),
|
||||
TEXT("L2Packets Error!"), MB_ICONSTOP );
|
||||
RaiseException( ERROR_FILE_NOT_FOUND, 0, 0, NULL );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ws2_func[L2PFUNC_CONNECT] = (void *)GetProcAddress( l2pnet_hws2_32, "connect" );
|
||||
ws2_func[L2PFUNC_SEND] = (void *)GetProcAddress( l2pnet_hws2_32, "send" );
|
||||
ws2_func[L2PFUNC_RECV] = (void *)GetProcAddress( l2pnet_hws2_32, "recv" );
|
||||
ws2_func[L2PFUNC_SHUTDOWN] = (void *)GetProcAddress( l2pnet_hws2_32, "shutdown" );
|
||||
ws2_func[L2PFUNC_CLOSESOCKET] = (void *)GetProcAddress( l2pnet_hws2_32, "closesocket" );
|
||||
ws2_func[L2PFUNC_BIND] = (void *)GetProcAddress( l2pnet_hws2_32, "bind" );
|
||||
ws2_func[L2PFUNC_ACCEPT] = (void *)GetProcAddress( l2pnet_hws2_32, "accept" );
|
||||
ws2_func[L2PFUNC_SELECT] = (void *)GetProcAddress( l2pnet_hws2_32, "select" );
|
||||
ws2_func[L2PFUNC_SOCKET] = (void *)GetProcAddress( l2pnet_hws2_32, "socket" );
|
||||
ws2_func[L2PFUNC_LISTEN] = (void *)GetProcAddress( l2pnet_hws2_32, "listen" );
|
||||
for( i=1; i<l2pnet_ft_size; i++ )
|
||||
{
|
||||
if( ws2_func[i] == NULL )
|
||||
{
|
||||
_stprintf( mes, _T("ws2_func[%d] == NULL !"), i );
|
||||
MessageBox( NULL, mes, TEXT("L2Packets Error!"), MB_ICONSTOP );
|
||||
}
|
||||
}
|
||||
//select_winsock = (select_func)GetProcAddress( l2pnet_hws2_32, "select" );
|
||||
WSAStartup_func WSAStartup_ws2 = (WSAStartup_func)GetProcAddress( l2pnet_hws2_32, "WSAStartup" );
|
||||
if( !WSAStartup_ws2 )
|
||||
{
|
||||
MessageBox( NULL, TEXT("L2Packets cannot load ws2_32.dll!WSAStartup( WORD, LPWSADATA )\nFailing application!"),
|
||||
TEXT("L2Packets Error!"), MB_ICONSTOP );
|
||||
RaiseException( ERROR_FILE_NOT_FOUND, 0, 0, NULL );
|
||||
}
|
||||
WORD wVersionRequested = MAKEWORD(2,0);
|
||||
WSADATA wsa;
|
||||
i = WSAStartup_ws2( wVersionRequested, &wsa );
|
||||
if( i != 0 )
|
||||
{
|
||||
MessageBox( NULL, TEXT("ws2_32.dll!WSAStartup() returned error!\nFailing application!"),
|
||||
TEXT("L2Packets Error!"), MB_ICONSTOP );
|
||||
RaiseException( ERROR_BAD_UNIT, 0, 0, NULL );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Closes winsock (wrapper around WSACleanup() **/
|
||||
int L2PNet_Cleanup()
|
||||
{
|
||||
WSACleanup_func WSACleanup_ws2 = (WSACleanup_func)GetProcAddress( l2pnet_hws2_32, "WSACleanup" );
|
||||
if( !WSACleanup_ws2 )
|
||||
{
|
||||
MessageBox( NULL, TEXT("L2Packets cannot load ws2_32.dll!WSACleanup(void)\nFailing application!"),
|
||||
TEXT("L2Packets Error!"), MB_ICONSTOP );
|
||||
RaiseException( ERROR_FILE_NOT_FOUND, 0, 0, NULL );
|
||||
return -1;
|
||||
}
|
||||
return WSACleanup_ws2();
|
||||
}
|
||||
|
||||
/** Overrides specified function for L2Packets network layer.
|
||||
** New function must have the same prototype as corresponding
|
||||
** L2PNet_* function! */
|
||||
void L2PNet_setFunction( int funcNo, void *func_addr )
|
||||
{
|
||||
if( (funcNo < 1) || (funcNo >= 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<socks_count; i++ ) FD_SET( socks_array[i], &readFds );
|
||||
prfds = &readFds;
|
||||
}
|
||||
if( dwSelFlags & L2PNET_SELECT_WRITE )
|
||||
{
|
||||
for( i=0; i<socks_count; i++ ) FD_SET( socks_array[i], &writeFds );
|
||||
pwfds = &writeFds;
|
||||
}
|
||||
long microsecs = lWaitMilliSecs * 1000; // 1 millisec = 1 000 microsec
|
||||
long secs = microsecs / 1000000; // 1 second = 1 000 000 microseconds
|
||||
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
|
||||
for( i=0; i<socks_count; i++ )
|
||||
{
|
||||
if( L2PNet_FD_ISSET( socks_array[i], &readFds ) && pbReadyForRead ) pbReadyForRead[i] = 1;
|
||||
if( L2PNet_FD_ISSET( socks_array[i], &writeFds ) && pbReadyForWrite ) pbReadyForWrite[i] = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Receives data from socket.
|
||||
** returns number of bytes read, 0 on connection closed, -1 on error */
|
||||
int L2PNet_recv( unsigned int sock, unsigned char *pucRecvBuffer, unsigned int uBufferSizeBytes )
|
||||
{
|
||||
int ret = -1;
|
||||
if( l2pnet_ft[L2PFUNC_RECV] )
|
||||
{
|
||||
ret = ( (int (*)(unsigned int, unsigned char *, unsigned int))(l2pnet_ft[L2PFUNC_RECV]) )
|
||||
( sock, pucRecvBuffer, uBufferSizeBytes );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ( (int (__stdcall*)(SOCKET, char *, int, int))(ws2_func[L2PFUNC_RECV]))
|
||||
( sock, (char *)pucRecvBuffer, (int)uBufferSizeBytes, 0 );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Writes data to socket.
|
||||
** returns number of bytes sent, -1 on error */
|
||||
int L2PNet_send( unsigned int sock, const unsigned char *pucSendBuffer, unsigned int uNumberOfBytesToSend )
|
||||
{
|
||||
int ret = -1;
|
||||
if( l2pnet_ft[L2PFUNC_SEND] )
|
||||
{
|
||||
ret = ( (int (*)(unsigned int, const unsigned char *, unsigned int))(l2pnet_ft[L2PFUNC_SEND]) )
|
||||
( sock, pucSendBuffer, uNumberOfBytesToSend );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ( (int (__stdcall*)(SOCKET, const char *, int, int))(ws2_func[L2PFUNC_SEND]))
|
||||
( sock, (const char *)pucSendBuffer, (int)uNumberOfBytesToSend, 0 );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Stops data transfer on socket, preparing to close. */
|
||||
int L2PNet_shutdown( unsigned int sock )
|
||||
{
|
||||
int ret = -1;
|
||||
if( l2pnet_ft[L2PFUNC_SHUTDOWN] )
|
||||
{
|
||||
ret = ( (int (*)(unsigned))(l2pnet_ft[L2PFUNC_SHUTDOWN]) )( sock );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ( (int (__stdcall*)(SOCKET,int))(ws2_func[L2PFUNC_SHUTDOWN]))( sock, 0x02 ); // SD_BOTH
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Closes socket and frees its resources from system. */
|
||||
int L2PNet_closesocket( unsigned int sock )
|
||||
{
|
||||
int ret = -1;
|
||||
if( l2pnet_ft[L2PFUNC_CLOSESOCKET] )
|
||||
{
|
||||
ret = ( (int (*)(unsigned))(l2pnet_ft[L2PFUNC_CLOSESOCKET]) )( sock );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ( (int (__stdcall*)(SOCKET))(ws2_func[L2PFUNC_CLOSESOCKET]))( sock );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Connects socket to specified address
|
||||
** returns -1 on error/timeout, 0 on error */
|
||||
int L2PNet_connect( unsigned int sock, const char *ip, unsigned short port )
|
||||
{
|
||||
if( !ip || (port == 0) ) return -1;
|
||||
int ret = -1;
|
||||
if( l2pnet_ft[L2PFUNC_CONNECT] )
|
||||
{
|
||||
ret = ( (int (*)(unsigned int, const char*, unsigned short))(l2pnet_ft[L2PFUNC_CONNECT]) )( sock, ip, port );
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
memset( &addr, 0, sizeof(addr) );
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = L2PNet_htons( port );
|
||||
addr.sin_addr.s_addr = L2PNet_inet_addr( ip );
|
||||
if( addr.sin_addr.s_addr == INADDR_NONE )
|
||||
{
|
||||
// try to resolve
|
||||
L2PNet_resolveHostname( ip, &addr.sin_addr );
|
||||
}
|
||||
ret = ( (int (__stdcall*)(SOCKET,const struct sockaddr*,int))(ws2_func[L2PFUNC_CONNECT]))
|
||||
( sock, (const struct sockaddr *)&addr, sizeof(addr) );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Binds socket to specified address
|
||||
** returns 0 on ok, -1 on error */
|
||||
int L2PNet_bind( unsigned int sock, const char *ip, unsigned short port )
|
||||
{
|
||||
int ret = -1;
|
||||
if( l2pnet_ft[L2PFUNC_BIND] )
|
||||
{
|
||||
ret = ( (int (*)(unsigned int, const char*, unsigned short))(l2pnet_ft[L2PFUNC_BIND]) )( sock, ip, port );
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
memset( &addr, 0, sizeof(addr) );
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = L2PNet_htons( port );
|
||||
addr.sin_addr.s_addr = L2PNet_inet_addr( ip );
|
||||
if( addr.sin_addr.s_addr == INADDR_NONE )
|
||||
{
|
||||
// try to resolve
|
||||
L2PNet_resolveHostname( ip, &addr.sin_addr );
|
||||
}
|
||||
ret = ( (int (__stdcall*)(SOCKET,const struct sockaddr *,int))(ws2_func[L2PFUNC_BIND]))
|
||||
( sock, (const struct sockaddr *)&addr, sizeof(addr) );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Starts listening on socket to aceept incoming connections
|
||||
** returns 0 on ok, -1 on error */
|
||||
int L2PNet_listen( unsigned int sock )
|
||||
{
|
||||
int ret = -1;
|
||||
if( l2pnet_ft[L2PFUNC_LISTEN] )
|
||||
{
|
||||
ret = ( (int (*)(unsigned))(l2pnet_ft[L2PFUNC_LISTEN]) )( sock );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ( (int (__stdcall*)(SOCKET,int))(ws2_func[L2PFUNC_LISTEN]))( sock, 1 );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Accepts incoming connection from socket
|
||||
** returns accepted socket on OK, -1 on error */
|
||||
unsigned int L2PNet_accept( unsigned int sock, char *acceptedIP, unsigned short *acceptedPort )
|
||||
{
|
||||
int ret = -1;
|
||||
if( l2pnet_ft[L2PFUNC_ACCEPT] )
|
||||
{
|
||||
ret = ( (int (*)(unsigned int, char *, unsigned short *))(l2pnet_ft[L2PFUNC_ACCEPT]) )
|
||||
( sock, acceptedIP, acceptedPort );
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
memset( &addr, 0, sizeof(addr) );
|
||||
int addrlen = sizeof(addr);
|
||||
ret = ( (int (__stdcall*)(SOCKET,struct sockaddr *,int *))(ws2_func[L2PFUNC_ACCEPT]))
|
||||
( sock, (struct sockaddr *)&addr, &addrlen );
|
||||
if( ret != -1 )
|
||||
{
|
||||
sprintf( acceptedIP, "%d.%d.%d.%d",
|
||||
(int)addr.sin_addr.S_un.S_un_b.s_b1,
|
||||
(int)addr.sin_addr.S_un.S_un_b.s_b2,
|
||||
(int)addr.sin_addr.S_un.S_un_b.s_b3,
|
||||
(int)addr.sin_addr.S_un.S_un_b.s_b4
|
||||
);
|
||||
(*acceptedPort) = L2PNet_ntohs( addr.sin_port );
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Wrapper around standard select() function **/
|
||||
/** !!! CANNOT BE OVERRIDED !!! **/
|
||||
int L2PNet_select_wrapper_DUMB( int nfds,
|
||||
fd_set *readFds,
|
||||
fd_set *writeFds,
|
||||
fd_set *exceptFds,
|
||||
const struct timeval *timeout )
|
||||
{
|
||||
if( !ws2_func[L2PFUNC_SELECT] )
|
||||
{
|
||||
//RaiseException(
|
||||
return -1;
|
||||
}
|
||||
int ret = ((select_func)(ws2_func[L2PFUNC_SELECT]))( nfds, readFds, writeFds, exceptFds, timeout );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Wrapper around WSAGetLastError() **/
|
||||
int L2PNet_WSAGetLastError(void)
|
||||
{
|
||||
WSAGetLastError_func WSAGetLastError_winsock = (WSAGetLastError_func)GetProcAddress
|
||||
( l2pnet_hws2_32, "WSAGetLastError" );
|
||||
if( !WSAGetLastError_winsock ) return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
int ret = WSAGetLastError_winsock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Wrapper around WSASetLastError() **/
|
||||
void L2PNet_WSASetLastError( int iError )
|
||||
{
|
||||
WSASetLastError_func WSASetLastError_winsock = (WSASetLastError_func)GetProcAddress
|
||||
( l2pnet_hws2_32, "WSASetLastError" );
|
||||
if( !WSASetLastError_winsock ) return;
|
||||
WSASetLastError_winsock( iError );
|
||||
return;
|
||||
}
|
||||
|
||||
/** Prints Winsock error code as string to specified file **/
|
||||
// incomplete errors list!!!!
|
||||
int L2PNet_WSAPrintLastError( FILE *f, int wsaerr )
|
||||
{
|
||||
if( !f ) return -1;
|
||||
char s[64] = {'U','N','K','N','O','W','N',0};
|
||||
switch( wsaerr )
|
||||
{
|
||||
case 0: strcpy( s, "ERROR_OK" ); break;
|
||||
case WSANOTINITIALISED: strcpy( s, "WSANOTINITIALISED" ); break;
|
||||
case WSAEFAULT: strcpy( s, "WSAEFAULT" ); break;
|
||||
case WSAENETDOWN: strcpy( s, "WSAENETDOWN" ); break;
|
||||
case WSAEINVAL: strcpy( s, "WSAEINVAL" ); break;
|
||||
case WSAEINTR: strcpy( s, "WSAEINTR" ); break;
|
||||
case WSAEINPROGRESS: strcpy( s, "WSAEINPROGRESS" ); break;
|
||||
case WSAENOTSOCK: strcpy( s, "WSAENOTSOCK" ); break;
|
||||
case WSAEWOULDBLOCK: strcpy( s, "WSAEWOULDBLOCK" ); break;
|
||||
case WSAECONNRESET: strcpy( s, "WSAECONNRESET" ); break;
|
||||
}
|
||||
return fprintf( f, "%d: %s", wsaerr, s );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// from reactos's ws2_32.dll
|
||||
//
|
||||
|
||||
/* WORD network to host order conversion for little endian machines */
|
||||
#define WN2H(w) \
|
||||
((((w) & 0xFF00) >> 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;
|
||||
}
|
195
l2packets/net_io/L2Packet_NetLayer.h
Normal file
195
l2packets/net_io/L2Packet_NetLayer.h
Normal file
@@ -0,0 +1,195 @@
|
||||
#ifndef H_L2P_NET_LAYER
|
||||
#define H_L2P_NET_LAYER
|
||||
|
||||
// define SOCKET type for Linux
|
||||
#ifdef L2PACKETS_LINUX
|
||||
typedef unsigned int SOCKET;
|
||||
#endif
|
||||
|
||||
/** Initializes L2Packets network layer.\n
|
||||
* Win32:\n
|
||||
* By default network functions L2PNet_* will be used,
|
||||
* which use corresponding Winsock2 functions.
|
||||
* Linux:\n
|
||||
* does nothing. Under Linux, most of functions here do nothing, they are just wrapper around glibc
|
||||
* \return 1 on success, 0 on error
|
||||
*/
|
||||
int L2PNet_InitDefault();
|
||||
|
||||
/** Closes winsock (Win32: wrapper around WSACleanup()) (Linux: does nothing) **/
|
||||
int L2PNet_Cleanup();
|
||||
|
||||
#ifdef L2PACKETS_WINDOWS
|
||||
#define L2PFUNC_CONNECT 1
|
||||
#define L2PFUNC_SEND 2
|
||||
#define L2PFUNC_RECV 3
|
||||
#define L2PFUNC_SHUTDOWN 4
|
||||
#define L2PFUNC_CLOSESOCKET 5
|
||||
#define L2PFUNC_BIND 6
|
||||
#define L2PFUNC_ACCEPT 7
|
||||
#define L2PFUNC_SELECT 8
|
||||
#define L2PFUNC_SOCKET 9
|
||||
#define L2PFUNC_LISTEN 10
|
||||
/** Overrides specified function for L2Packets network layer.\n
|
||||
* New function must have the same prototype as corresponding
|
||||
* L2PNet_* function!
|
||||
* only under Windows!
|
||||
* \param funcNo - function number to replace
|
||||
* \param func_addr - pointer to new function
|
||||
*/
|
||||
void L2PNet_setFunction( int funcNo, void *func_addr );
|
||||
#endif
|
||||
|
||||
/** Creates TCP socket
|
||||
* \param bUse_NonBlock_IO_Mode - if true, socket will be non-blocking
|
||||
* \return 0xFFFFFFFF on error, on success - socket [1..0xFFFFFFFE] :) */
|
||||
unsigned int L2PNet_TCPsocket_create( bool bUse_NonBlock_IO_Mode );
|
||||
|
||||
/** flag for L2PNet_select() to test for read ready */
|
||||
#define L2PNET_SELECT_READ 0x000000001
|
||||
/** flag for L2PNet_select() to test for write ready */
|
||||
#define L2PNET_SELECT_WRITE 0x000000002
|
||||
|
||||
/** Waits for socket to be ready for read or write
|
||||
* \param sock - socket
|
||||
* \param dwSelFlags - select flags (L2PNET_SELECT_READ|L2PNET_SELECT_WRITE)
|
||||
* \param lWaitMilliSecs - wait timeout in milliseconds
|
||||
* \param pbReadyForRead - (*pbReadyForRead) will be set to 1, if sock is ready to read. may be NULL
|
||||
* \param pbReadyForWrite - (*pbReadyForWrite) will be set to 1, if sock is ready to write. may be NULL
|
||||
* \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 (mya be NULL)
|
||||
|
||||
/** Check state for multiple sockets\n
|
||||
* \warning NOT DONE, DO NOT USE
|
||||
*/
|
||||
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
|
||||
|
||||
/** Receives data from socket.
|
||||
* \param sock - socket
|
||||
* \param pucRecvBuffer - pointer to receive buffer
|
||||
* \param uBufferSizeBytes - bufer size in bytes
|
||||
* \return number of bytes read, 0 on connection closed, -1 on error */
|
||||
int L2PNet_recv( unsigned int sock, unsigned char *pucRecvBuffer, unsigned int uBufferSizeBytes );
|
||||
|
||||
/** Writes data to socket.
|
||||
* \param sock - socket
|
||||
* \param pucSendBuffer - pointer to buffer to send
|
||||
* \param uNumberOfBytesToSend - number of bytes to send from buffer
|
||||
* \return number of bytes sent, -1 on error */
|
||||
int L2PNet_send( unsigned int sock, const unsigned char *pucSendBuffer, unsigned int uNumberOfBytesToSend );
|
||||
|
||||
/** Stops data transfer on socket, preparing to close.
|
||||
* \param sock - socket
|
||||
* \return dont care
|
||||
*/
|
||||
int L2PNet_shutdown( unsigned int sock );
|
||||
|
||||
/** Closes socket and frees its resources from system.
|
||||
* \param sock - socket
|
||||
* \return dont care
|
||||
*/
|
||||
int L2PNet_closesocket( unsigned int sock );
|
||||
|
||||
/** Connects socket to specified address
|
||||
* \param sock - socket
|
||||
* \param ip - string ip (ex. "127.0.0.1")
|
||||
* \param port - port to connect to
|
||||
* \return -1 on error/timeout, 0 on error */
|
||||
int L2PNet_connect( unsigned int sock, const char *ip, unsigned short port );
|
||||
|
||||
/** Binds socket to specified address
|
||||
* \param sock - socket
|
||||
* \param ip - IP to bind socket to
|
||||
* \param port - port to bind socket to
|
||||
* \returns 0 on ok, -1 on error */
|
||||
int L2PNet_bind( unsigned int sock, const char *ip, unsigned short port );
|
||||
|
||||
/** Starts listening on socket to aceept incoming connections
|
||||
* \param sock - socket
|
||||
* \returns 0 on ok, -1 on error */
|
||||
int L2PNet_listen( unsigned int sock );
|
||||
|
||||
/** Accepts incoming connection from socket
|
||||
* \param sock - socket
|
||||
* \param acceptedIP - will contain IP of accepted client
|
||||
* \param acceptedPort - (*acceptedPort) will be set to port of accepted client
|
||||
* \return accepted socket on OK, -1 on error */
|
||||
unsigned int L2PNet_accept( unsigned int sock, char *acceptedIP, unsigned short *acceptedPort );
|
||||
|
||||
/** Wrapper around standard WinSock select() function.
|
||||
* \param nfds - ignored on Win32
|
||||
* \param readFds - fd_set of sockets to test to readability
|
||||
* \param writeFds - fd_set of sockets to test to writeability
|
||||
* \param exceptFds - fd_set of sockets to test for errors
|
||||
* \param timeout - timeval struct, wait timeout
|
||||
* \warning !!! CANNOT BE OVERRIDED !!! by L2PNet_setFunction() (only for Win32)
|
||||
*/
|
||||
int L2PNet_select_wrapper_DUMB( int nfds,
|
||||
fd_set *readFds,
|
||||
fd_set *writeFds,
|
||||
fd_set *exceptFds,
|
||||
const struct timeval *timeout );
|
||||
|
||||
/** Win32: Wrapper around WSAGetLastError()\n
|
||||
* Linux: returns same as errno
|
||||
* \return last error code
|
||||
*/
|
||||
int L2PNet_WSAGetLastError(void);
|
||||
|
||||
/** Win32: Wrapper around WSASetLastError()
|
||||
* Linux: does nothing
|
||||
*/
|
||||
void L2PNet_WSASetLastError( int iError );
|
||||
|
||||
/** Prints Winsock error code as string to specified file.\n
|
||||
* Under linux uses strerror()
|
||||
* \warning Win32: incomplete errors list!!!!
|
||||
*/
|
||||
int L2PNet_WSAPrintLastError( FILE *f, int wsaerr );
|
||||
|
||||
|
||||
|
||||
// socket functions duplications
|
||||
|
||||
/** host-to-network-long */
|
||||
unsigned long L2PNet_htonl( unsigned long hostlong );
|
||||
/** host-to-network-short */
|
||||
unsigned short L2PNet_htons( unsigned short hostshort );
|
||||
/** net-to-host-long */
|
||||
unsigned long L2PNet_ntohl( unsigned long netlong );
|
||||
/** net-to-host-short */
|
||||
unsigned short L2PNet_ntohs( unsigned short netshort );
|
||||
|
||||
|
||||
/** Converts a string containing an IPv4 address to an unsigned long
|
||||
* \param cp - Pointer to string with address to convert
|
||||
* \return Binary representation of IPv4 address, or INADDR_NONE
|
||||
*/
|
||||
unsigned long L2PNet_inet_addr( const char *cp );
|
||||
|
||||
/* Replacer for inet_ntoa(). Converts IP address form binary form to string.
|
||||
* \param in struct in_addr ip address to convert to string
|
||||
* \warning This function is not thread-safe now -_-
|
||||
*/
|
||||
char *L2PNet_inet_ntoa( struct in_addr in );
|
||||
|
||||
/** Cross-platform FD_ISSET() macro replacement */
|
||||
int L2PNet_FD_ISSET( unsigned int sock, fd_set *set );
|
||||
|
||||
/** Resolves hostname, places result in in_addr struct.\n
|
||||
* If string in hostname is ip, works like inet_addr() :)
|
||||
* \param hostname input string with hostname
|
||||
* \param pinAddr output struct. pinAddr->s_addr will be resulting IP address
|
||||
*/
|
||||
bool L2PNet_resolveHostname( const char *hostname, struct in_addr *pinAddr );
|
||||
|
||||
#endif /* H_L2P_NET_LAYER */
|
416
l2packets/net_io/L2Packet_NetLayer_linux.cpp
Normal file
416
l2packets/net_io/L2Packet_NetLayer_linux.cpp
Normal file
@@ -0,0 +1,416 @@
|
||||
#include "stdafx.h"
|
||||
#include "L2Packet_NetLayer.h"
|
||||
|
||||
// keeps result of inet_ntoa
|
||||
char l2pnet_static_inet_ntoa_buffer[32];
|
||||
|
||||
int L2PNet_InitDefault()
|
||||
{
|
||||
l2pnet_static_inet_ntoa_buffer[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Closes winsock (wrapper around WSACleanup() **/
|
||||
int L2PNet_Cleanup()
|
||||
{
|
||||
// does nothing
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Creates TCP socket
|
||||
** returns 0xFFFFFFFF on error, on success - [1..0xFFFFFFFE] :) */
|
||||
unsigned int L2PNet_TCPsocket_create( bool bUse_NonBlock_IO_Mode )
|
||||
{
|
||||
int sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
|
||||
if( sock == -1 ) return 0xFFFFFFFF;
|
||||
if( bUse_NonBlock_IO_Mode )
|
||||
{
|
||||
int fl = fcntl( sock, F_GETFL, 0 );
|
||||
fl |= O_NONBLOCK;
|
||||
fcntl( sock, F_SETFL, fl );
|
||||
}
|
||||
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)
|
||||
{
|
||||
// L2PNet_select_dumb
|
||||
if( dwSelFlags == 0 ) return -1;
|
||||
if( pbReadyForRead ) (*pbReadyForRead) = 0;
|
||||
if( pbReadyForWrite ) (*pbReadyForWrite) = 0;
|
||||
fd_set readFds;
|
||||
fd_set writeFds;
|
||||
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;
|
||||
int ret = select( sock+1, 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 );
|
||||
fd_set readFds;
|
||||
fd_set writeFds;
|
||||
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<socks_count; i++ ) FD_SET( socks_array[i], &readFds );
|
||||
prfds = &readFds;
|
||||
}
|
||||
if( dwSelFlags & L2PNET_SELECT_WRITE )
|
||||
{
|
||||
for( i=0; i<socks_count; i++ ) FD_SET( socks_array[i], &writeFds );
|
||||
pwfds = &writeFds;
|
||||
}
|
||||
// calc nfds - get max socket fd
|
||||
int nfds = socks_array[0];
|
||||
for( i=0; i<socks_count; i++ ) if( nfds > (int)(socks_array[i]) ) nfds = (int)(socks_array[i]);
|
||||
// init timeval
|
||||
long microsecs = lWaitMilliSecs * 1000; // 1 millisec = 1 000 microsec
|
||||
long secs = microsecs / 1000000; // 1 second = 1 000 000 microseconds
|
||||
microsecs -= secs * 1000000;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = secs;
|
||||
tv.tv_usec = microsecs;
|
||||
ret = select( nfds+1, prfds, pwfds, NULL, &tv );
|
||||
if( ret == 0 ) return 0; // timeout failed
|
||||
if( ret == -1 ) return -1; // select error
|
||||
// results
|
||||
for( i=0; i<socks_count; i++ )
|
||||
{
|
||||
if( L2PNet_FD_ISSET( socks_array[i], &readFds ) && pbReadyForRead ) pbReadyForRead[i] = 1;
|
||||
if( L2PNet_FD_ISSET( socks_array[i], &writeFds ) && pbReadyForWrite ) pbReadyForWrite[i] = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Receives data from socket.
|
||||
** returns number of bytes read, 0 on connection closed, -1 on error */
|
||||
int L2PNet_recv( unsigned int sock, unsigned char *pucRecvBuffer, unsigned int uBufferSizeBytes )
|
||||
{
|
||||
int ret = -1;
|
||||
ret = recv( sock, pucRecvBuffer, (int)uBufferSizeBytes, 0 );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Writes data to socket.
|
||||
** returns number of bytes sent, -1 on error */
|
||||
int L2PNet_send( unsigned int sock, const unsigned char *pucSendBuffer, unsigned int uNumberOfBytesToSend )
|
||||
{
|
||||
int ret = -1;
|
||||
ret = send( sock, pucSendBuffer, (int)uNumberOfBytesToSend, 0 );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Stops data transfer on socket, preparing to close. */
|
||||
int L2PNet_shutdown( unsigned int sock )
|
||||
{
|
||||
int ret = -1;
|
||||
ret = shutdown( sock, 0 );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Closes socket and frees its resources from system. */
|
||||
int L2PNet_closesocket( unsigned int sock )
|
||||
{
|
||||
int ret = -1;
|
||||
ret = close( sock );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Connects socket to specified address
|
||||
** returns -1 on error/timeout, 0 on error */
|
||||
int L2PNet_connect( unsigned int sock, const char *ip, unsigned short port )
|
||||
{
|
||||
if( !ip || (port == 0) ) return -1;
|
||||
int ret = -1;
|
||||
sockaddr_in addr;
|
||||
memset( &addr, 0, sizeof(addr) );
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = L2PNet_htons( port );
|
||||
addr.sin_addr.s_addr = L2PNet_inet_addr( ip );
|
||||
if( addr.sin_addr.s_addr == INADDR_NONE )
|
||||
{
|
||||
// try to resolve
|
||||
L2PNet_resolveHostname( ip, &addr.sin_addr );
|
||||
}
|
||||
ret = connect( sock, (const sockaddr *)&addr, sizeof(addr) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Binds socket to specified address
|
||||
** returns 0 on ok, -1 on error */
|
||||
int L2PNet_bind( unsigned int sock, const char *ip, unsigned short port )
|
||||
{
|
||||
sockaddr_in addr;
|
||||
memset( &addr, 0, sizeof(addr) );
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = L2PNet_htons( port );
|
||||
addr.sin_addr.s_addr = L2PNet_inet_addr( ip );
|
||||
if( addr.sin_addr.s_addr == INADDR_NONE )
|
||||
{
|
||||
// try to resolve
|
||||
L2PNet_resolveHostname( ip, &addr.sin_addr );
|
||||
}
|
||||
int ret = bind( sock, (const sockaddr *)&addr, sizeof(addr) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Starts listening on socket to aceept incoming connections
|
||||
** returns 0 on ok, -1 on error */
|
||||
int L2PNet_listen( unsigned int sock )
|
||||
{
|
||||
int ret = -1;
|
||||
ret = listen( sock, 1 );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Accepts incoming connection from socket
|
||||
** returns accepted socket on OK, -1 on error */
|
||||
unsigned int L2PNet_accept( unsigned int sock, char *acceptedIP, unsigned short *acceptedPort )
|
||||
{
|
||||
sockaddr_in addr;
|
||||
memset( &addr, 0, sizeof(addr) );
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
int ret = accept( sock, (sockaddr *)&addr, &addrlen );
|
||||
if( ret != -1 )
|
||||
{
|
||||
sprintf( acceptedIP, "%d.%d.%d.%d",
|
||||
(int)( (addr.sin_addr.s_addr & 0x000000FF) ),
|
||||
(int)( (addr.sin_addr.s_addr & 0x0000FF00) >> 8),
|
||||
(int)( (addr.sin_addr.s_addr & 0x00FF0000) >> 16),
|
||||
(int)( (addr.sin_addr.s_addr & 0xFF000000) >> 24)
|
||||
);
|
||||
(*acceptedPort) = L2PNet_ntohs( addr.sin_port );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Wrapper around standard select() function **/
|
||||
/** !!! CANNOT BE OVERRIDED !!! **/
|
||||
int L2PNet_select_wrapper_DUMB( int nfds,
|
||||
fd_set *readFds,
|
||||
fd_set *writeFds,
|
||||
fd_set *exceptFds,
|
||||
const struct timeval *timeout )
|
||||
{
|
||||
timeval *tv_noconst = const_cast<timeval *>(timeout);
|
||||
int ret = select( nfds, readFds, writeFds, exceptFds, tv_noconst );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Wrapper around WSAGetLastError() **/
|
||||
int L2PNet_WSAGetLastError(void)
|
||||
{
|
||||
int ret = errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Wrapper around WSASetLastError() **/
|
||||
void L2PNet_WSASetLastError( int iError )
|
||||
{
|
||||
iError = 0;
|
||||
// does nothing
|
||||
return;
|
||||
}
|
||||
|
||||
/** Prints Winsock error code as string to specified file **/
|
||||
// incomplete errors list!!!!
|
||||
int L2PNet_WSAPrintLastError( FILE *f, int wsaerr )
|
||||
{
|
||||
if( !f ) return -1;
|
||||
return fprintf( f, "%d: %s", wsaerr, strerror( wsaerr ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// from reactos's ws2_32.dll
|
||||
//
|
||||
|
||||
/* WORD network to host order conversion for little endian machines */
|
||||
#define WN2H(w) \
|
||||
((((w) & 0xFF00) >> 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_addr & 0xFF, b, 10 );
|
||||
sprintf( b, "%d", (int)(in.s_addr & 0xFF) );
|
||||
strcpy( p, b );
|
||||
//itoa( (in.s_addr >> 8) & 0xFF, b, 10 );
|
||||
sprintf( b, "%d", (int)((in.s_addr >> 8) & 0xFF) );
|
||||
strcat( p, "." );
|
||||
strcat( p, b );
|
||||
//itoa( (in.s_addr >> 16) & 0xFF, b, 10 );
|
||||
sprintf( b, "%d", (int)((in.s_addr >> 16) & 0xFF) );
|
||||
strcat( p, "." );
|
||||
strcat( p, b );
|
||||
//itoa( (in.s_addr >> 24) & 0xFF, b, 10 );
|
||||
sprintf( b, "%d", (int)((in.s_addr >> 24) & 0xFF) );
|
||||
strcat( p, "." );
|
||||
strcat( p, b );
|
||||
|
||||
return l2pnet_static_inet_ntoa_buffer;
|
||||
}
|
||||
|
||||
// :(((
|
||||
int L2PNet_FD_ISSET( unsigned int sock, fd_set *set )
|
||||
{
|
||||
int ret = FD_ISSET( sock, set );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
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( hostname, NULL, &addr_hints, &retAddr );
|
||||
if( ret == 0 ) // OK
|
||||
{
|
||||
if( retAddr )
|
||||
{
|
||||
pinAddr->s_addr = ((sockaddr_in *)retAddr->ai_addr)->sin_addr.s_addr;
|
||||
freeaddrinfo( retAddr );
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
Reference in New Issue
Block a user