Init
This commit is contained in:
708
Samples/NATCompleteServer/main.cpp
Normal file
708
Samples/NATCompleteServer/main.cpp
Normal file
@ -0,0 +1,708 @@
|
||||
/*
|
||||
* Original work: Copyright (c) 2014, Oculus VR, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
|
||||
*
|
||||
*
|
||||
* Modified work: Copyright (c) 2016-2018, SLikeSoft UG (haftungsbeschränkt)
|
||||
*
|
||||
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
|
||||
* license found in the license.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "slikenet/peerinterface.h"
|
||||
#include "slikenet/sleep.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits> // used for std::numeric_limits
|
||||
#include "slikenet/Kbhit.h"
|
||||
#include "slikenet/MessageIdentifiers.h"
|
||||
#include "slikenet/BitStream.h"
|
||||
#include "slikenet/sleep.h"
|
||||
#include "slikenet/UDPProxyServer.h"
|
||||
#include "slikenet/UDPProxyCoordinator.h"
|
||||
#include "slikenet/NatPunchthroughServer.h"
|
||||
#include "slikenet/NatTypeDetectionServer.h"
|
||||
#include "slikenet/SocketLayer.h"
|
||||
#include "slikenet/Getche.h"
|
||||
#include "slikenet/Gets.h"
|
||||
#include "CloudServerHelper.h"
|
||||
#include "slikenet/CloudClient.h"
|
||||
#include "slikenet/statistics.h"
|
||||
#include "slikenet/RelayPlugin.h"
|
||||
#include "slikenet/linux_adapter.h"
|
||||
#include "slikenet/osx_adapter.h"
|
||||
|
||||
//#define VERBOSE_LOGGING
|
||||
|
||||
using namespace SLNet;
|
||||
|
||||
enum FeatureSupport
|
||||
{
|
||||
SUPPORTED,
|
||||
UNSUPPORTED,
|
||||
QUERY
|
||||
};
|
||||
|
||||
enum FeatureList
|
||||
{
|
||||
NAT_TYPE_DETECTION_SERVER,
|
||||
NAT_PUNCHTHROUGH_SERVER,
|
||||
RELAY_PLUGIN,
|
||||
UDP_PROXY_COORDINATOR,
|
||||
UDP_PROXY_SERVER,
|
||||
CLOUD_SERVER,
|
||||
FEATURE_LIST_COUNT,
|
||||
};
|
||||
|
||||
static unsigned short DEFAULT_RAKPEER_PORT=61111;
|
||||
|
||||
#define NatTypeDetectionServerFramework_Supported QUERY
|
||||
#define NatPunchthroughServerFramework_Supported QUERY
|
||||
#define RelayPlugin_Supported QUERY
|
||||
#define UDPProxyCoordinatorFramework_Supported UNSUPPORTED
|
||||
#define UDPProxyServerFramework_Supported UNSUPPORTED
|
||||
#define CloudServerFramework_Supported QUERY
|
||||
|
||||
struct SampleFramework
|
||||
{
|
||||
virtual const char * QueryName(void)=0;
|
||||
virtual const char * QueryRequirements(void)=0;
|
||||
virtual const char * QueryFunction(void)=0;
|
||||
virtual void Init(SLNet::RakPeerInterface *rakPeer)=0;
|
||||
virtual void ProcessPacket(SLNet::RakPeerInterface *rakPeer, Packet *packet)=0;
|
||||
virtual void Shutdown(SLNet::RakPeerInterface *rakPeer)=0;
|
||||
|
||||
FeatureSupport isSupported;
|
||||
};
|
||||
|
||||
struct NatTypeDetectionServerFramework : public SampleFramework
|
||||
{
|
||||
NatTypeDetectionServerFramework() {isSupported=NatTypeDetectionServerFramework_Supported; ntds=0;}
|
||||
virtual const char * QueryName(void) {return "NatTypeDetectionServer";}
|
||||
virtual const char * QueryRequirements(void) {return "Requires 4 IP addresses";}
|
||||
virtual const char * QueryFunction(void) {return "Determines router type to filter by connectable systems.\nOne instance needed, multiple instances may exist to spread workload.";}
|
||||
virtual void Init(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (isSupported==SUPPORTED)
|
||||
{
|
||||
ntds = new NatTypeDetectionServer;
|
||||
rakPeer->AttachPlugin(ntds);
|
||||
|
||||
if (rakPeer->GetNumberOfAddresses() < 4)
|
||||
{
|
||||
printf("Failed. Not enough IP addresses to bind to.\n");
|
||||
rakPeer->DetachPlugin(ntds);
|
||||
delete ntds;
|
||||
ntds=0;
|
||||
isSupported=UNSUPPORTED;
|
||||
return;
|
||||
}
|
||||
ntds->Startup(rakPeer->GetLocalIP(1), rakPeer->GetLocalIP(2), rakPeer->GetLocalIP(3));
|
||||
}
|
||||
}
|
||||
virtual void ProcessPacket(SLNet::RakPeerInterface *rakPeer, Packet *packet)
|
||||
{
|
||||
// unused parameters
|
||||
(void)rakPeer;
|
||||
(void)packet;
|
||||
}
|
||||
virtual void Shutdown(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (ntds)
|
||||
{
|
||||
rakPeer->DetachPlugin(ntds);
|
||||
delete ntds;
|
||||
}
|
||||
ntds=0;
|
||||
}
|
||||
|
||||
NatTypeDetectionServer *ntds;
|
||||
};
|
||||
struct NatPunchthroughServerFramework : public SampleFramework, public NatPunchthroughServerDebugInterface_Printf
|
||||
{
|
||||
NatPunchthroughServerFramework() {isSupported=NatPunchthroughServerFramework_Supported; nps=0;}
|
||||
virtual const char * QueryName(void) {return "NatPunchthroughServerFramework";}
|
||||
virtual const char * QueryRequirements(void) {return "None";}
|
||||
virtual const char * QueryFunction(void) {return "Coordinates NATPunchthroughClient.";}
|
||||
virtual void Init(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (isSupported==SUPPORTED)
|
||||
{
|
||||
nps = new NatPunchthroughServer;
|
||||
rakPeer->AttachPlugin(nps);
|
||||
#ifdef VERBOSE_LOGGING
|
||||
nps->SetDebugInterface(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
virtual void ProcessPacket(SLNet::RakPeerInterface *rakPeer, Packet *packet)
|
||||
{
|
||||
// unused parameters
|
||||
(void)rakPeer;
|
||||
(void)packet;
|
||||
}
|
||||
virtual void Shutdown(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (nps)
|
||||
{
|
||||
rakPeer->DetachPlugin(nps);
|
||||
delete nps;
|
||||
}
|
||||
nps=0;
|
||||
}
|
||||
|
||||
NatPunchthroughServer *nps;
|
||||
};
|
||||
struct RelayPluginFramework : public SampleFramework
|
||||
{
|
||||
RelayPluginFramework() {relayPlugin=nullptr;isSupported=RelayPlugin_Supported;}
|
||||
virtual const char * QueryName(void) {return "RelayPlugin";}
|
||||
virtual const char * QueryRequirements(void) {return "None.";}
|
||||
virtual const char * QueryFunction(void) {return "Relays messages between named connections.";}
|
||||
virtual void Init(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (isSupported==SUPPORTED)
|
||||
{
|
||||
relayPlugin = new RelayPlugin;
|
||||
rakPeer->AttachPlugin(relayPlugin);
|
||||
relayPlugin->SetAcceptAddParticipantRequests(true);
|
||||
}
|
||||
}
|
||||
virtual void ProcessPacket(SLNet::RakPeerInterface *rakPeer, Packet *packet)
|
||||
{
|
||||
// unused parameters
|
||||
(void)rakPeer;
|
||||
(void)packet;
|
||||
}
|
||||
virtual void Shutdown(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (relayPlugin)
|
||||
{
|
||||
rakPeer->DetachPlugin(relayPlugin);
|
||||
delete relayPlugin;
|
||||
relayPlugin=0;
|
||||
}
|
||||
}
|
||||
|
||||
RelayPlugin *relayPlugin;
|
||||
};
|
||||
struct UDPProxyCoordinatorFramework : public SampleFramework
|
||||
{
|
||||
UDPProxyCoordinatorFramework() {udppc=0; isSupported=UDPProxyCoordinatorFramework_Supported;}
|
||||
virtual const char * QueryName(void) {return "UDPProxyCoordinator";}
|
||||
virtual const char * QueryRequirements(void) {return "Bandwidth to handle a few hundred bytes per game session.";}
|
||||
virtual const char * QueryFunction(void) {return "Coordinates UDPProxyClient to find available UDPProxyServer.\nExactly one instance required.";}
|
||||
virtual void Init(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (isSupported==SUPPORTED)
|
||||
{
|
||||
udppc = new UDPProxyCoordinator;
|
||||
rakPeer->AttachPlugin(udppc);
|
||||
|
||||
char password[512];
|
||||
printf("Create password for UDPProxyCoordinator: ");
|
||||
Gets(password,sizeof(password));
|
||||
if (password[0]==0)
|
||||
{
|
||||
password[0]='a';
|
||||
password[1]=0;
|
||||
}
|
||||
udppc->SetRemoteLoginPassword(password);
|
||||
}
|
||||
}
|
||||
virtual void ProcessPacket(SLNet::RakPeerInterface *rakPeer, Packet *packet)
|
||||
{
|
||||
// unused parameters
|
||||
(void)rakPeer;
|
||||
(void)packet;
|
||||
}
|
||||
virtual void Shutdown(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (udppc)
|
||||
{
|
||||
rakPeer->DetachPlugin(udppc);
|
||||
delete udppc;
|
||||
udppc=0;
|
||||
}
|
||||
}
|
||||
|
||||
UDPProxyCoordinator *udppc;
|
||||
};
|
||||
SystemAddress SelectAmongConnectedSystems(SLNet::RakPeerInterface *rakPeer, const char *hostName)
|
||||
{
|
||||
DataStructures::List<SystemAddress> addresses;
|
||||
DataStructures::List<RakNetGUID> guids;
|
||||
rakPeer->GetSystemList(addresses, guids);
|
||||
if (addresses.Size()==0)
|
||||
{
|
||||
return SLNet::UNASSIGNED_SYSTEM_ADDRESS;
|
||||
}
|
||||
if (addresses.Size()>1)
|
||||
{
|
||||
printf("Select IP address for %s.\n", hostName);
|
||||
char buff[64];
|
||||
for (unsigned int i=0; i < addresses.Size(); i++)
|
||||
{
|
||||
addresses[i].ToString(true, buff, static_cast<size_t>(64));
|
||||
printf("%i. %s\n", i+1, buff);
|
||||
}
|
||||
Gets(buff,sizeof(buff));
|
||||
if (buff[0]==0)
|
||||
{
|
||||
return SLNet::UNASSIGNED_SYSTEM_ADDRESS;
|
||||
}
|
||||
unsigned int idx = atoi(buff);
|
||||
if (idx<=0 || idx > addresses.Size())
|
||||
{
|
||||
return SLNet::UNASSIGNED_SYSTEM_ADDRESS;
|
||||
}
|
||||
return addresses[idx-1];
|
||||
}
|
||||
else
|
||||
return addresses[0];
|
||||
};
|
||||
SystemAddress ConnectBlocking(SLNet::RakPeerInterface *rakPeer, const char *hostName)
|
||||
{
|
||||
SystemAddress returnvalue = SLNet::UNASSIGNED_SYSTEM_ADDRESS;
|
||||
char ipAddr[64];
|
||||
printf("Enter IP of system %s is running on: ", hostName);
|
||||
Gets(ipAddr,sizeof(ipAddr));
|
||||
if (ipAddr[0]==0)
|
||||
{
|
||||
printf("Failed. Not connected to %s.\n", hostName);
|
||||
return SLNet::UNASSIGNED_SYSTEM_ADDRESS;
|
||||
}
|
||||
char port[64];
|
||||
printf("Enter port of system %s is running on: ", hostName);
|
||||
Gets(port, sizeof(port));
|
||||
if (port[0]==0)
|
||||
{
|
||||
printf("Failed. Not connected to %s.\n", hostName);
|
||||
return SLNet::UNASSIGNED_SYSTEM_ADDRESS;
|
||||
}
|
||||
const int intPort = atoi(port);
|
||||
if ((intPort < 0) || (intPort > std::numeric_limits<unsigned short>::max())) {
|
||||
printf("Failed. Specified port %d is outside valid bounds [0, %u]", intPort, std::numeric_limits<unsigned short>::max());
|
||||
return SLNet::UNASSIGNED_SYSTEM_ADDRESS;
|
||||
}
|
||||
if (rakPeer->Connect(ipAddr, static_cast<unsigned short>(intPort), 0, 0)!= SLNet::CONNECTION_ATTEMPT_STARTED)
|
||||
{
|
||||
printf("Failed connect call for %s.\n", hostName);
|
||||
return SLNet::UNASSIGNED_SYSTEM_ADDRESS;
|
||||
}
|
||||
printf("Connecting...\n");
|
||||
SLNet::Packet *packet;
|
||||
// #med - review --- at least we'd add a sleep interval here - also review whether the behavior is correct to only check the very first received packet (old RakNet code was bogus in this regards)
|
||||
do {
|
||||
packet = rakPeer->Receive();
|
||||
} while (packet == nullptr);
|
||||
|
||||
if (packet->data[0] == ID_CONNECTION_REQUEST_ACCEPTED)
|
||||
returnvalue = packet->systemAddress;
|
||||
|
||||
rakPeer->DeallocatePacket(packet);
|
||||
|
||||
return returnvalue;
|
||||
}
|
||||
struct UDPProxyServerFramework : public SampleFramework, public UDPProxyServerResultHandler
|
||||
{
|
||||
UDPProxyServerFramework() {udpps=0; isSupported=UDPProxyServerFramework_Supported;}
|
||||
virtual const char * QueryName(void) {return "UDPProxyServer";}
|
||||
virtual const char * QueryRequirements(void) {return "Bandwidth to handle forwarded game traffic.";}
|
||||
virtual const char * QueryFunction(void) {return "Allows game clients to forward network traffic transparently.\nOne or more instances required, can be added at runtime.";}
|
||||
virtual void Init(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (isSupported==SUPPORTED)
|
||||
{
|
||||
printf("Logging into UDPProxyCoordinator...\n");
|
||||
SystemAddress coordinatorAddress=SelectAmongConnectedSystems(rakPeer, "UDPProxyCoordinator");
|
||||
if (coordinatorAddress== SLNet::UNASSIGNED_SYSTEM_ADDRESS)
|
||||
{
|
||||
printf("Warning: RakPeer is not currently connected to any system.\nEnter option:\n(1). UDPProxyCoordinator is on localhost\n(2). Connect to a remote system\n(3). Fail.\nOption: ");
|
||||
int ch=_getche();
|
||||
printf("\n");
|
||||
if (ch=='1' || ch==13) // 13 is just pressing return
|
||||
{
|
||||
coordinatorAddress=rakPeer->GetInternalID(UNASSIGNED_SYSTEM_ADDRESS,0);
|
||||
}
|
||||
else if (ch=='2')
|
||||
{
|
||||
coordinatorAddress=ConnectBlocking(rakPeer, "UDPProxyCoordinator");
|
||||
if (coordinatorAddress== SLNet::UNASSIGNED_SYSTEM_ADDRESS)
|
||||
{
|
||||
printf("Failed to connect.\n");
|
||||
isSupported=QUERY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed. Not connected to UDPProxyCoordinator.\n");
|
||||
isSupported=QUERY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char password[512];
|
||||
printf("Enter password used with UDPProxyCoordinator: ");
|
||||
Gets(password,sizeof(password));
|
||||
if (password[0]==0)
|
||||
{
|
||||
password[0]='a';
|
||||
password[1]=0;
|
||||
}
|
||||
|
||||
udpps = new UDPProxyServer;
|
||||
udpps->SetResultHandler(this);
|
||||
rakPeer->AttachPlugin(udpps);
|
||||
if (udpps->LoginToCoordinator(password, coordinatorAddress)==false)
|
||||
{
|
||||
printf("LoginToCoordinator call failed.\n");
|
||||
isSupported=QUERY;
|
||||
rakPeer->DetachPlugin(udpps);
|
||||
delete udpps;
|
||||
udpps=0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void ProcessPacket(SLNet::RakPeerInterface *rakPeer, Packet *packet)
|
||||
{
|
||||
// unused parameters
|
||||
(void)rakPeer;
|
||||
(void)packet;
|
||||
}
|
||||
virtual void Shutdown(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (udpps)
|
||||
{
|
||||
rakPeer->DetachPlugin(udpps);
|
||||
delete udpps;
|
||||
udpps=0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnLoginSuccess(SLNet::RakString usedPassword, SLNet::UDPProxyServer *proxyServerPlugin)
|
||||
{
|
||||
// unused parameters
|
||||
(void)proxyServerPlugin;
|
||||
|
||||
printf("%s logged into UDPProxyCoordinator.\n", QueryName());
|
||||
}
|
||||
virtual void OnAlreadyLoggedIn(SLNet::RakString usedPassword, SLNet::UDPProxyServer *proxyServerPlugin)
|
||||
{
|
||||
// unused parameters
|
||||
(void)proxyServerPlugin;
|
||||
|
||||
printf("%s already logged into UDPProxyCoordinator.\n", QueryName());
|
||||
}
|
||||
virtual void OnNoPasswordSet(SLNet::RakString usedPassword, SLNet::UDPProxyServer *proxyServerPlugin)
|
||||
{
|
||||
// unused parameters
|
||||
(void)proxyServerPlugin;
|
||||
|
||||
printf("%s failed login to UDPProxyCoordinator. No password set.\n", QueryName());
|
||||
isSupported=QUERY;
|
||||
delete udpps;
|
||||
udpps=0;
|
||||
}
|
||||
virtual void OnWrongPassword(SLNet::RakString usedPassword, SLNet::UDPProxyServer *proxyServerPlugin)
|
||||
{
|
||||
// unused parameters
|
||||
(void)proxyServerPlugin;
|
||||
|
||||
printf("%s failed login to UDPProxyCoordinator. %s was the wrong password.\n", QueryName(), usedPassword.C_String());
|
||||
isSupported=QUERY;
|
||||
delete udpps;
|
||||
udpps=0;
|
||||
}
|
||||
|
||||
UDPProxyServer *udpps;
|
||||
};
|
||||
struct CloudServerFramework : public SampleFramework
|
||||
{
|
||||
CloudServerFramework() {cloudServer=nullptr;isSupported=CloudServerFramework_Supported;}
|
||||
virtual const char * QueryName(void) {return "CloudServer";}
|
||||
virtual const char * QueryRequirements(void) {return "None.";}
|
||||
virtual const char * QueryFunction(void) {return "Single instance cloud server that maintains connection counts\nUseful as a directory server to find other client instances.";}
|
||||
virtual void Init(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (isSupported==SUPPORTED)
|
||||
{
|
||||
cloudServer = new CloudServer;
|
||||
rakPeer->AttachPlugin(cloudServer);
|
||||
cloudClient = new CloudClient;
|
||||
rakPeer->AttachPlugin(cloudClient);
|
||||
cloudServerHelperFilter = new CloudServerHelperFilter;
|
||||
cloudServer->AddQueryFilter(cloudServerHelperFilter);
|
||||
cloudServer->SetMaxUploadBytesPerClient(65535);
|
||||
cloudServerHelper.OnConnectionCountChange(rakPeer, cloudClient);
|
||||
}
|
||||
}
|
||||
virtual void ProcessPacket(SLNet::RakPeerInterface *rakPeer, Packet *packet)
|
||||
{
|
||||
if (isSupported!=SUPPORTED)
|
||||
return;
|
||||
|
||||
switch (packet->data[0])
|
||||
{
|
||||
case ID_NEW_INCOMING_CONNECTION:
|
||||
#ifdef VERBOSE_LOGGING
|
||||
printf("Got connection to %s\n", packet->systemAddress.ToString(true));
|
||||
#endif
|
||||
cloudServerHelper.OnConnectionCountChange(rakPeer, cloudClient);
|
||||
break;
|
||||
case ID_CONNECTION_LOST:
|
||||
case ID_DISCONNECTION_NOTIFICATION:
|
||||
#ifdef VERBOSE_LOGGING
|
||||
printf("Lost connection to %s\n", packet->systemAddress.ToString(true));
|
||||
#endif
|
||||
cloudServerHelper.OnConnectionCountChange(rakPeer, cloudClient);
|
||||
break;
|
||||
}
|
||||
}
|
||||
virtual void Shutdown(SLNet::RakPeerInterface *rakPeer)
|
||||
{
|
||||
if (cloudServer)
|
||||
{
|
||||
rakPeer->DetachPlugin(cloudServer);
|
||||
delete cloudServer;
|
||||
cloudServer=0;
|
||||
rakPeer->DetachPlugin(cloudClient);
|
||||
delete cloudClient;
|
||||
cloudClient=0;
|
||||
delete cloudServerHelperFilter;
|
||||
cloudServerHelperFilter=0;
|
||||
}
|
||||
}
|
||||
|
||||
SLNet::CloudServer *cloudServer;
|
||||
SLNet::CloudClient *cloudClient;
|
||||
SLNet::CloudServerHelperFilter *cloudServerHelperFilter;
|
||||
SLNet::CloudServerHelper cloudServerHelper;
|
||||
};
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
SLNet::RakPeerInterface *rakPeer= SLNet::RakPeerInterface::GetInstance();
|
||||
SystemAddress ipList[ MAXIMUM_NUMBER_OF_INTERNAL_IDS ];
|
||||
printf("IPs:\n");
|
||||
unsigned int i;
|
||||
for (i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++) {
|
||||
ipList[i]=rakPeer->GetLocalIP(i);
|
||||
if (ipList[i]!=UNASSIGNED_SYSTEM_ADDRESS)
|
||||
printf("%i. %s\n", i+1, ipList[i].ToString(false));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0 && argc <= 3) {
|
||||
printf("Could not determine any local IP address.\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
// If RakPeer is started on 2 IP addresses, NATPunchthroughServer supports port stride detection, improving success rate
|
||||
int sdLen=1;
|
||||
SLNet::SocketDescriptor sd[2];
|
||||
if (argc>1)
|
||||
{
|
||||
const int intPeerPort = atoi(argv[1]);
|
||||
if ((intPeerPort < 0) || (intPeerPort > std::numeric_limits<unsigned short>::max())) {
|
||||
printf("Specified peer port %d is outside valid bounds [0, %u]", intPeerPort, std::numeric_limits<unsigned short>::max());
|
||||
return 2;
|
||||
}
|
||||
DEFAULT_RAKPEER_PORT = static_cast<unsigned short>(intPeerPort);
|
||||
}
|
||||
|
||||
// set the first IP address
|
||||
sd[0].port = DEFAULT_RAKPEER_PORT;
|
||||
// #med - improve the logic here to simplify the handling...
|
||||
if (argc > 2)
|
||||
strcpy_s(sd[0].hostAddress, argv[2]);
|
||||
|
||||
// #high - improve determining the proper IP addresses
|
||||
// - filter between IPv4/IPv6 and only use either of these
|
||||
// - fallback to other IP addresses, if a given one failed to be bound
|
||||
// allow enforcing single IP address mode by specifying second/third argument to the same IP address
|
||||
if ((i >= 2 && argc <= 3) || (argc > 3)) {
|
||||
const char *ipAddress1 = (argc > 2) ? argv[2] : ipList[0].ToString(false);
|
||||
const char *ipAddress2 = (argc > 3) ? argv[3] : ipList[1].ToString(false);
|
||||
strcpy_s(sd[0].hostAddress, ipAddress1);
|
||||
sd[1].port = DEFAULT_RAKPEER_PORT+1;
|
||||
strcpy_s(sd[1].hostAddress, ipAddress2);
|
||||
printf("Dual IP address mode.\nFirst IP Address: '%s' (port: %u)\nSecond IP Address: '%s' (port: %u)\n", ipAddress1, sd[0].port, ipAddress2, sd[1].port);
|
||||
sdLen = 2;
|
||||
}
|
||||
else {
|
||||
printf("Single IP address mode.\nUsing port %i\n", sd[0].port);
|
||||
}
|
||||
|
||||
const StartupResult success = rakPeer->Startup(8096, sd, sdLen);
|
||||
if (success != SLNet::RAKNET_STARTED)
|
||||
{
|
||||
printf("Failed to start rakPeer! Quitting - error code: %d\n", success);
|
||||
SLNet::RakPeerInterface::DestroyInstance(rakPeer);
|
||||
return 1;
|
||||
}
|
||||
rakPeer->SetTimeoutTime(5000, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
printf("Started on %s\n\n", rakPeer->GetMyBoundAddress().ToString(true));
|
||||
|
||||
rakPeer->SetMaximumIncomingConnections(8096);
|
||||
|
||||
SampleFramework *samples[FEATURE_LIST_COUNT];
|
||||
i=0;
|
||||
samples[i++] = new NatTypeDetectionServerFramework;
|
||||
samples[i++] = new NatPunchthroughServerFramework;
|
||||
samples[i++] = new RelayPluginFramework;
|
||||
samples[i++] = new UDPProxyCoordinatorFramework;
|
||||
samples[i++] = new UDPProxyServerFramework;
|
||||
samples[i++] = new CloudServerFramework;
|
||||
assert(i==FEATURE_LIST_COUNT);
|
||||
|
||||
bool isFirstPrint=true;
|
||||
for (i=0; i < FEATURE_LIST_COUNT; i++)
|
||||
{
|
||||
if (samples[i]->isSupported==QUERY)
|
||||
{
|
||||
if (isFirstPrint)
|
||||
{
|
||||
printf("NAT traversal server.\nSee http://www.dx.net/raknet_dx.php for discounted server hosting\nSelect which features to support.\n");
|
||||
isFirstPrint=false;
|
||||
}
|
||||
printf("\n%s\nRequirements: %s\nDescription: %s\n", samples[i]->QueryName(), samples[i]->QueryRequirements(), samples[i]->QueryFunction());
|
||||
printf("Support %s? (y/n): ", samples[i]->QueryName());
|
||||
int supported=_getche();
|
||||
if (supported=='y' || supported=='Y' || supported==13) // 13 is just pressing return
|
||||
{
|
||||
samples[i]->isSupported=SUPPORTED;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
for (i=0; i < FEATURE_LIST_COUNT; i++)
|
||||
{
|
||||
if (samples[i]->isSupported==SUPPORTED)
|
||||
{
|
||||
printf("Starting %s...\n", samples[i]->QueryName());
|
||||
samples[i]->Init(rakPeer);
|
||||
if (samples[i]->isSupported!=SUPPORTED)
|
||||
{
|
||||
printf("Failed to start %s.", samples[i]->QueryName());
|
||||
if (samples[i]->isSupported==QUERY)
|
||||
{
|
||||
printf(" Retry? (y/n): ");
|
||||
int supported=_getche();
|
||||
if (supported=='y' || supported=='Y')
|
||||
{
|
||||
samples[i]->isSupported=SUPPORTED;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
}
|
||||
else
|
||||
printf("Success.\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool anySupported=false;
|
||||
for (i=0; i < FEATURE_LIST_COUNT; i++)
|
||||
{
|
||||
if (samples[i]->isSupported==SUPPORTED)
|
||||
{
|
||||
anySupported=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (anySupported==false)
|
||||
{
|
||||
printf("No features supported! Quitting.\n");
|
||||
rakPeer->Shutdown(100);
|
||||
SLNet::RakPeerInterface::DestroyInstance(rakPeer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool firstComma=true;
|
||||
printf("Supported features: ");
|
||||
for (i=0; i < FEATURE_LIST_COUNT; i++)
|
||||
{
|
||||
if (samples[i]->isSupported==SUPPORTED)
|
||||
{
|
||||
if (firstComma==false)
|
||||
printf(", ");
|
||||
else
|
||||
firstComma=false;
|
||||
printf("%s", samples[i]->QueryName());
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nEntering update loop. Press 'q' to quit.\n");
|
||||
|
||||
SLNet::Packet *packet;
|
||||
bool quit=false;
|
||||
while (!quit)
|
||||
{
|
||||
for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
|
||||
{
|
||||
for (i=0; i < FEATURE_LIST_COUNT; i++)
|
||||
{
|
||||
samples[i]->ProcessPacket(rakPeer, packet);
|
||||
}
|
||||
}
|
||||
|
||||
if (_kbhit())
|
||||
{
|
||||
int ch = _getch();
|
||||
if (ch=='q')
|
||||
{
|
||||
quit=true;
|
||||
}
|
||||
else if (ch==' ')
|
||||
{
|
||||
RakNetStatistics rns;
|
||||
char message[2048];
|
||||
bool hasStatistics = rakPeer->GetStatistics(0, &rns);
|
||||
if (hasStatistics)
|
||||
{
|
||||
StatisticsToString(&rns, message, 2048, 2);
|
||||
printf("SYSTEM 0:\n%s\n", message);
|
||||
|
||||
memset(&rns, 0, sizeof(RakNetStatistics));
|
||||
rakPeer->GetStatistics(UNASSIGNED_SYSTEM_ADDRESS, &rns);
|
||||
StatisticsToString(&rns, message, 2048, 2);
|
||||
printf("STAT SUM:\n%s\n", message);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("No system 0\n");
|
||||
}
|
||||
|
||||
DataStructures::List<SystemAddress> addresses;
|
||||
DataStructures::List<RakNetGUID> guids;
|
||||
rakPeer->GetSystemList(addresses, guids);
|
||||
printf("%i systems connected\n", addresses.Size());
|
||||
}
|
||||
}
|
||||
RakSleep(30);
|
||||
}
|
||||
|
||||
printf("Quitting.\n");
|
||||
for (i=0; i < FEATURE_LIST_COUNT; i++)
|
||||
{
|
||||
samples[i]->Shutdown(rakPeer);
|
||||
}
|
||||
rakPeer->Shutdown(100);
|
||||
SLNet::RakPeerInterface::DestroyInstance(rakPeer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user