// \file
//
// This file is part of RakNet Copyright 2003 Jenkins Software LLC
//
// Usage of RakNet is subject to the appropriate license agreement.
#include "RakNetDefines.h"
#include "RakPeer.h"
#include "RakNetTypes.h"
#include "WSAStartupSingleton.h"
#ifdef _WIN32
#elif defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
#else
#define closesocket close
#include <unistd.h>
#endif
#if defined(new)
#pragma push_macro("new")
#undef new
#define RMO_NEW_UNDEF_ALLOCATING_QUEUE
#endif
#include <time.h>
#include <ctype.h> // toupper
#include <string.h>
#include "GetTime.h"
#include "MessageIdentifiers.h"
#include "DS_HuffmanEncodingTree.h"
#include "Rand.h"
#include "PluginInterface2.h"
#include "StringCompressor.h"
#include "StringTable.h"
#include "NetworkIDObject.h"
#include "RakNetTypes.h"
#include "SHA1.h"
#include "RakSleep.h"
#include "RouterInterface.h"
#include "RakAssert.h"
#include "RakNetVersion.h"
#include "NetworkIDManager.h"
#include "DataBlockEncryptor.h"
#include "gettimeofday.h"
#include "SignaledEvent.h"
#include "SuperFastHash.h"
RAK_THREAD_DECLARATION(UpdateNetworkLoop);
RAK_THREAD_DECLARATION(RecvFromLoop);
RAK_THREAD_DECLARATION(UDTConnect);
#define REMOTE_SYSTEM_LOOKUP_HASH_MULTIPLE 8
#if !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ )
#include <stdlib.h> // malloc
#endif
#if defined(_XBOX) || defined(X360)
#elif defined(_WIN32)
//
#else
/*
#include <alloca.h> // Console 2
#include <stdlib.h>
extern bool _extern_Console2LoadModules(void);
extern int _extern_Console2GetConnectionStatus(void);
extern int _extern_Console2GetLobbyStatus(void);
//extern bool Console2StartupFluff(unsigned int *);
extern void Console2ShutdownFluff(void);
//extern unsigned int Console2ActivateConnection(unsigned int, void *);
//extern bool Console2BlockOnEstablished(void);
extern void Console2GetIPAndPort(unsigned int, char *, unsigned short *, unsigned int );
//extern void Console2DeactivateConnection(unsigned int, unsigned int);
*/
#endif
static const int NUM_MTU_SIZES=3;
#if defined(_XBOX) || defined(X360)
#elif __PC__
static const int mtuSizes[NUM_MTU_SIZES]={1200, 1200, 576};
#else
static const int mtuSizes[NUM_MTU_SIZES]={MAXIMUM_MTU_SIZE, 1200, 576};
#endif
#include "RakAlloca.h"
// Note to self - if I change this it might affect RECIPIENT_OFFLINE_MESSAGE_INTERVAL in Natpunchthrough.cpp
//static const int MAX_OPEN_CONNECTION_REQUESTS=8;
//static const int TIME_BETWEEN_OPEN_CONNECTION_REQUESTS=500;
#ifdef _MSC_VER
#pragma warning( push )
#endif
using namespace RakNet;
static RakNetRandom rnr;
struct RakPeerAndIndex
{
SOCKET s;
unsigned short remotePortRakNetWasStartedOn_PS3;
RakPeer *rakPeer;
};
// On a Little-endian machine the RSA key and message are mangled, but we're
// trying to be friendly to the little endians, so we do byte order
// mangling on Big-Endian machines. Note that this mangling is independent
// of the byte order used on the network (which also defaults to little-end).
#ifdef HOST_ENDIAN_IS_BIG
void __inline BSWAPCPY(unsigned char *dest, unsigned char *source, int bytesize)
{
#ifdef _DEBUG
RakAssert( (bytesize % 4 == 0)&&(bytesize)&& "Something is wrong with your exponent or modulus size.");
#endif
int i;
for (i=0; i<bytesize; i+=4)
{
dest[i] = source[i+3];
dest[i+1] = source[i+2];
dest[i+2] = source[i+1];
dest[i+3] = source[i];
}
}
void __inline BSWAPSELF(unsigned char *source, int bytesize)
{
#ifdef _DEBUG
RakAssert( (bytesize % 4 == 0)&&(bytesize)&& "Something is wrong with your exponent or modulus size.");
#endif
int i;
unsigned char a, b;
for (i=0; i<bytesize; i+=4)
{
a = source[i];
b = source[i+1];
source[i] = source[i+3];
source[i+1] = source[i+2];
source[i+2] = b;
source[i+3] = a;
}
}
#endif
static const unsigned int SYN_COOKIE_OLD_RANDOM_NUMBER_DURATION = 10000;
static const unsigned int MAX_OFFLINE_DATA_LENGTH=400; // I set this because I limit ID_CONNECTION_REQUEST to 512 bytes, and the password is appended to that packet.
// Used to distinguish between offline messages with data, and messages from the reliability layer
// Should be different than any message that could result from messages from the reliability layer
#pragma warning(disable:4309) // 'initializing' : truncation of constant value
// Make sure highest bit is 0, so isValid in DatagramHeaderFormat is false
static const char OFFLINE_MESSAGE_DATA_ID[16]={0x00,0xFF,0xFF,0x00,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFD,0x12,0x34,0x56,0x78};
//#define _DO_PRINTF
// UPDATE_THREAD_POLL_TIME is how often the update thread will poll to see
// if receive wasn't called within UPDATE_THREAD_UPDATE_TIME. If it wasn't called within that time,
// the updating thread will activate and take over network communication until Receive is called again.
//static const unsigned int UPDATE_THREAD_UPDATE_TIME=30;
//static const unsigned int UPDATE_THREAD_POLL_TIME=30;
//#define _TEST_AES
struct PacketFollowedByData
{
Packet p;
unsigned char data[1];
};
Packet *RakPeer::AllocPacket(unsigned dataSize, const char *file, unsigned int line)
{
// Crashes when dataSize is 4 bytes - not sure why
// unsigned char *data = (unsigned char *) rakMalloc_Ex(sizeof(PacketFollowedByData)+dataSize, file, line);
// Packet *p = &((PacketFollowedByData *)data)->p;
// p->data=((PacketFollowedByData *)data)->data;
// p->length=dataSize;
// p->bitSize=BYTES_TO_BITS(dataSize);
// p->deleteData=false;
// p->guid=UNASSIGNED_RAKNET_GUID;
// return p;
Packet *p;
packetAllocationPoolMutex.Lock();
p = packetAllocationPool.Allocate(file,line);
packetAllocationPoolMutex.Unlock();
p = new ((void*)p) Packet;
p->data=(unsigned char*) rakMalloc_Ex(dataSize,file,line);
p->length=dataSize;
p->bitSize=BYTES_TO_BITS(dataSize);
p->deleteData=true;
p->guid=UNASSIGNED_RAKNET_GUID;
return p;
}
Packet *RakPeer::AllocPacket(unsigned dataSize, unsigned char *data, const char *file, unsigned int line)
{
// Packet *p = (Packet *)rakMalloc_Ex(sizeof(Packet), file, line);
Packet *p;
packetAllocationPoolMutex.Lock();
p = packetAllocationPool.Allocate(file,line);
packetAllocationPoolMutex.Unlock();
p = new ((void*)p) Packet;
p->data=data;
p->length=dataSize;
p->bitSize=BYTES_TO_BITS(dataSize);
p->deleteData=true;
p->guid=UNASSIGNED_RAKNET_GUID;
return p;
}
// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Constructor
// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RakPeer::RakPeer()
{
StringCompressor::AddReference();
RakNet::StringTable::AddReference();
WSAStartupSingleton::AddRef();
#if !defined(_XBOX) && !defined(_WIN32_WCE) && !defined(X360)
usingSecurity = false;
#endif
memset( frequencyTable, 0, sizeof( unsigned int ) * 256 );
rawBytesSent = rawBytesReceived = compressedBytesSent = compressedBytesReceived = 0;
outputTree = inputTree = 0;
defaultMTUSize = mtuSizes[NUM_MTU_SIZES-1];
trackFrequencyTable = false;
maximumIncomingConnections = 0;
maximumNumberOfPeers = 0;
//remoteSystemListSize=0;
remoteSystemList = 0;
remoteSystemLookup=0;
bytesSentPerSecond = bytesReceivedPerSecond = 0;
endThreads = true;
isMainLoopThreadActive = false;
isRecvFromLoopThreadActive = false;
// isRecvfromThreadActive=false;
#if defined(GET_TIME_SPIKE_LIMIT) && GET_TIME_SPIKE_LIMIT>0
occasionalPing = true;
#else
occasionalPing = false;
#end