Example #1
0
unsigned int PingRakNetServer(const char *addr, unsigned short port)
{
    RakNet::Packet *packet;
    bool done = false;
    RakNet::TimeMS time = PING_UNREACHABLE;

    RakNet::SocketDescriptor socketDescriptor{0, ""};
    RakNet::RakPeerInterface *peer = RakNet::RakPeerInterface::GetInstance();
    peer->Startup(1, &socketDescriptor, 1);
    if (!peer->Ping(addr, port, false))
        return time;
    RakNet::TimeMS start = RakNet::GetTimeMS();
    while (!done)
    {
        RakNet::TimeMS now = RakNet::GetTimeMS();
        if (now - start >= PING_UNREACHABLE)
            break;

        packet = peer->Receive();
        if (!packet)
            continue;

        switch (packet->data[0])
        {
            case ID_DISCONNECTION_NOTIFICATION:
            case ID_CONNECTION_LOST:
                done = true;
                break;
            case ID_CONNECTED_PING:
            case ID_UNCONNECTED_PONG:
            {
                RakNet::BitStream bsIn(&packet->data[1], packet->length, false);
                bsIn.Read(time);
                time = now - time;
                done = true;
                break;
            }
            default:
                break;
        }
        peer->DeallocatePacket(packet);
    }

    peer->Shutdown(0);
    RakNet::RakPeerInterface::DestroyInstance(peer);
    return time > PING_UNREACHABLE ? PING_UNREACHABLE : time;
}
Example #2
0
//This static method is called when the client wants to connect to the server
void Session::StartClient(void * pVoid){
	//A parameter list is given with needed variables
	ArgumentList* pArgumentList = (ArgumentList*)pVoid;
	RakNet::RakPeerInterface* pClient;
	pClient = pArgumentList->inter;
	SessionType type = pArgumentList->type;
	RakNet::RPC3* rpc3Inst = pArgumentList->rpc3;
	SystemAddress clientID=UNASSIGNED_SYSTEM_ADDRESS;

	//Register the RPC3 functions we want to call upon
	RPC3_REGISTER_FUNCTION(rpc3Inst, ReceiveInformation);
	RPC3_REGISTER_FUNCTION(rpc3Inst, UpdateCharacter);
	RPC3_REGISTER_FUNCTION(rpc3Inst, UpdateCharacterVelocity);
	RPC3_REGISTER_FUNCTION(rpc3Inst, SyncClients);
	RPC3_REGISTER_FUNCTION(rpc3Inst, ReceiveID);
	RPC3_REGISTER_FUNCTION(rpc3Inst, RemoveCharacter);
	
	//Create the basic connection with help of RakNet
	SocketDescriptor socketDescriptor(0,0);
	socketDescriptor.socketFamily=AF_INET;
	pClient->Startup(1,&socketDescriptor, 1);
	pClient->Ping( "255.255.255.255", 50000, true, 0 );

	// Holds packets
	Packet* p;

	//Make sure the RPC3 is attached as a plugin, else it won't work
	pClient->AttachPlugin(rpc3Inst);

	char message[2048];
	// Loop for input
	while (Session::threading)
	{
		// This sleep keeps RakNet responsive
		RakSleep(30);
		#ifdef _WIN32
			Sleep(30);
		#else
			usleep(30 * 1000);
		#endif

		// Get a packet from either the server or the client
		for (p=pClient->Receive(); p; pClient->DeallocatePacket(p), p=pClient->Receive())
		{
			switch (p->data[0])
			{
			case ID_DISCONNECTION_NOTIFICATION:
				printf("ID_DISCONNECTION_NOTIFICATION\n");
				break;
			case ID_ALREADY_CONNECTED:
				printf("ID_ALREADY_CONNECTED\n");
				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				printf("Connection attempt failed\n");
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
				break;
			case ID_UNCONNECTED_PONG:
				// Found the server
				pClient->Connect(p->systemAddress.ToString(false),p->systemAddress.GetPort(),0,0,0);
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				// This tells the client they have connected
				printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
				Game::getSingletonPtr()->CreateCharacter("PlayerHost");
				//Game::getSingletonPtr()->SetPlayer(
				break;
			case ID_NEW_INCOMING_CONNECTION:
			{
				printf("New incoming connection");
				break;
			}
			case ID_RPC_REMOTE_ERROR:
				{
					// Recipient system returned an error
					switch (p->data[1])
					{
					case RakNet::RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE:
						printf("RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE\n");
						break;
					case RakNet::RPC_ERROR_OBJECT_DOES_NOT_EXIST:
						printf("RPC_ERROR_OBJECT_DOES_NOT_EXIST\n");
						break;
					case RakNet::RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE:
						printf("RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE\n");
						break;
					case RakNet::RPC_ERROR_FUNCTION_NOT_REGISTERED:
						printf("RPC_ERROR_FUNCTION_NOT_REGISTERED\n");
						break;
					case RakNet::RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED:
						printf("RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED\n");
						break;
					case RakNet::RPC_ERROR_CALLING_CPP_AS_C:
						printf("RPC_ERROR_CALLING_CPP_AS_C\n");
						break;
					case RakNet::RPC_ERROR_CALLING_C_AS_CPP:
						printf("RPC_ERROR_CALLING_C_AS_CPP\n");
						break;
					}
					printf("Function: %s", p->data+2);
				}
			}
		}
	}
	//When we are done as a client, close everything and delete RPC3
	Session::threading = false;
	pClient->Shutdown(20,0);
	RakNet::RakPeerInterface::DestroyInstance(pClient);
	delete rpc3Inst;
}
int main(int argc, char** argv) {
	RakNet::RakPeerInterface *server = RakNet::RakPeerInterface::GetInstance();
	RakNet::Packet* p;
	unsigned char packetIdentifier;
	RakNet::SystemAddress clientID = RakNet::UNASSIGNED_SYSTEM_ADDRESS;
	RakNet::RakNetStatistics *rss;
	RakNet::SocketDescriptor socketDescriptors[2];
	char portstring[30];

	socketDescriptors[0].port = SERVER_PORT;
	socketDescriptors[0].socketFamily = AF_INET; // Test out IPV4
	socketDescriptors[1].port = SERVER_PORT;
	socketDescriptors[1].socketFamily = AF_INET6; // Test out IPV6
	if (server->Startup(4, socketDescriptors, 2) != RakNet::RAKNET_STARTED) {
		std::cout << "IPV6 not supported, starting with IPV4-only interface..." << std::endl;
		if (server->Startup(4, socketDescriptors, 1) != RakNet::RAKNET_STARTED) {
			std::cerr << "Error creating server, exiting..." << std::endl;
			exit(-1);
		}
	}
	std::cout << "Server started successfully. Listening on port " << SERVER_PORT << std::endl;
	server->SetMaximumIncomingConnections(20);
	server->SetOccasionalPing(true);
	server->SetUnreliableTimeout(1000);

	DataStructures::List<RakNet::RakNetSocket2*> sockets;
	server->GetSockets(sockets);
	std::cout << "Socket addresses used by RakNet:" << std::endl;
	for (unsigned int i = 0; i < sockets.Size(); i++) {
		printf("%i. %s\n", i + 1, sockets[i]->GetBoundAddress().ToString(true));
	}
	char message[2048];

	// Loop for input
	while (1)
	{

		// This sleep keeps RakNet responsive
		RakSleep(30);

		if (kbhit())
		{
			// Notice what is not here: something to keep our network running.  It's
			// fine to block on gets or anything we want
			// Because the network engine was painstakingly written using threads.
			Gets(message, sizeof(message));

			if (strcmp(message, "quit") == 0)
			{
				puts("Quitting.");
				break;
			}

			if (strcmp(message, "stat") == 0)
			{
				rss = server->GetStatistics(server->GetSystemAddressFromIndex(0));
				StatisticsToString(rss, message, 2);
				printf("%s", message);
				printf("Ping %i\n", server->GetAveragePing(server->GetSystemAddressFromIndex(0)));

				continue;
			}

			if (strcmp(message, "ping") == 0)
			{
				server->Ping(clientID);

				continue;
			}

			if (strcmp(message, "pingip") == 0)
			{
				printf("Enter IP: ");
				Gets(message, sizeof(message));
				printf("Enter port: ");
				Gets(portstring, sizeof(portstring));
				if (portstring[0] == 0)
					strcpy(portstring, "1234");
				server->Ping(message, atoi(portstring), false);

				continue;
			}

			if (strcmp(message, "kick") == 0)
			{
				server->CloseConnection(clientID, true, 0);

				continue;
			}

			if (strcmp(message, "getconnectionlist") == 0)
			{
				printf("Connections:\n");
				RakNet::SystemAddress systems[10];
				unsigned short numConnections = 10;
				server->GetConnectionList((RakNet::SystemAddress*) &systems, &numConnections);
				for (int i = 0; i < numConnections; i++)
				{
					printf("%i. %s\n", i + 1, systems[i].ToString(true));
				}
				continue;
			}

			if (strcmp(message, "ban") == 0)
			{
				printf("Enter IP to ban.  You can use * as a wildcard\n");
				Gets(message, sizeof(message));
				server->AddToBanList(message);
				printf("IP %s added to ban list.\n", message);

				continue;
			}


			// Message now holds what we want to broadcast
			char message2[2048];
			// Append Server: to the message so clients know that it ORIGINATED from the server
			// All messages to all clients come from the server either directly or by being
			// relayed from other clients
			message2[0] = 0;
			const static char prefix[] = "Server: ";
			strncpy(message2, prefix, sizeof(message2));
			strncat(message2, message, sizeof(message2) - strlen(prefix) - 1);

			// message2 is the data to send
			// strlen(message2)+1 is to send the null terminator
			// HIGH_PRIORITY doesn't actually matter here because we don't use any other priority
			// RELIABLE_ORDERED means make sure the message arrives in the right order
			// We arbitrarily pick 0 for the ordering stream
			// RakNet::UNASSIGNED_SYSTEM_ADDRESS means don't exclude anyone from the broadcast
			// true means broadcast the message to everyone connected
			server->Send(message2, (const int)strlen(message2) + 1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, RakNet::UNASSIGNED_SYSTEM_ADDRESS, true);
		}

		// Get a packet from either the server or the client

		for (p = server->Receive(); p; server->DeallocatePacket(p), p = server->Receive())
		{
			// We got a packet, get the identifier with our handy function
			packetIdentifier = GetPacketIdentifier(p);

			// Check if this is a network message packet
			switch (packetIdentifier)
			{
			case ID_DISCONNECTION_NOTIFICATION:
				// Connection lost normally
				printf("ID_DISCONNECTION_NOTIFICATION from %s\n", p->systemAddress.ToString(true));;
				break;


			case ID_NEW_INCOMING_CONNECTION:
				// Somebody connected.  We have their IP now
				printf("ID_NEW_INCOMING_CONNECTION from %s with GUID %s\n", p->systemAddress.ToString(true), p->guid.ToString());
				clientID = p->systemAddress; // Record the player ID of the client

				printf("Remote internal IDs:\n");
				for (int index = 0; index < MAXIMUM_NUMBER_OF_INTERNAL_IDS; index++)
				{
					RakNet::SystemAddress internalId = server->GetInternalID(p->systemAddress, index);
					if (internalId != RakNet::UNASSIGNED_SYSTEM_ADDRESS)
					{
						printf("%i. %s\n", index + 1, internalId.ToString(true));
					}
				}

				break;

			case ID_INCOMPATIBLE_PROTOCOL_VERSION:
				printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
				break;

			case ID_CONNECTED_PING:
			case ID_UNCONNECTED_PING:
				printf("Ping from %s\n", p->systemAddress.ToString(true));
				break;

			case ID_CONNECTION_LOST:
				// Couldn't deliver a reliable packet - i.e. the other system was abnormally
				// terminated
				printf("ID_CONNECTION_LOST from %s\n", p->systemAddress.ToString(true));;
				break;

			default:
				// The server knows the static data of all clients, so we can prefix the message
				// With the name data
				printf("%s\n", p->data);

				// Relay the message.  We prefix the name for other clients.  This demonstrates
				// That messages can be changed on the server before being broadcast
				// Sending is the same as before
				sprintf(message, "%s", p->data);
				server->Send(message, (const int)strlen(message) + 1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, p->systemAddress, true);

				break;
			}

		}
	}

	server->Shutdown(300);
	// We're done with the network
	RakNet::RakPeerInterface::DestroyInstance(server);


}
int main(void)
{
	// Pointers to the interfaces of our server and client.
	// Note we can easily have both in the same program
	RakNet::RakPeerInterface *client;
	RakNet::RakPeerInterface *server;
	bool b;
	char str[256];
	char serverPort[30], clientPort[30];
	RakNet::TimeMS quitTime;
	// Holds packets
	RakNet::Packet* p;	

	printf("A client / server sample showing how clients can broadcast offline packets\n");
	printf("to find active servers.\n");
	printf("Difficulty: Beginner\n\n");

	printf("Instructions:\nRun one or more servers on the same port.\nRun a client and it will get pongs from those servers.\n");
	printf("Run as (s)erver or (c)lient?\n");
	Gets(str, sizeof(str));

	if (str[0]=='s' || str[0]=='S')
	{
		client=0;
		server=RakNet::RakPeerInterface::GetInstance();
		// A server
		printf("Enter the server port\n");
		Gets(serverPort,sizeof(serverPort));
		if (serverPort[0]==0)
			strcpy(serverPort, "60001");

		printf("Starting server.\n");
		// The server has to be started to respond to pings.
		RakNet::SocketDescriptor socketDescriptor(atoi(serverPort),0);
		socketDescriptor.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255
		b = server->Startup(2, &socketDescriptor, 1)==RakNet::RAKNET_STARTED;
		server->SetMaximumIncomingConnections(2);
		if (b)
			printf("Server started, waiting for connections.\n");
		else
		{ 
			printf("Server failed to start.  Terminating.\n");
			exit(1);
		}
	}
	else
	{
		client=RakNet::RakPeerInterface::GetInstance();
		server=0;

		// Get our input
		printf("Enter the client port to listen on, or 0\n");
		Gets(clientPort,sizeof(clientPort));
		if (clientPort[0]==0)
			strcpy(clientPort, "60000");
		printf("Enter the port to ping\n");
		Gets(serverPort,sizeof(serverPort));
		if (serverPort[0]==0)
			strcpy(serverPort, "60001");
		RakNet::SocketDescriptor socketDescriptor(atoi(clientPort),0);
		socketDescriptor.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255
		client->Startup(1, &socketDescriptor, 1);

		// Connecting the client is very simple.  0 means we don't care about
		// a connectionValidationInteger, and false for low priority threads
		// All 255's mean broadcast
		client->Ping("255.255.255.255", atoi(serverPort), false);

		printf("Pinging\n");
	}

	printf("How many seconds to run this sample for?\n");
	Gets(str, sizeof(str));
	if (str[0]==0)
	{
		printf("Defaulting to 5 seconds\n");
		quitTime = RakNet::GetTimeMS() + 5000;
	}
	else
		quitTime = RakNet::GetTimeMS() + atoi(str) * 1000;

	// Loop for input
	while (RakNet::GetTimeMS() < quitTime)
	{
		if (server)
			p = server->Receive();
		else 
			p = client->Receive();

		if (p==0)
		{
			RakSleep(30);
			continue;
		}
		if (server)
			server->DeallocatePacket(p);
		else
		{
			if (p->data[0]==ID_UNCONNECTED_PONG)
			{
				RakNet::TimeMS time;
				RakNet::BitStream bsIn(p->data,p->length,false);
				bsIn.IgnoreBytes(1);
				bsIn.Read(time);
				printf("Got pong from %s with time %i\n", p->systemAddress.ToString(), RakNet::GetTimeMS() - time);
			}
			else if (p->data[0]==ID_UNCONNECTED_PING)
			{
				printf("ID_UNCONNECTED_PING from %s\n",p->guid.ToString());
			}
			else if (p->data[0]==ID_UNCONNECTED_PING_OPEN_CONNECTIONS)
			{
				printf("ID_UNCONNECTED_PING_OPEN_CONNECTIONS from %s\n",p->guid.ToString());
			}
			client->DeallocatePacket(p);
		}

		RakSleep(30);
	}

	// We're done with the network
	if (server)
		RakNet::RakPeerInterface::DestroyInstance(server);
	if (client)
		RakNet::RakPeerInterface::DestroyInstance(client);

	return 0;
}