Files
mcpe/thirdparty/raknet/RakNetTypes.cpp
Brent a0f71c7b27 C++03 Support & Partial Xbox 360 Support (#37)
* WIP C++03 + Xbox 360 Support

* math.h & _USE_MATH_DEFINES on Level.hpp
Updated Xenon vcxproj file for new file structure.

* * Fix bad GUI scale setup.

* * Gui: Use ratios instead of hardcoded sub-1 floating point values, to make the mechanism more clear.

* Add Direct Connect Button and Screen (#30)

* Add Direct Connect Button and Screen

* Remove accidental extra build directories for wasm

* Add DirectConnectScreen.cpp to the CMake

* Use Hungarian coding style notation

* * Fix errors caused by #30

* * Improve the Chat Screen

* * Improve the DirectConnectScreen, among other things.

* * Update the game title once again.

* * Add build-wasm.bat.

* * Add info about compiling for wasm

* * Fix send to specific GUID actually broadcasting to everyone

* * Add command manager.

* * Add writeable configuration.

* * Allow dynamic screen size change on windows

* * Allow the same thing on the emscripten version.

* WIP C++03 + Xbox 360 Support

* Fixed a possible merging issue that broke RakNet?

* Additional Xbox 360 compatability fixes

---------

Co-authored-by: Brent Da Mage <BrentDaMage@users.noreply.github.com>
Co-authored-by: iProgramInCpp <iprogramincpp@gmail.com>
Co-authored-by: ts <124226059+uniformization@users.noreply.github.com>
2023-08-07 15:48:52 +03:00

817 lines
18 KiB
C++

/*
* Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
/// \file
///
#include "RakNetTypes.h"
#include "RakAssert.h"
#include <string.h>
#include <stdio.h>
#include "WindowsIncludes.h"
#include "WSAStartupSingleton.h"
#include "SocketDefines.h"
#include "RakNetSocket2.h"
#if defined(_WIN32)
// extern __int64 _strtoui64(const char*, char**, int); // needed for Code::Blocks. Does not compile on Visual Studio 2010
// IP_DONTFRAGMENT is different between winsock 1 and winsock 2. Therefore, Winsock2.h must be linked againt Ws2_32.lib
// winsock.h must be linked against WSock32.lib. If these two are mixed up the flag won't work correctly
#include "WindowsIncludes.h"
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include <string.h> // strncasecmp
#include "Itoa.h"
#include "SocketLayer.h"
#include "SuperFastHash.h"
#include <stdlib.h>
using namespace RakNet;
const char *IPV6_LOOPBACK="::1";
const char *IPV4_LOOPBACK="127.0.0.1";
AddressOrGUID::AddressOrGUID( Packet *packet )
{
rakNetGuid=packet->guid;
systemAddress=packet->systemAddress;
}
unsigned long AddressOrGUID::ToInteger( const AddressOrGUID &aog )
{
if (aog.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
return RakNetGUID::ToUint32(aog.rakNetGuid);
return SystemAddress::ToInteger(aog.systemAddress);
}
const char *AddressOrGUID::ToString(bool writePort) const
{
if (rakNetGuid!=UNASSIGNED_RAKNET_GUID)
return rakNetGuid.ToString();
return systemAddress.ToString(writePort);
}
void AddressOrGUID::ToString(bool writePort, char *dest) const
{
if (rakNetGuid!=UNASSIGNED_RAKNET_GUID)
return rakNetGuid.ToString(dest);
return systemAddress.ToString(writePort,dest);
}
bool RakNet::NonNumericHostString( const char *host )
{
// Return false if IP address. Return true if domain
unsigned int i=0;
while (host[i])
{
// IPV4: natpunch.jenkinssoftware.com
// IPV6: fe80::7c:31f7:fec4:27de%14
if ((host[i]>='g' && host[i]<='z') ||
(host[i]>='A' && host[i]<='Z'))
return true;
++i;
}
return false;
}
SocketDescriptor::SocketDescriptor() {
#ifdef __native_client__
blockingSocket=false;
#else
blockingSocket=true;
#endif
port=0; hostAddress[0]=0; remotePortRakNetWasStartedOn_PS3_PSP2=0; extraSocketOptions=0; socketFamily=AF_INET;}
SocketDescriptor::SocketDescriptor(unsigned short _port, const char *_hostAddress)
{
#ifdef __native_client__
blockingSocket=false;
#else
blockingSocket=true;
#endif
remotePortRakNetWasStartedOn_PS3_PSP2=0;
port=_port;
if (_hostAddress)
strcpy(hostAddress, _hostAddress);
else
hostAddress[0]=0;
extraSocketOptions=0;
socketFamily=AF_INET;
}
// Defaults to not in peer to peer mode for NetworkIDs. This only sends the localSystemAddress portion in the BitStream class
// This is what you want for client/server, where the server assigns all NetworkIDs and it is unnecessary to transmit the full structure.
// For peer to peer, this will transmit the systemAddress of the system that created the object in addition to localSystemAddress. This allows
// Any system to create unique ids locally.
// All systems must use the same value for this variable.
//bool RAK_DLL_EXPORT NetworkID::peerToPeerMode=false;
SystemAddress& SystemAddress::operator = ( const SystemAddress& input )
{
memcpy(&address, &input.address, sizeof(address));
systemIndex = input.systemIndex;
debugPort = input.debugPort;
return *this;
}
bool SystemAddress::EqualsExcludingPort( const SystemAddress& right ) const
{
return (address.addr4.sin_family==AF_INET && address.addr4.sin_addr.s_addr==right.address.addr4.sin_addr.s_addr)
#if RAKNET_SUPPORT_IPV6==1
|| (address.addr4.sin_family==AF_INET6 && memcmp(address.addr6.sin6_addr.s6_addr, right.address.addr6.sin6_addr.s6_addr, sizeof(address.addr6.sin6_addr.s6_addr))==0)
#endif
;
}
unsigned short SystemAddress::GetPort(void) const
{
return ntohs(address.addr4.sin_port);
}
unsigned short SystemAddress::GetPortNetworkOrder(void) const
{
return address.addr4.sin_port;
}
void SystemAddress::SetPortHostOrder(unsigned short s)
{
address.addr4.sin_port=htons(s);
debugPort=s;
}
void SystemAddress::SetPortNetworkOrder(unsigned short s)
{
address.addr4.sin_port=s;
debugPort=ntohs(s);
}
bool SystemAddress::operator==( const SystemAddress& right ) const
{
return address.addr4.sin_port == right.address.addr4.sin_port && EqualsExcludingPort(right);
}
bool SystemAddress::operator!=( const SystemAddress& right ) const
{
return (*this==right)==false;
}
bool SystemAddress::operator>( const SystemAddress& right ) const
{
if (address.addr4.sin_port == right.address.addr4.sin_port)
{
#if RAKNET_SUPPORT_IPV6==1
if (address.addr4.sin_family==AF_INET)
return address.addr4.sin_addr.s_addr>right.address.addr4.sin_addr.s_addr;
return memcmp(address.addr6.sin6_addr.s6_addr, right.address.addr6.sin6_addr.s6_addr, sizeof(address.addr6.sin6_addr.s6_addr))>0;
#else
return address.addr4.sin_addr.s_addr>right.address.addr4.sin_addr.s_addr;
#endif
}
return address.addr4.sin_port>right.address.addr4.sin_port;
}
bool SystemAddress::operator<( const SystemAddress& right ) const
{
if (address.addr4.sin_port == right.address.addr4.sin_port)
{
#if RAKNET_SUPPORT_IPV6==1
if (address.addr4.sin_family==AF_INET)
return address.addr4.sin_addr.s_addr<right.address.addr4.sin_addr.s_addr;
return memcmp(address.addr6.sin6_addr.s6_addr, right.address.addr6.sin6_addr.s6_addr, sizeof(address.addr6.sin6_addr.s6_addr))>0;
#else
return address.addr4.sin_addr.s_addr<right.address.addr4.sin_addr.s_addr;
#endif
}
return address.addr4.sin_port<right.address.addr4.sin_port;
}
int SystemAddress::size(void)
{
#if RAKNET_SUPPORT_IPV6==1
return sizeof(sockaddr_in6) + sizeof(char);
#else
return sizeof(uint32_t) + sizeof(unsigned short) + sizeof(char);
#endif
}
unsigned long SystemAddress::ToInteger( const SystemAddress &sa )
{
unsigned int lastHash = SuperFastHashIncremental ((const char*) & sa.address.addr4.sin_port, sizeof(sa.address.addr4.sin_port), sizeof(sa.address.addr4.sin_port) );
#if RAKNET_SUPPORT_IPV6==1
if (sa.address.addr4.sin_family==AF_INET)
return SuperFastHashIncremental ((const char*) & sa.address.addr4.sin_addr.s_addr, sizeof(sa.address.addr4.sin_addr.s_addr), lastHash );
else
return SuperFastHashIncremental ((const char*) & sa.address.addr6.sin6_addr.s6_addr, sizeof(sa.address.addr6.sin6_addr.s6_addr), lastHash );
#else
return SuperFastHashIncremental ((const char*) & sa.address.addr4.sin_addr.s_addr, sizeof(sa.address.addr4.sin_addr.s_addr), lastHash );
#endif
}
unsigned char SystemAddress::GetIPVersion(void) const
{
if (address.addr4.sin_family==AF_INET)
return 4;
return 6;
}
unsigned int SystemAddress::GetIPPROTO(void) const
{
#if RAKNET_SUPPORT_IPV6==1
if (address.addr4.sin_family==AF_INET)
return IPPROTO_IP;
return IPPROTO_IPV6;
#else
return IPPROTO_IP;
#endif
}
void SystemAddress::SetToLoopback(void)
{
SetToLoopback(GetIPVersion());
}
void SystemAddress::SetToLoopback(unsigned char ipVersion)
{
if (ipVersion==4)
{
FromString(IPV4_LOOPBACK, 0, ipVersion);
}
else
{
FromString(IPV6_LOOPBACK, 0, ipVersion);
}
}
bool SystemAddress::IsLoopback(void) const
{
if (GetIPVersion()==4)
{
// unsigned long l = htonl(address.addr4.sin_addr.s_addr);
if (htonl(address.addr4.sin_addr.s_addr)==2130706433)
return true;
if (address.addr4.sin_addr.s_addr==0)
return true;
}
#if RAKNET_SUPPORT_IPV6==1
else
{
const static char localhost[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
if (memcmp(&address.addr6.sin6_addr, localhost, 16)==0)
return true;
}
#endif
return false;
}
void SystemAddress::ToString_Old(bool writePort, char *dest, char portDelineator) const
{
#ifdef _XBOX
RakAssert("Not yet supported" && 0);
#else
if (*this==UNASSIGNED_SYSTEM_ADDRESS)
{
strcpy(dest, "UNASSIGNED_SYSTEM_ADDRESS");
return;
}
char portStr[2];
portStr[0]=portDelineator;
portStr[1]=0;
in_addr in;
in.s_addr = address.addr4.sin_addr.s_addr;
const char *ntoaStr = inet_ntoa( in );
strcpy(dest, ntoaStr);
if (writePort)
{
strcat(dest, portStr);
Itoa(GetPort(), dest+strlen(dest), 10);
}
#endif
}
const char *SystemAddress::ToString(bool writePort, char portDelineator) const
{
static unsigned char strIndex=0;
#if RAKNET_SUPPORT_IPV6==1
static char str[8][INET6_ADDRSTRLEN+5+1];
#else
static char str[8][22+5+1];
#endif
unsigned char lastStrIndex=strIndex;
strIndex++;
ToString(writePort, str[lastStrIndex&7], portDelineator);
return (char*) str[lastStrIndex&7];
}
#if RAKNET_SUPPORT_IPV6==1
void SystemAddress::ToString_New(bool writePort, char *dest, char portDelineator) const
{
int ret;
(void) ret;
if (*this==UNASSIGNED_SYSTEM_ADDRESS)
{
strcpy(dest, "UNASSIGNED_SYSTEM_ADDRESS");
return;
}
if (address.addr4.sin_family==AF_INET)
{
ret=getnameinfo((struct sockaddr *) &address.addr4, sizeof(struct sockaddr_in), dest, 22, NULL, 0, NI_NUMERICHOST);
}
else
{
ret=getnameinfo((struct sockaddr *) &address.addr6, sizeof(struct sockaddr_in6), dest, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
}
if (ret!=0)
{
dest[0]=0;
}
if (writePort)
{
unsigned char ch[2];
ch[0]=portDelineator;
ch[1]=0;
strcat(dest, (const char*) ch);
Itoa(ntohs(address.addr4.sin_port), dest+strlen(dest), 10);
}
}
#endif // #if RAKNET_SUPPORT_IPV6!=1
void SystemAddress::ToString(bool writePort, char *dest, char portDelineator) const
{
#if RAKNET_SUPPORT_IPV6!=1
ToString_Old(writePort,dest,portDelineator);
#else
ToString_New(writePort,dest,portDelineator);
#endif // #if RAKNET_SUPPORT_IPV6!=1
}
SystemAddress::SystemAddress()
{
address.addr4.sin_family=AF_INET;
// used for operator ==
memset(&address,0,sizeof(address)); address.addr4.sin_family=AF_INET;
systemIndex=(SystemIndex)-1;
debugPort=0;
}
SystemAddress::SystemAddress(const char *str)
{
address.addr4.sin_family=AF_INET;
SetPortHostOrder(0);
FromString(str);
systemIndex=(SystemIndex)-1;
}
SystemAddress::SystemAddress(const char *str, unsigned short port)
{
address.addr4.sin_family=AF_INET;
FromStringExplicitPort(str,port);
systemIndex=(SystemIndex)-1;
}
#ifdef _MSC_VER
#pragma warning( disable : 4996 ) // The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
#endif
void SystemAddress::FixForIPVersion(const SystemAddress &boundAddressToSocket)
{
char str[128];
ToString(false,str);
// TODO - what about 255.255.255.255?
if (strcmp(str, IPV6_LOOPBACK)==0)
{
if (boundAddressToSocket.GetIPVersion()==4)
{
FromString(IPV4_LOOPBACK,0,4);
}
}
else if (strcmp(str, IPV4_LOOPBACK)==0)
{
#if RAKNET_SUPPORT_IPV6==1
if (boundAddressToSocket.GetIPVersion()==6)
{
FromString(IPV6_LOOPBACK,0,6);
}
#endif
// if (boundAddressToSocket.GetIPVersion()==4)
// {
// // Some kind of bug with sendto: returns "The requested address is not valid in its context." if loopback doesn't have the same IP address
// address.addr4.sin_addr.s_addr=boundAddressToSocket.address.addr4.sin_addr.s_addr;
// }
}
}
bool SystemAddress::IsLANAddress(void)
{
// return address.addr4.sin_addr.S_un.S_un_b.s_b1==10 || address.addr4.sin_addr.S_un.s_b1==192;
#if defined(__WIN32__)
return address.addr4.sin_addr.S_un.S_un_b.s_b1==10 || address.addr4.sin_addr.S_un.S_un_b.s_b1==192;
#else
return (address.addr4.sin_addr.s_addr >> 24) == 10 || (address.addr4.sin_addr.s_addr >> 24) == 192;
#endif
}
bool SystemAddress::SetBinaryAddress(const char *str, char portDelineator)
{
if ( NonNumericHostString( str ) )
{
#if defined(_WIN32)
if (_strnicmp(str,"localhost", 9)==0)
#else
if (strncasecmp(str,"localhost", 9)==0)
#endif
{
address.addr4.sin_addr.s_addr=inet_addr__("127.0.0.1");
if (str[9])
{
SetPortHostOrder((unsigned short) atoi(str+9));
}
return true;
}
//const char *ip = ( char* ) SocketLayer::DomainNameToIP( str );
char ip[65];
ip[0]=0;
RakNetSocket2::DomainNameToIP(str, ip);
if (ip[0])
{
address.addr4.sin_addr.s_addr=inet_addr__(ip);
}
else
{
*this = UNASSIGNED_SYSTEM_ADDRESS;
return false;
}
}
else
{
//#ifdef _XBOX
// binaryAddress=UNASSIGNED_SYSTEM_ADDRESS.binaryAddress;
//#else
// Split the string into the first part, and the : part
int index, portIndex;
char IPPart[22];
char portPart[10];
// Only write the valid parts, don't change existing if invalid
// binaryAddress=UNASSIGNED_SYSTEM_ADDRESS.binaryAddress;
// port=UNASSIGNED_SYSTEM_ADDRESS.port;
for (index=0; str[index] && str[index]!=portDelineator && index<22; index++)
{
if (str[index]!='.' && (str[index]<'0' || str[index]>'9'))
break;
IPPart[index]=str[index];
}
IPPart[index]=0;
portPart[0]=0;
if (str[index] && str[index+1])
{
index++;
for (portIndex=0; portIndex<10 && str[index] && index < 22+10; index++, portIndex++)
{
if (str[index]<'0' || str[index]>'9')
break;
portPart[portIndex]=str[index];
}
portPart[portIndex]=0;
}
if (IPPart[0])
{
address.addr4.sin_addr.s_addr=inet_addr__(IPPart);
}
if (portPart[0])
{
address.addr4.sin_port=htons((unsigned short) atoi(portPart));
debugPort=ntohs(address.addr4.sin_port);
}
//#endif
}
return true;
}
#ifdef _MSC_VER
#pragma warning( disable : 4702 ) // warning C4702: unreachable code
#endif
bool SystemAddress::FromString(const char *str, char portDelineator, int ipVersion)
{
#if RAKNET_SUPPORT_IPV6!=1
(void) ipVersion;
return SetBinaryAddress(str,portDelineator);
#else
if (str==0)
{
memset(&address,0,sizeof(address));
address.addr4.sin_family=AF_INET;
return true;
}
#if RAKNET_SUPPORT_IPV6==1
char ipPart[INET6_ADDRSTRLEN];
#else
char ipPart[INET_ADDRSTRLEN];
#endif
char portPart[32];
int i=0,j;
// TODO - what about 255.255.255.255?
if (ipVersion==4 && strcmp(str, IPV6_LOOPBACK)==0)
{
strcpy(ipPart,IPV4_LOOPBACK);
}
else if (ipVersion==6 && strcmp(str, IPV4_LOOPBACK)==0)
{
address.addr4.sin_family=AF_INET6;
strcpy(ipPart,IPV6_LOOPBACK);
}
else if (NonNumericHostString(str)==false)
{
for (; i < sizeof(ipPart) && str[i]!=0 && str[i]!=portDelineator; i++)
{
if ((str[i]<'0' || str[i]>'9') && (str[i]<'a' || str[i]>'f') && (str[i]<'A' || str[i]>'F') && str[i]!='.' && str[i]!=':' && str[i]!='%' && str[i]!='-' && str[i]!='/')
break;
ipPart[i]=str[i];
}
ipPart[i]=0;
}
else
{
strncpy(ipPart,str,sizeof(ipPart));
ipPart[sizeof(ipPart)-1]=0;
}
j=0;
if (str[i]==portDelineator && portDelineator!=0)
{
i++;
for (; j < sizeof(portPart) && str[i]!=0; i++, j++)
{
portPart[j]=str[i];
}
}
portPart[j]=0;
// needed for getaddrinfo
WSAStartupSingleton::AddRef();
// This could be a domain, or a printable address such as "192.0.2.1" or "2001:db8:63b3:1::3490"
// I want to convert it to its binary representation
addrinfo hints, *servinfo=0;
memset(&hints, 0, sizeof hints);
hints.ai_socktype = SOCK_DGRAM;
if (ipVersion==6)
hints.ai_family = AF_INET6;
else if (ipVersion==4)
hints.ai_family = AF_INET;
else
hints.ai_family = AF_UNSPEC;
getaddrinfo(ipPart, "", &hints, &servinfo);
if (servinfo==0)
{
if (ipVersion==6)
{
ipVersion=4;
hints.ai_family = AF_UNSPEC;
getaddrinfo(ipPart, "", &hints, &servinfo);
if (servinfo==0)
return false;
}
else
return false;
}
RakAssert(servinfo);
unsigned short oldPort = address.addr4.sin_port;
#if RAKNET_SUPPORT_IPV6==1
if (servinfo->ai_family == AF_INET)
{
// if (ipVersion==6)
// {
// address.addr4.sin_family=AF_INET6;
// memset(&address.addr6,0,sizeof(address.addr6));
// memcpy(address.addr6.sin6_addr.s6_addr+12,&((struct sockaddr_in *)servinfo->ai_addr)->sin_addr.s_addr,sizeof(unsigned long));
// }
// else
// {
address.addr4.sin_family=AF_INET;
memcpy(&address.addr4, (struct sockaddr_in *)servinfo->ai_addr,sizeof(struct sockaddr_in));
// }
}
else
{
address.addr4.sin_family=AF_INET6;
memcpy(&address.addr6, (struct sockaddr_in6 *)servinfo->ai_addr,sizeof(struct sockaddr_in6));
}
#else
address.addr4.sin_family=AF_INET4;
memcpy(&address.addr4, (struct sockaddr_in *)servinfo->ai_addr,sizeof(struct sockaddr_in));
#endif
freeaddrinfo(servinfo); // free the linked list
// needed for getaddrinfo
WSAStartupSingleton::Deref();
// PORT
if (portPart[0])
{
address.addr4.sin_port=htons((unsigned short) atoi(portPart));
debugPort=ntohs(address.addr4.sin_port);
}
else
{
address.addr4.sin_port=oldPort;
}
#endif // #if RAKNET_SUPPORT_IPV6!=1
return true;
}
bool SystemAddress::FromStringExplicitPort(const char *str, unsigned short port, int ipVersion)
{
bool b = FromString(str,(char) 0,ipVersion);
if (b==false)
{
*this=UNASSIGNED_SYSTEM_ADDRESS;
return false;
}
address.addr4.sin_port=htons(port);
debugPort=ntohs(address.addr4.sin_port);
return true;
}
void SystemAddress::CopyPort( const SystemAddress& right )
{
address.addr4.sin_port=right.address.addr4.sin_port;
debugPort=right.debugPort;
}
RakNetGUID::RakNetGUID()
{
systemIndex=(SystemIndex)-1;
*this=UNASSIGNED_RAKNET_GUID;
}
bool RakNetGUID::operator==( const RakNetGUID& right ) const
{
return g==right.g;
}
bool RakNetGUID::operator!=( const RakNetGUID& right ) const
{
return g!=right.g;
}
bool RakNetGUID::operator > ( const RakNetGUID& right ) const
{
return g > right.g;
}
bool RakNetGUID::operator < ( const RakNetGUID& right ) const
{
return g < right.g;
}
const char *RakNetGUID::ToString(void) const
{
static unsigned char strIndex=0;
static char str[8][64];
unsigned char lastStrIndex=strIndex;
strIndex++;
ToString(str[lastStrIndex&7]);
return (char*) str[lastStrIndex&7];
}
void RakNetGUID::ToString(char *dest) const
{
if (*this==UNASSIGNED_RAKNET_GUID)
strcpy(dest, "UNASSIGNED_RAKNET_GUID");
else
//sprintf(dest, "%u.%u.%u.%u.%u.%u", g[0], g[1], g[2], g[3], g[4], g[5]);
sprintf(dest, "%" PRINTF_64_BIT_MODIFIER "u", (long long unsigned int) g);
// sprintf(dest, "%u.%u.%u.%u.%u.%u", g[0], g[1], g[2], g[3], g[4], g[5]);
}
bool RakNetGUID::FromString(const char *source)
{
if (source==0)
return false;
#if defined(WIN32)
g=_strtoui64(source, NULL, 10);
#else
// Changed from g=strtoull(source,0,10); for android
g=strtoull(source, (char **)NULL, 10);
#endif
return true;
}
unsigned long RakNetGUID::ToUint32( const RakNetGUID &g )
{
return ((unsigned long) (g.g >> 32)) ^ ((unsigned long) (g.g & 0xFFFFFFFF));
}