the whole game
This commit is contained in:
816
project/lib_projects/raknet/jni/RaknetSources/UDPForwarder.cpp
Executable file
816
project/lib_projects/raknet/jni/RaknetSources/UDPForwarder.cpp
Executable file
@@ -0,0 +1,816 @@
|
||||
#include "UDPForwarder.h"
|
||||
|
||||
#if _RAKNET_SUPPORT_UDPForwarder==1
|
||||
|
||||
#include "GetTime.h"
|
||||
#include "MTUSize.h"
|
||||
#include "SocketLayer.h"
|
||||
#include "WSAStartupSingleton.h"
|
||||
#include "RakSleep.h"
|
||||
#include "DS_OrderedList.h"
|
||||
#include "LinuxStrings.h"
|
||||
#include "SocketDefines.h"
|
||||
#include "VitaIncludes.h"
|
||||
|
||||
using namespace RakNet;
|
||||
static const unsigned short DEFAULT_MAX_FORWARD_ENTRIES=64;
|
||||
|
||||
#ifdef UDP_FORWARDER_EXECUTE_THREADED
|
||||
namespace RakNet
|
||||
{
|
||||
RAK_THREAD_DECLARATION(UpdateUDPForwarder);
|
||||
}
|
||||
#endif
|
||||
|
||||
int UDPForwarder::SrcAndDestForwardEntryComp( const UDPForwarder::SrcAndDest &inputKey, UDPForwarder::ForwardEntry * const &cls )
|
||||
{
|
||||
if (inputKey.source < cls->srcAndDest.source)
|
||||
return -1;
|
||||
|
||||
if (inputKey.source > cls->srcAndDest.source)
|
||||
return 1;
|
||||
|
||||
if (inputKey.dest < cls->srcAndDest.dest)
|
||||
return -1;
|
||||
|
||||
if (inputKey.dest > cls->srcAndDest.dest)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
bool operator<( const DataStructures::MLKeyRef<UDPForwarder::SrcAndDest> &inputKey, const UDPForwarder::ForwardEntry *cls )
|
||||
{
|
||||
return inputKey.Get().source < cls->srcAndDest.source ||
|
||||
(inputKey.Get().source == cls->srcAndDest.source && inputKey.Get().dest < cls->srcAndDest.dest);
|
||||
}
|
||||
bool operator>( const DataStructures::MLKeyRef<UDPForwarder::SrcAndDest> &inputKey, const UDPForwarder::ForwardEntry *cls )
|
||||
{
|
||||
return inputKey.Get().source > cls->srcAndDest.source ||
|
||||
(inputKey.Get().source == cls->srcAndDest.source && inputKey.Get().dest > cls->srcAndDest.dest);
|
||||
}
|
||||
bool operator==( const DataStructures::MLKeyRef<UDPForwarder::SrcAndDest> &inputKey, const UDPForwarder::ForwardEntry *cls )
|
||||
{
|
||||
return inputKey.Get().source == cls->srcAndDest.source && inputKey.Get().dest == cls->srcAndDest.dest;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
UDPForwarder::ForwardEntry::ForwardEntry() {socket=INVALID_SOCKET; timeLastDatagramForwarded=RakNet::GetTimeMS(); updatedSourcePort=false; updatedDestPort=false;}
|
||||
UDPForwarder::ForwardEntry::~ForwardEntry() {
|
||||
if (socket!=INVALID_SOCKET)
|
||||
closesocket__(socket);
|
||||
}
|
||||
|
||||
UDPForwarder::UDPForwarder()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSAStartupSingleton::AddRef();
|
||||
#endif
|
||||
|
||||
maxForwardEntries=DEFAULT_MAX_FORWARD_ENTRIES;
|
||||
isRunning=false;
|
||||
threadRunning=false;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
UDPForwarder::~UDPForwarder()
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
#ifdef _WIN32
|
||||
WSAStartupSingleton::Deref();
|
||||
#endif
|
||||
}
|
||||
void UDPForwarder::Startup(void)
|
||||
{
|
||||
if (isRunning==true)
|
||||
return;
|
||||
|
||||
isRunning=true;
|
||||
threadRunning=false;
|
||||
|
||||
#ifdef UDP_FORWARDER_EXECUTE_THREADED
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int errorCode;
|
||||
|
||||
|
||||
|
||||
|
||||
errorCode = RakNet::RakThread::Create(UpdateUDPForwarder, this);
|
||||
|
||||
if ( errorCode != 0 )
|
||||
{
|
||||
RakAssert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
while (threadRunning==false)
|
||||
RakSleep(30);
|
||||
#endif
|
||||
}
|
||||
void UDPForwarder::Shutdown(void)
|
||||
{
|
||||
if (isRunning==false)
|
||||
return;
|
||||
|
||||
isRunning=false;
|
||||
|
||||
#ifdef UDP_FORWARDER_EXECUTE_THREADED
|
||||
while (threadRunning==true)
|
||||
RakSleep(30);
|
||||
#endif
|
||||
|
||||
unsigned int j;
|
||||
for (j=0; j < forwardList.Size(); j++)
|
||||
RakNet::OP_DELETE(forwardList[j],_FILE_AND_LINE_);
|
||||
forwardList.Clear(false, _FILE_AND_LINE_);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
void UDPForwarder::Update(void)
|
||||
{
|
||||
#ifndef UDP_FORWARDER_EXECUTE_THREADED
|
||||
#if RAKNET_SUPPORT_IPV6!=1
|
||||
UpdateThreaded_Old();
|
||||
#else
|
||||
UpdateThreaded();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
void UDPForwarder::UpdateThreaded_Old(void)
|
||||
{
|
||||
fd_set readFD;
|
||||
//fd_set exceptionFD;
|
||||
FD_ZERO(&readFD);
|
||||
// FD_ZERO(&exceptionFD);
|
||||
int selectResult;
|
||||
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec=0;
|
||||
tv.tv_usec=0;
|
||||
|
||||
|
||||
RakNet::TimeMS curTime = RakNet::GetTimeMS();
|
||||
|
||||
SOCKET largestDescriptor=0;
|
||||
unsigned int i;
|
||||
|
||||
// Remove unused entries
|
||||
i=0;
|
||||
while (i < forwardList.Size())
|
||||
{
|
||||
if (curTime > forwardList[i]->timeLastDatagramForwarded && // Account for timestamp wrap
|
||||
curTime > forwardList[i]->timeLastDatagramForwarded+forwardList[i]->timeoutOnNoDataMS)
|
||||
{
|
||||
RakNet::OP_DELETE(forwardList[i],_FILE_AND_LINE_);
|
||||
forwardList.RemoveAtIndex(i);
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
if (forwardList.Size()==0)
|
||||
return;
|
||||
|
||||
for (i=0; i < forwardList.Size(); i++)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
|
||||
#endif
|
||||
FD_SET(forwardList[i]->socket, &readFD);
|
||||
// FD_SET(forwardList[i]->readSocket, &exceptionFD);
|
||||
|
||||
if (forwardList[i]->socket > largestDescriptor)
|
||||
largestDescriptor = forwardList[i]->socket;
|
||||
}
|
||||
|
||||
|
||||
selectResult=(int) select__((int) largestDescriptor+1, &readFD, 0, 0, &tv);
|
||||
|
||||
|
||||
|
||||
|
||||
char data[ MAXIMUM_MTU_SIZE ];
|
||||
sockaddr_in sa;
|
||||
socklen_t len2;
|
||||
|
||||
if (selectResult > 0)
|
||||
{
|
||||
DataStructures::Queue<ForwardEntry*> entriesToRead;
|
||||
ForwardEntry *forwardEntry;
|
||||
|
||||
for (i=0; i < forwardList.Size(); i++)
|
||||
{
|
||||
forwardEntry = forwardList[i];
|
||||
// I do this because I'm updating the forwardList, and don't want to lose FD_ISSET as the list is no longer in order
|
||||
if (FD_ISSET(forwardEntry->socket, &readFD))
|
||||
entriesToRead.Push(forwardEntry,_FILE_AND_LINE_);
|
||||
}
|
||||
|
||||
while (entriesToRead.IsEmpty()==false)
|
||||
{
|
||||
forwardEntry=entriesToRead.Pop();
|
||||
|
||||
const int flag=0;
|
||||
int receivedDataLen, len=0;
|
||||
unsigned short portnum=0;
|
||||
len2 = sizeof( sa );
|
||||
sa.sin_family = AF_INET;
|
||||
receivedDataLen = recvfrom__( forwardEntry->socket, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sa, ( socklen_t* ) & len2 );
|
||||
|
||||
if (receivedDataLen<0)
|
||||
{
|
||||
#if defined(_WIN32) && defined(_DEBUG)
|
||||
DWORD dwIOError = WSAGetLastError();
|
||||
|
||||
if (dwIOError!=WSAECONNRESET && dwIOError!=WSAEINTR && dwIOError!=WSAETIMEDOUT)
|
||||
{
|
||||
LPVOID messageBuffer;
|
||||
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
||||
( LPTSTR ) & messageBuffer, 0, NULL );
|
||||
// something has gone wrong here...
|
||||
RAKNET_DEBUG_PRINTF( "recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
||||
|
||||
//Free the buffer.
|
||||
LocalFree( messageBuffer );
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
portnum = ntohs( sa.sin_port );
|
||||
if (forwardEntry->srcAndDest.source.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->updatedSourcePort==false && forwardEntry->srcAndDest.dest.GetPort()!=portnum)
|
||||
{
|
||||
forwardEntry->updatedSourcePort=true;
|
||||
|
||||
if (forwardEntry->srcAndDest.source.GetPort()!=portnum)
|
||||
{
|
||||
unsigned int index;
|
||||
SrcAndDest srcAndDest(forwardEntry->srcAndDest.dest, forwardEntry->srcAndDest.source);
|
||||
bool objectExists;
|
||||
index = forwardList.GetIndexFromKey(srcAndDest, &objectExists);
|
||||
if (objectExists)
|
||||
{
|
||||
forwardList.RemoveAtIndex(index);
|
||||
}
|
||||
forwardEntry->srcAndDest.source.SetPort(portnum);
|
||||
forwardList.Insert(forwardEntry->srcAndDest,forwardEntry,true,_FILE_AND_LINE_);
|
||||
}
|
||||
}
|
||||
|
||||
if (forwardEntry->srcAndDest.source.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->srcAndDest.source.GetPort()==portnum)
|
||||
{
|
||||
// Forward to dest
|
||||
len=0;
|
||||
sockaddr_in saOut;
|
||||
saOut.sin_port = forwardEntry->srcAndDest.dest.GetPortNetworkOrder(); // User port
|
||||
saOut.sin_addr.s_addr = forwardEntry->srcAndDest.dest.address.addr4.sin_addr.s_addr;
|
||||
saOut.sin_family = AF_INET;
|
||||
do
|
||||
{
|
||||
len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & saOut, sizeof( saOut ) );
|
||||
}
|
||||
while ( len == 0 );
|
||||
|
||||
// printf("1. Forwarding after %i ms\n", curTime-forwardEntry->timeLastDatagramForwarded);
|
||||
|
||||
forwardEntry->timeLastDatagramForwarded=curTime;
|
||||
}
|
||||
|
||||
if (forwardEntry->srcAndDest.dest.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->updatedDestPort==false && forwardEntry->srcAndDest.source.GetPort()!=portnum)
|
||||
{
|
||||
forwardEntry->updatedDestPort=true;
|
||||
|
||||
if (forwardEntry->srcAndDest.dest.GetPort()!=portnum)
|
||||
{
|
||||
unsigned int index;
|
||||
SrcAndDest srcAndDest(forwardEntry->srcAndDest.source, forwardEntry->srcAndDest.dest);
|
||||
bool objectExists;
|
||||
index = forwardList.GetIndexFromKey(srcAndDest, &objectExists);
|
||||
if (objectExists)
|
||||
{
|
||||
forwardList.RemoveAtIndex(index);
|
||||
}
|
||||
forwardEntry->srcAndDest.dest.SetPort(portnum);
|
||||
forwardList.Insert(forwardEntry->srcAndDest,forwardEntry,true,_FILE_AND_LINE_);
|
||||
}
|
||||
}
|
||||
|
||||
if (forwardEntry->srcAndDest.dest.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->srcAndDest.dest.GetPort()==portnum)
|
||||
{
|
||||
// Forward to source
|
||||
len=0;
|
||||
sockaddr_in saOut;
|
||||
saOut.sin_port = forwardEntry->srcAndDest.source.GetPortNetworkOrder(); // User port
|
||||
saOut.sin_addr.s_addr = forwardEntry->srcAndDest.source.address.addr4.sin_addr.s_addr;
|
||||
saOut.sin_family = AF_INET;
|
||||
do
|
||||
{
|
||||
len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & saOut, sizeof( saOut ) );
|
||||
}
|
||||
while ( len == 0 );
|
||||
|
||||
// printf("2. Forwarding after %i ms\n", curTime-forwardEntry->timeLastDatagramForwarded);
|
||||
|
||||
forwardEntry->timeLastDatagramForwarded=curTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if RAKNET_SUPPORT_IPV6==1
|
||||
void UDPForwarder::UpdateThreaded(void)
|
||||
{
|
||||
fd_set readFD;
|
||||
//fd_set exceptionFD;
|
||||
FD_ZERO(&readFD);
|
||||
// FD_ZERO(&exceptionFD);
|
||||
timeval tv;
|
||||
int selectResult;
|
||||
tv.tv_sec=0;
|
||||
tv.tv_usec=0;
|
||||
|
||||
RakNet::TimeMS curTime = RakNet::GetTimeMS();
|
||||
|
||||
SOCKET largestDescriptor=0;
|
||||
unsigned int i;
|
||||
|
||||
// Remove unused entries
|
||||
i=0;
|
||||
while (i < forwardList.Size())
|
||||
{
|
||||
if (curTime > forwardList[i]->timeLastDatagramForwarded && // Account for timestamp wrap
|
||||
curTime > forwardList[i]->timeLastDatagramForwarded+forwardList[i]->timeoutOnNoDataMS)
|
||||
{
|
||||
RakNet::OP_DELETE(forwardList[i],_FILE_AND_LINE_);
|
||||
forwardList.RemoveAtIndex(i);
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
if (forwardList.Size()==0)
|
||||
return;
|
||||
|
||||
for (i=0; i < forwardList.Size(); i++)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
|
||||
#endif
|
||||
FD_SET(forwardList[i]->socket, &readFD);
|
||||
// FD_SET(forwardList[i]->readSocket, &exceptionFD);
|
||||
|
||||
if (forwardList[i]->socket > largestDescriptor)
|
||||
largestDescriptor = forwardList[i]->socket;
|
||||
}
|
||||
|
||||
selectResult=(int) select__((int) largestDescriptor+1, &readFD, 0, 0, &tv);
|
||||
|
||||
char data[ MAXIMUM_MTU_SIZE ];
|
||||
sockaddr_storage their_addr;
|
||||
sockaddr* sockAddrPtr;
|
||||
socklen_t sockLen;
|
||||
socklen_t* socketlenPtr=(socklen_t*) &sockLen;
|
||||
sockaddr_in *sockAddrIn;
|
||||
sockaddr_in6 *sockAddrIn6;
|
||||
SystemAddress receivedAddr;
|
||||
sockLen=sizeof(their_addr);
|
||||
sockAddrPtr=(sockaddr*) &their_addr;
|
||||
|
||||
if (selectResult > 0)
|
||||
{
|
||||
DataStructures::Queue<ForwardEntry*> entriesToRead;
|
||||
ForwardEntry *forwardEntry;
|
||||
|
||||
for (i=0; i < forwardList.Size(); i++)
|
||||
{
|
||||
forwardEntry = forwardList[i];
|
||||
// I do this because I'm updating the forwardList, and don't want to lose FD_ISSET as the list is no longer in order
|
||||
if (FD_ISSET(forwardEntry->socket, &readFD))
|
||||
entriesToRead.Push(forwardEntry,_FILE_AND_LINE_);
|
||||
}
|
||||
|
||||
while (entriesToRead.IsEmpty()==false)
|
||||
{
|
||||
forwardEntry=entriesToRead.Pop();
|
||||
|
||||
const int flag=0;
|
||||
int receivedDataLen, len=0;
|
||||
receivedDataLen = recvfrom__( forwardEntry->socket, data, MAXIMUM_MTU_SIZE, flag, sockAddrPtr, socketlenPtr );
|
||||
|
||||
if (receivedDataLen<0)
|
||||
{
|
||||
#if defined(_WIN32) && defined(_DEBUG)
|
||||
DWORD dwIOError = WSAGetLastError();
|
||||
|
||||
if (dwIOError!=WSAECONNRESET && dwIOError!=WSAEINTR && dwIOError!=WSAETIMEDOUT)
|
||||
{
|
||||
LPVOID messageBuffer;
|
||||
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
|
||||
( LPTSTR ) & messageBuffer, 0, NULL );
|
||||
// something has gone wrong here...
|
||||
RAKNET_DEBUG_PRINTF( "recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer );
|
||||
|
||||
//Free the buffer.
|
||||
LocalFree( messageBuffer );
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (their_addr.ss_family==AF_INET)
|
||||
{
|
||||
sockAddrIn=(sockaddr_in *)&their_addr;
|
||||
sockAddrIn6=0;
|
||||
memcpy(&receivedAddr.address.addr4,sockAddrIn,sizeof(sockaddr_in));
|
||||
// receivedAddr.address.addr4.sin_port=ntohs( sockAddrIn->sin_port );
|
||||
}
|
||||
else
|
||||
{
|
||||
sockAddrIn=0;
|
||||
sockAddrIn6=(sockaddr_in6 *)&their_addr;
|
||||
memcpy(&receivedAddr.address.addr6,sockAddrIn6,sizeof(sockaddr_in6));
|
||||
// receivedAddr.address.addr6.sin6_port=ntohs( sockAddrIn6->sin6_port );
|
||||
}
|
||||
|
||||
if (forwardEntry->srcAndDest.source.EqualsExcludingPort(receivedAddr) && forwardEntry->updatedSourcePort==false && forwardEntry->srcAndDest.dest.GetPort()!=receivedAddr.GetPort())
|
||||
{
|
||||
forwardEntry->updatedSourcePort=true;
|
||||
|
||||
if (forwardEntry->srcAndDest.source.GetPort()!=receivedAddr.GetPort())
|
||||
{
|
||||
unsigned int index;
|
||||
SrcAndDest srcAndDest(forwardEntry->srcAndDest.dest, forwardEntry->srcAndDest.source);
|
||||
bool objectExists;
|
||||
index=forwardList.GetIndexFromKey(srcAndDest, &objectExists);
|
||||
forwardList.RemoveAtIndex(index);
|
||||
forwardEntry->srcAndDest.source.SetPort(receivedAddr.GetPort());
|
||||
forwardList.Push(forwardEntry,forwardEntry->srcAndDest,_FILE_AND_LINE_);
|
||||
}
|
||||
}
|
||||
|
||||
if (forwardEntry->srcAndDest.source.EqualsExcludingPort(receivedAddr) && forwardEntry->srcAndDest.source.GetPort()==receivedAddr.GetPort())
|
||||
{
|
||||
// Forward to dest
|
||||
len=0;
|
||||
|
||||
if (forwardEntry->srcAndDest.dest.address.addr4.sin_family==AF_INET)
|
||||
{
|
||||
do
|
||||
{
|
||||
len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & forwardEntry->srcAndDest.dest.address.addr4, sizeof( sockaddr_in ) );
|
||||
}
|
||||
while ( len == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & forwardEntry->srcAndDest.dest.address.addr6, sizeof( sockaddr_in ) );
|
||||
}
|
||||
while ( len == 0 );
|
||||
}
|
||||
|
||||
|
||||
// printf("1. Forwarding after %i ms\n", curTime-forwardEntry->timeLastDatagramForwarded);
|
||||
|
||||
forwardEntry->timeLastDatagramForwarded=curTime;
|
||||
}
|
||||
|
||||
if (forwardEntry->srcAndDest.dest.EqualsExcludingPort(receivedAddr) && forwardEntry->updatedDestPort==false && forwardEntry->srcAndDest.source.GetPort()!=receivedAddr.GetPort())
|
||||
{
|
||||
forwardEntry->updatedDestPort=true;
|
||||
|
||||
if (forwardEntry->srcAndDest.dest.GetPort()!=receivedAddr.GetPort())
|
||||
{
|
||||
unsigned int index;
|
||||
SrcAndDest srcAndDest(forwardEntry->srcAndDest.source, forwardEntry->srcAndDest.dest);
|
||||
index=forwardList.GetIndexOf(srcAndDest);
|
||||
forwardList.RemoveAtIndex(index);
|
||||
forwardEntry->srcAndDest.dest.SetPort(receivedAddr.GetPort());
|
||||
forwardList.Push(forwardEntry,forwardEntry->srcAndDest,_FILE_AND_LINE_);
|
||||
}
|
||||
}
|
||||
|
||||
if (forwardEntry->srcAndDest.dest.EqualsExcludingPort(receivedAddr) && forwardEntry->srcAndDest.dest.GetPort()==receivedAddr.GetPort())
|
||||
{
|
||||
// Forward to source
|
||||
len=0;
|
||||
if (forwardEntry->srcAndDest.source.address.addr4.sin_family==AF_INET)
|
||||
{
|
||||
do
|
||||
{
|
||||
len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & forwardEntry->srcAndDest.source.address.addr4, sizeof( sockaddr_in ) );
|
||||
}
|
||||
while ( len == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & forwardEntry->srcAndDest.source.address.addr6, sizeof( sockaddr_in ) );
|
||||
}
|
||||
while ( len == 0 );
|
||||
}
|
||||
|
||||
// printf("2. Forwarding after %i ms\n", curTime-forwardEntry->timeLastDatagramForwarded);
|
||||
|
||||
forwardEntry->timeLastDatagramForwarded=curTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // #if RAKNET_SUPPORT_IPV6!=1
|
||||
void UDPForwarder::SetMaxForwardEntries(unsigned short maxEntries)
|
||||
{
|
||||
RakAssert(maxEntries>0 && maxEntries<65535/2);
|
||||
maxForwardEntries=maxEntries;
|
||||
}
|
||||
int UDPForwarder::GetMaxForwardEntries(void) const
|
||||
{
|
||||
return maxForwardEntries;
|
||||
}
|
||||
int UDPForwarder::GetUsedForwardEntries(void) const
|
||||
{
|
||||
return (int) forwardList.Size();
|
||||
}
|
||||
UDPForwarderResult UDPForwarder::AddForwardingEntry(SrcAndDest srcAndDest, RakNet::TimeMS timeoutOnNoDataMS, unsigned short *port, const char *forceHostAddress, short socketFamily)
|
||||
{
|
||||
(void) socketFamily;
|
||||
|
||||
unsigned int insertionIndex;
|
||||
bool objectExists;
|
||||
insertionIndex = forwardList.GetIndexFromKey(srcAndDest, &objectExists);
|
||||
if (objectExists==false)
|
||||
{
|
||||
#if RAKNET_SUPPORT_IPV6!=1
|
||||
int sock_opt;
|
||||
sockaddr_in listenerSocketAddress;
|
||||
listenerSocketAddress.sin_port = 0;
|
||||
ForwardEntry *fe = RakNet::OP_NEW<UDPForwarder::ForwardEntry>(_FILE_AND_LINE_);
|
||||
fe->srcAndDest=srcAndDest;
|
||||
fe->timeoutOnNoDataMS=timeoutOnNoDataMS;
|
||||
fe->socket = socket__( AF_INET, SOCK_DGRAM, 0 );
|
||||
|
||||
//printf("Made socket %i\n", fe->readSocket);
|
||||
|
||||
// This doubles the max throughput rate
|
||||
sock_opt=1024*256;
|
||||
setsockopt__(fe->socket, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
|
||||
|
||||
// Immediate hard close. Don't linger the readSocket, or recreating the readSocket quickly on Vista fails.
|
||||
sock_opt=0;
|
||||
setsockopt__(fe->socket, SOL_SOCKET, SO_LINGER, ( char * ) & sock_opt, sizeof ( sock_opt ) );
|
||||
|
||||
listenerSocketAddress.sin_family = AF_INET;
|
||||
|
||||
if (forceHostAddress && forceHostAddress[0])
|
||||
{
|
||||
|
||||
|
||||
|
||||
listenerSocketAddress.sin_addr.s_addr = inet_addr__( forceHostAddress );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
listenerSocketAddress.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
|
||||
int ret = bind__( fe->socket, ( struct sockaddr * ) & listenerSocketAddress, sizeof( listenerSocketAddress ) );
|
||||
if (ret==-1)
|
||||
{
|
||||
RakNet::OP_DELETE(fe,_FILE_AND_LINE_);
|
||||
return UDPFORWARDER_BIND_FAILED;
|
||||
}
|
||||
#else
|
||||
ForwardEntry *fe = RakNet::OP_NEW<UDPForwarder::ForwardEntry>(_FILE_AND_LINE_);
|
||||
fe->srcAndDest=srcAndDest;
|
||||
fe->timeoutOnNoDataMS=timeoutOnNoDataMS;
|
||||
fe->socket=INVALID_SOCKET;
|
||||
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof (addrinfo)); // make sure the struct is empty
|
||||
hints.ai_family = socketFamily;
|
||||
hints.ai_socktype = SOCK_DGRAM; // UDP sockets
|
||||
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
|
||||
struct addrinfo *servinfo=0, *aip; // will point to the results
|
||||
|
||||
|
||||
RakAssert(forceHostAddress==0 || forceHostAddress[0]!=0);
|
||||
if (_stricmp(forceHostAddress,"UNASSIGNED_SYSTEM_ADDRESS")==0)
|
||||
{
|
||||
getaddrinfo(0, "0", &hints, &servinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
getaddrinfo(forceHostAddress, "0", &hints, &servinfo);
|
||||
}
|
||||
|
||||
for (aip = servinfo; aip != NULL; aip = aip->ai_next)
|
||||
{
|
||||
// Open socket. The address type depends on what
|
||||
// getaddrinfo() gave us.
|
||||
fe->socket = socket__(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
|
||||
if (fe->socket != INVALID_SOCKET)
|
||||
{
|
||||
int ret = bind__( fe->socket, aip->ai_addr, (int) aip->ai_addrlen );
|
||||
if (ret>=0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
closesocket__(fe->socket);
|
||||
fe->socket=INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fe->socket==INVALID_SOCKET)
|
||||
return UDPFORWARDER_BIND_FAILED;
|
||||
|
||||
//printf("Made socket %i\n", fe->readSocket);
|
||||
|
||||
// This doubles the max throughput rate
|
||||
int sock_opt;
|
||||
sock_opt=1024*256;
|
||||
setsockopt__(fe->socket, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
|
||||
|
||||
// Immediate hard close. Don't linger the readSocket, or recreating the readSocket quickly on Vista fails.
|
||||
sock_opt=0;
|
||||
setsockopt__(fe->socket, SOL_SOCKET, SO_LINGER, ( char * ) & sock_opt, sizeof ( sock_opt ) );
|
||||
#endif // #if RAKNET_SUPPORT_IPV6!=1
|
||||
|
||||
// unsigned int oldSize = forwardList.Size();
|
||||
forwardList.InsertAtIndex(fe,insertionIndex,_FILE_AND_LINE_);
|
||||
// RakAssert(forwardList.GetIndexOf(fe->srcAndDest)!=(unsigned int) -1);
|
||||
*port = SocketLayer::GetLocalPort ( fe->socket );
|
||||
return UDPFORWARDER_SUCCESS;
|
||||
}
|
||||
|
||||
return UDPFORWARDER_FORWARDING_ALREADY_EXISTS;
|
||||
}
|
||||
UDPForwarderResult UDPForwarder::StartForwarding(SystemAddress source, SystemAddress destination, RakNet::TimeMS timeoutOnNoDataMS, const char *forceHostAddress, unsigned short socketFamily,
|
||||
unsigned short *forwardingPort, SOCKET *forwardingSocket)
|
||||
{
|
||||
// Invalid parameters?
|
||||
if (timeoutOnNoDataMS == 0 || timeoutOnNoDataMS > UDP_FORWARDER_MAXIMUM_TIMEOUT || source==UNASSIGNED_SYSTEM_ADDRESS || destination==UNASSIGNED_SYSTEM_ADDRESS)
|
||||
return UDPFORWARDER_INVALID_PARAMETERS;
|
||||
|
||||
#ifdef UDP_FORWARDER_EXECUTE_THREADED
|
||||
ThreadOperation threadOperation;
|
||||
threadOperation.source=source;
|
||||
threadOperation.destination=destination;
|
||||
threadOperation.timeoutOnNoDataMS=timeoutOnNoDataMS;
|
||||
threadOperation.forceHostAddress=forceHostAddress;
|
||||
threadOperation.socketFamily=socketFamily;
|
||||
threadOperation.operation=ThreadOperation::TO_START_FORWARDING;
|
||||
threadOperationIncomingMutex.Lock();
|
||||
threadOperationIncomingQueue.Push(threadOperation, _FILE_AND_LINE_ );
|
||||
threadOperationIncomingMutex.Unlock();
|
||||
|
||||
while (1)
|
||||
{
|
||||
RakSleep(0);
|
||||
threadOperationOutgoingMutex.Lock();
|
||||
if (threadOperationOutgoingQueue.Size()!=0)
|
||||
{
|
||||
threadOperation=threadOperationOutgoingQueue.Pop();
|
||||
threadOperationOutgoingMutex.Unlock();
|
||||
if (forwardingPort)
|
||||
*forwardingPort=threadOperation.forwardingPort;
|
||||
if (forwardingSocket)
|
||||
*forwardingSocket=threadOperation.forwardingSocket;
|
||||
return threadOperation.result;
|
||||
}
|
||||
threadOperationOutgoingMutex.Unlock();
|
||||
|
||||
}
|
||||
#else
|
||||
return StartForwardingThreaded(source, destination, timeoutOnNoDataMS, forceHostAddress, socketFamily, srcToDestPort, destToSourcePort, srcToDestSocket, destToSourceSocket);
|
||||
#endif
|
||||
|
||||
}
|
||||
UDPForwarderResult UDPForwarder::StartForwardingThreaded(SystemAddress source, SystemAddress destination, RakNet::TimeMS timeoutOnNoDataMS, const char *forceHostAddress, unsigned short socketFamily,
|
||||
unsigned short *forwardingPort, SOCKET *forwardingSocket)
|
||||
{
|
||||
SrcAndDest srcAndDest(source, destination);
|
||||
|
||||
UDPForwarderResult result = AddForwardingEntry(srcAndDest, timeoutOnNoDataMS, forwardingPort, forceHostAddress, socketFamily);
|
||||
|
||||
if (result!=UDPFORWARDER_SUCCESS)
|
||||
return result;
|
||||
|
||||
if (*forwardingSocket)
|
||||
{
|
||||
unsigned int idx;
|
||||
bool objectExists;
|
||||
idx = forwardList.GetIndexFromKey(srcAndDest, &objectExists);
|
||||
RakAssert(objectExists);
|
||||
*forwardingSocket=forwardList[idx]->socket;
|
||||
}
|
||||
|
||||
return UDPFORWARDER_SUCCESS;
|
||||
}
|
||||
void UDPForwarder::StopForwarding(SystemAddress source, SystemAddress destination)
|
||||
{
|
||||
#ifdef UDP_FORWARDER_EXECUTE_THREADED
|
||||
ThreadOperation threadOperation;
|
||||
threadOperation.source=source;
|
||||
threadOperation.destination=destination;
|
||||
threadOperation.operation=ThreadOperation::TO_STOP_FORWARDING;
|
||||
threadOperationIncomingMutex.Lock();
|
||||
threadOperationIncomingQueue.Push(threadOperation, _FILE_AND_LINE_ );
|
||||
threadOperationIncomingMutex.Unlock();
|
||||
#else
|
||||
StopForwardingThreaded(source, destination);
|
||||
#endif
|
||||
}
|
||||
void UDPForwarder::StopForwardingThreaded(SystemAddress source, SystemAddress destination)
|
||||
{
|
||||
SrcAndDest srcAndDest(destination,source);
|
||||
|
||||
bool objectExists;
|
||||
unsigned int idx = forwardList.GetIndexFromKey(srcAndDest, &objectExists);
|
||||
if (objectExists)
|
||||
{
|
||||
RakNet::OP_DELETE(forwardList[idx],_FILE_AND_LINE_);
|
||||
forwardList.RemoveAtIndex(idx);
|
||||
}
|
||||
}
|
||||
namespace RakNet {
|
||||
#ifdef UDP_FORWARDER_EXECUTE_THREADED
|
||||
RAK_THREAD_DECLARATION(UpdateUDPForwarder)
|
||||
{
|
||||
|
||||
|
||||
|
||||
UDPForwarder * udpForwarder = ( UDPForwarder * ) arguments;
|
||||
|
||||
|
||||
udpForwarder->threadRunning=true;
|
||||
UDPForwarder::ThreadOperation threadOperation;
|
||||
while (udpForwarder->isRunning)
|
||||
{
|
||||
udpForwarder->threadOperationIncomingMutex.Lock();
|
||||
while (udpForwarder->threadOperationIncomingQueue.Size())
|
||||
{
|
||||
threadOperation=udpForwarder->threadOperationIncomingQueue.Pop();
|
||||
udpForwarder->threadOperationIncomingMutex.Unlock();
|
||||
if (threadOperation.operation==UDPForwarder::ThreadOperation::TO_START_FORWARDING)
|
||||
{
|
||||
threadOperation.result=udpForwarder->StartForwardingThreaded(threadOperation.source, threadOperation.destination, threadOperation.timeoutOnNoDataMS,
|
||||
threadOperation.forceHostAddress, threadOperation.socketFamily, &threadOperation.forwardingPort, &threadOperation.forwardingSocket);
|
||||
udpForwarder->threadOperationOutgoingMutex.Lock();
|
||||
udpForwarder->threadOperationOutgoingQueue.Push(threadOperation, _FILE_AND_LINE_ );
|
||||
udpForwarder->threadOperationOutgoingMutex.Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
udpForwarder->StopForwardingThreaded(threadOperation.source, threadOperation.destination);
|
||||
}
|
||||
|
||||
|
||||
udpForwarder->threadOperationIncomingMutex.Lock();
|
||||
}
|
||||
udpForwarder->threadOperationIncomingMutex.Unlock();
|
||||
|
||||
#if RAKNET_SUPPORT_IPV6!=1
|
||||
udpForwarder->UpdateThreaded_Old();
|
||||
#else
|
||||
udpForwarder->UpdateThreaded();
|
||||
#endif
|
||||
|
||||
|
||||
// 12/1/2010 Do not change from 0
|
||||
// See http://www.jenkinssoftware.com/forum/index.php?topic=4033.0;topicseen
|
||||
// Avoid 100% reported CPU usage
|
||||
RakSleep(0);
|
||||
}
|
||||
udpForwarder->threadRunning=false;
|
||||
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
} // namespace RakNet
|
||||
#endif
|
||||
|
||||
#endif // #if _RAKNET_SUPPORT_FileOperations==1
|
||||
Reference in New Issue
Block a user