#include "RakPeerInterface.h" #include "RakNetworkFactory.h" #include #include #include #include #include "BitStream.h" #include "PacketEnumerations.h" #include "StringCompressor.h" #include "ConnectionGraph.h" #include "Router.h" #ifdef _COMPATIBILITY_1 #include "Compatibility1Includes.h" // Developers of a certain platform will know what to do here. #elif defined(_WIN32) #include // Sleep #else #include // usleep #include #endif #define CHAIN_LENGTH 5 #define CHAIN_NODES_LENGTH 2 void TestRPC(RPCParameters *rpcParameters) { printf("In TestRPC to test routed RPC calls. Sender was %s\n", rpcParameters->sender.ToString()); } void GetInputIndices(int *chainIndex, int *chainNodeIndex); int main(void) { RakPeerInterface *chain[CHAIN_LENGTH]; RakPeerInterface *chainNodes[CHAIN_NODES_LENGTH * CHAIN_LENGTH]; ConnectionGraph connectionGraph[CHAIN_NODES_LENGTH * CHAIN_LENGTH+CHAIN_LENGTH]; Router router[CHAIN_NODES_LENGTH * CHAIN_LENGTH+CHAIN_LENGTH]; unsigned i,j; printf("Demonstration of the router plugin.\n"); printf("The router plugin exposes a Send function allowing you to send to\n"); printf("systems you are not directly connected to. It also causes a system to route\n"); printf("messages that weren't directed to it. It also uses multicasting to send the\n"); printf("minimum amount of data for when there are multiple recipients for the\n"); printf("same message.\n"); printf("Difficulty: Advanced\n\n"); // This topology is a 'chain' of instances of RakPeer - just a straight line for (i=0; i < CHAIN_LENGTH; i++) { chain[i]=RakNetworkFactory::GetRakPeerInterface(); chain[i]->Initialize(CHAIN_NODES_LENGTH+2, 50000+i, 30,0); chain[i]->SetMaximumIncomingConnections(CHAIN_NODES_LENGTH+1); chain[i]->AttachPlugin(&connectionGraph[i]); chain[i]->AttachPlugin(&router[i]); REGISTER_STATIC_RPC(chain[i], TestRPC); router[i].SetRestrictRoutingByType(true); router[i].AddAllowedType(ID_USER_PACKET_ENUM); // Allow this type of message router[i].AddAllowedType(ID_RPC); // Allow this type of message router[i].SetConnectionGraph(connectionGraph[i].GetGraph()); } // Each element in the chain is essentially a server, with a number of 'chain nodes' attached to it. for (i=0; i < CHAIN_NODES_LENGTH * CHAIN_LENGTH; i++) { chainNodes[i]=RakNetworkFactory::GetRakPeerInterface(); chainNodes[i]->Initialize(1, 60000+i, 30,0); chainNodes[i]->SetMaximumIncomingConnections(0); chainNodes[i]->AttachPlugin(&connectionGraph[CHAIN_LENGTH+i]); chainNodes[i]->AttachPlugin(&router[CHAIN_LENGTH+i]); REGISTER_STATIC_RPC(chainNodes[i], TestRPC); router[i+CHAIN_LENGTH].SetConnectionGraph(connectionGraph[CHAIN_LENGTH+i].GetGraph()); } // Connect the chain for (i=1; i < CHAIN_LENGTH; i++) chain[i]->Connect("127.0.0.1", 50000+i-1, 0, 0); // Connect the chain nodes for (i=0; i < CHAIN_LENGTH; i++) for (j=0; j < CHAIN_NODES_LENGTH; j++) chainNodes[i*CHAIN_NODES_LENGTH+j]->Connect("127.0.0.1", 50000+i, 0, 0); Sleep(500); printf("Commands:\n(Q)uit\n(S)end message\n"); Packet *p; while (1) { for (i=0; i < CHAIN_LENGTH; i++) { p=chain[i]->Receive(); if (p) { if (p->data[0]==ID_USER_PACKET_ENUM) printf("Chain %i (port %i) got %s from port %i\n", i, 50000+i, p->data+1,p->playerId.port); chain[i]->DeallocatePacket(p); } } for (i=0; i < CHAIN_NODES_LENGTH * CHAIN_LENGTH; i++) { p=chainNodes[i]->Receive(); if (p) { if (p->data[0]==ID_USER_PACKET_ENUM) printf("Chain Node %i (port %i) got %s from port %i\n", i, 60000+i, p->data+1,p->playerId.port); chainNodes[i]->DeallocatePacket(p); } } if (kbhit()) { char ch=getch(); if (ch=='q') break; if (ch=='s') { SystemAddressList systemList; int senderChainIndex, senderChainNodeIndex; int recipientChainIndex, recipientChainNodeIndex; PlayerID recipient; char str[256]; chain[0]->IPToPlayerID("127.0.0.1", 60000, &recipient); printf("Sender:\n"); GetInputIndices(&senderChainIndex, &senderChainNodeIndex); // senderChainIndex=0; senderChainNodeIndex=0; if (senderChainNodeIndex!=-1) printf("Sending from port %i\n", 60000+senderChainIndex*CHAIN_NODES_LENGTH+senderChainNodeIndex); else printf("Sending from port %i\n", 50000+senderChainIndex); do { printf("Recipient %i:\n", systemList.GetList()->Size()); GetInputIndices(&recipientChainIndex, &recipientChainNodeIndex); // recipientChainIndex=CHAIN_LENGTH-1; recipientChainNodeIndex=CHAIN_NODES_LENGTH-1; if (recipientChainNodeIndex!=-1) recipient.port=60000+recipientChainIndex*CHAIN_NODES_LENGTH+recipientChainNodeIndex; else recipient.port=50000+recipientChainIndex; systemList.AddSystem(recipient); if (recipientChainNodeIndex!=-1) printf("Added recipient on port %i\n", 60000+recipientChainIndex*CHAIN_NODES_LENGTH+recipientChainNodeIndex); else printf("Added recipient on port %i\n", 50000+recipientChainIndex); printf("Hit 'y' to enter another recipient or anything else to stop.\n"); } while(getch()=='y'); printf("Enter string to send: "); gets(str); if (str[0]==0) strcpy(str, "Hello World"); RakNet::BitStream out; out.Write((unsigned char)ID_USER_PACKET_ENUM); out.Write(str,(const int)strlen(str)+1); // Write clear text rather than with string compressor so I can debug more easily bool outcome; if (senderChainNodeIndex!=-1) { // connectionGraph[CHAIN_LENGTH + CHAIN_NODES_LENGTH*senderChainIndex + senderChainNodeIndex].GetGraph()->Print(); outcome=router[CHAIN_LENGTH + CHAIN_NODES_LENGTH*senderChainIndex + senderChainNodeIndex].Send((char*)out.GetData(), out.GetNumberOfBitsUsed(), HIGH_PRIORITY, RELIABLE_ORDERED, 0, &systemList); chainNodes[CHAIN_NODES_LENGTH*senderChainIndex + senderChainNodeIndex]->RPC("TestRPC", 0, HIGH_PRIORITY, RELIABLE_ORDERED, 0, systemList.GetList()->operator[](0), false, false, UNASSIGNED_NETWORK_ID, 0); } else { // connectionGraph[senderChainIndex].GetGraph()->Print(); outcome=router[senderChainIndex].Send((char*)out.GetData(), out.GetNumberOfBitsUsed(), HIGH_PRIORITY, RELIABLE_ORDERED, 0, &systemList); // TODO // Test autorouted RPC chain[senderChainIndex]->RPC("TestRPC", 0, HIGH_PRIORITY, RELIABLE_ORDERED, 0, systemList.GetList()->operator[](0), false, false, UNASSIGNED_NETWORK_ID, 0); } if (outcome) printf("Send successful\n"); else printf("Send failed\n"); } } #ifdef _WIN32 Sleep(0); #else usleep(0 * 1000); #endif } for (i=0; i < CHAIN_LENGTH; i++) RakNetworkFactory::DestroyRakPeerInterface(chain[i]); for (i=0; i < CHAIN_NODES_LENGTH * CHAIN_LENGTH; i++) RakNetworkFactory::DestroyRakPeerInterface(chainNodes[i]); return 1; } void GetInputIndices(int *chainIndex, int *chainNodeIndex) { char str[256]; printf("Select chain index (0 to %i): ", CHAIN_LENGTH-1); gets(str); if (str[0]==0) strcpy(str, "0"); *chainIndex=atoi(str); printf("Enter chain node index or -1 for none (-1 to %i): ", CHAIN_NODES_LENGTH-1); gets(str); if (str[0]==0) strcpy(str, "-1"); *chainNodeIndex=atoi(str); }