virtual void Init(RakPeerInterface *rakPeer) { if (sampleResult==FAILED) return; SystemAddress serverAddress=SelectAmongConnectedSystems(rakPeer, "UDPProxyCoordinator"); if (serverAddress==UNASSIGNED_SYSTEM_ADDRESS) { serverAddress=ConnectBlocking(rakPeer, "UDPProxyCoordinator", DEFAULT_SERVER_ADDRESS, DEFAULT_SERVER_PORT); if (serverAddress==UNASSIGNED_SYSTEM_ADDRESS) { printf("Failed to connect to a server.\n"); sampleResult=FAILED; return; } } udpProxy = new UDPProxyClient; rakPeer->AttachPlugin(udpProxy); udpProxy->SetResultHandler(this); char guid[128]; printf("Enter RakNetGuid of the remote system, which should have already connected\nto the server.\nOr press enter to just listen.\n"); gets(guid); RakNetGUID targetGuid; targetGuid.FromString(guid); if (guid[0]) { RakNetGUID remoteSystemGuid; remoteSystemGuid.FromString(guid); udpProxy->RequestForwarding(serverAddress, UNASSIGNED_SYSTEM_ADDRESS, targetGuid, UDP_FORWARDER_MAXIMUM_TIMEOUT, 0); isListening=false; } else { printf("Listening\n"); printf("My GUID is %s\n", rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString()); isListening=true; } timeout=RakNet::GetTimeMS() + 5000; }
virtual void Init(RakPeerInterface *rakPeer) { if (sampleResult==FAILED) return; printf("Given your application's bandwidth, how much traffic can be forwarded through a single peer?\nIf you use more than half the available bandwidth, then this plugin won't work for you.\n");; char supportedStr[64]; do { printf("Enter a number greater than or equal to 0: "); gets(supportedStr); } while (supportedStr[0]==0); int supported=atoi(supportedStr); if (supported<=0) { printf("Aborting Router2\n"); sampleResult=FAILED; return; } SystemAddress peerAddress = SelectAmongConnectedSystems(rakPeer, "shared peer"); if (peerAddress==UNASSIGNED_SYSTEM_ADDRESS) { peerAddress=ConnectBlocking(rakPeer, "shared peer", "", RAKPEER_PORT_STR); if (peerAddress==UNASSIGNED_SYSTEM_ADDRESS) { printf("Failed to connect to a shared peer.\n"); sampleResult=FAILED; return; } } char guid[64]; printf("Destination system must be connected to the shared peer.\n"); do { printf("Enter RakNetGUID of destination system: "); gets(guid); } while (guid[0]==0); RakNetGUID endpointGuid; endpointGuid.FromString(guid); router2 = new Router2; rakPeer->AttachPlugin(router2); router2->EstablishRouting(endpointGuid); timeout=RakNet::GetTimeMS() + 5000; }
virtual void Init(RakPeerInterface *rakPeer) { if (sampleResult==FAILED) return; SystemAddress serverAddress=SelectAmongConnectedSystems(rakPeer, "NatPunchthroughServer"); if (serverAddress==UNASSIGNED_SYSTEM_ADDRESS) { serverAddress=ConnectBlocking(rakPeer, "NatPunchthroughServer", DEFAULT_SERVER_ADDRESS, DEFAULT_SERVER_PORT); if (serverAddress==UNASSIGNED_SYSTEM_ADDRESS) { printf("Failed to connect to a server.\n"); sampleResult=FAILED; return; } } char guid[128]; printf("Enter RakNetGuid of the remote system, which should have already connected\nto the server.\nOr press enter to just listen.\n"); gets(guid); npClient = new NatPunchthroughClient; npClient->SetDebugInterface(this); rakPeer->AttachPlugin(npClient); if (guid[0]) { RakNetGUID remoteSystemGuid; remoteSystemGuid.FromString(guid); npClient->OpenNAT(remoteSystemGuid, serverAddress); isListening=false; timeout=RakNet::GetTimeMS() + 10000; } else { printf("Listening\n"); printf("My GUID is %s\n", rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString()); isListening=true; } }
int main(void) { printf("Demonstration of the router2 plugin.\n"); printf("The router2 plugin allows you to connect to a system, routing messages through\n"); printf("a third system. This is useful if you can connect to the second system, but not\n"); printf("the third, due to NAT issues.\n"); printf("1. Start 2 routers\n"); printf("2. Start 2 endpoints, connecting both of them to both router(s).\n"); printf("3. Start routing through one of the routers\n"); printf("4. Once the connection has been established, close the selected router\nto reroute.\n"); printf("Difficulty: Advanced\n\n"); endpointGuid=UNASSIGNED_RAKNET_GUID; char str[64], str2[64]; rakPeer=RakNetworkFactory::GetRakPeerInterface(); rakPeer->SetMaximumIncomingConnections(32); SocketDescriptor sd(0,0); rakPeer->Startup(32,0,&sd,1); printf("Enter 'c' to connect, 'r' to start routing, 'q' to quit.\n"); rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString(str); printf("My GUID is %s\n", str); printf("Started on port %i\n", rakPeer->GetSocket(UNASSIGNED_SYSTEM_ADDRESS)->boundAddress.port); rakPeer->SetTimeoutTime(3000,UNASSIGNED_SYSTEM_ADDRESS); router2Plugin = new Router2; Router2DebugInterface r2di; router2Plugin->SetDebugInterface(&r2di); rakPeer->AttachPlugin(router2Plugin); router2Plugin->SetMaximumForwardingRequests(1); printf("Sample running. Press 'q' to quit\n"); while (1) { if (kbhit()) { char ch=getch(); if (ch=='q') break; if (ch=='r') { do { printf("Enter destination guid: "); gets(str2); } while (str2[0]==0); RakNetGUID destinationGuid; destinationGuid.FromString(str2); router2Plugin->EstablishRouting(destinationGuid); } if (ch=='c') { printf("Enter IP address to connect to: "); gets(str); if (str[0]==0) strcpy(str, "127.0.0.1"); do { printf("Enter port to connect to: "); gets(str2); } while (str2[0]==0); // Connect rakPeer->Connect(str,atoi(str2),0,0); } } RakSleep(30); ReadAllPackets(); } RakNetworkFactory::DestroyRakPeerInterface(rakPeer); delete router2Plugin; }
int main(void) { PortAudioStream *stream; PaError err; mute=false; bool quit; char ch; printf("A sample on how to use RakVoice. You need a microphone for this sample.\n"); printf("RakVoice relies on Speex for voice encoding and decoding.\n"); printf("See DependentExtensions/RakVoice/speex-1.1.12 for speex projects.\n"); printf("For windows, I had to define HAVE_CONFIG_H, include win32/config.h,\n"); printf("and include the files under libspeex, except those that start with test.\n"); printf("PortAudio is also included and is used to read and write audio data. You\n"); printf("can substitute whatever you want if you do not want to use portaudio.\n"); printf("Difficulty: Advanced\n\n"); // Since voice is peer to peer, we give the option to use the nat punchthrough client if desired. NatPunchthroughClient natPunchthroughClient; char port[256]; rakPeer = RakNetworkFactory::GetRakPeerInterface(); printf("Enter local port (enter for default): "); gets(port); if (port[0]==0) strcpy(port, "60000"); SocketDescriptor socketDescriptor(atoi(port),0); rakPeer->Startup(4, 30, &socketDescriptor, 1); rakPeer->SetMaximumIncomingConnections(4); rakPeer->AttachPlugin(&rakVoice); rakPeer->AttachPlugin(&natPunchthroughClient); rakVoice.Init(SAMPLE_RATE, FRAMES_PER_BUFFER*sizeof(SAMPLE)); err = Pa_Initialize(); if( err != paNoError ) goto error; err = Pa_OpenStream( &stream, Pa_GetDefaultInputDeviceID(), 1, // Num channels, whatever that means PA_SAMPLE_TYPE, NULL, Pa_GetDefaultOutputDeviceID(), 1, // Num channels PA_SAMPLE_TYPE, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, /* frames per buffer */ 0, /* number of buffers, if zero then use default minimum */ 0, /* paDitherOff, // flags */ PACallback, 0 ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Support NAT punchthrough? (y/n)? "); bool useNatPunchthrough; useNatPunchthrough=(getche()=='y'); printf("\n"); char facilitatorIP[256]; {//Linux fix. Won't compile without it. Because of the goto error above, the scope is ambigious. Make it a block to define that it will not be used after the jump. //Doesn't change current logic SystemAddress facilitator; if (useNatPunchthrough) { printf("My GUID is %s\n", rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString()); printf("Enter IP of facilitator (enter for default): "); gets(facilitatorIP); if (facilitatorIP[0]==0) strcpy(facilitatorIP, "94.198.81.195"); facilitator.SetBinaryAddress(facilitatorIP); facilitator.port=NAT_PUNCHTHROUGH_FACILITATOR_PORT; rakPeer->Connect(facilitatorIP, NAT_PUNCHTHROUGH_FACILITATOR_PORT, 0, 0); printf("Connecting to facilitator...\n"); } else { printf("Not supporting NAT punchthrough.\n"); } Packet *p; quit=false; if (useNatPunchthrough==false) printf("(Q)uit. (C)onnect. (D)isconnect. C(l)ose voice channels. (M)ute. ' ' for stats.\n"); while (!quit) { if (kbhit()) { ch=getch(); if (ch=='y') { quit=true; } else if (ch=='c') { if (useNatPunchthrough) { RakNetGUID destination; printf("Enter GUID of destination: "); char guidStr[256]; while (1) { gets(guidStr); if (!destination.FromString(guidStr)) printf("Invalid GUID format. Try again.\nEnter GUID of destination: "); else break; } printf("Starting NAT punch. Please wait...\n"); natPunchthroughClient.OpenNAT(destination,facilitator); } else { char ip[256]; printf("Enter IP of remote system: "); gets(ip); if (ip[0]==0) strcpy(ip, "127.0.0.1"); printf("Enter port of remote system: "); gets(port); if (port[0]==0) strcpy(port, "60000"); rakPeer->Connect(ip, atoi(port), 0,0); } } else if (ch=='m') { mute=!mute; if (mute) printf("Now muted.\n"); else printf("No longer muted.\n"); } else if (ch=='d') { rakPeer->Shutdown(100,0); } else if (ch=='l') { rakVoice.CloseAllChannels(); } else if (ch==' ') { char message[2048]; RakNetStatistics *rss=rakPeer->GetStatistics(rakPeer->GetSystemAddressFromIndex(0)); StatisticsToString(rss, message, 2); printf("%s", message); } else if (ch=='q') quit=true; ch=0; } p=rakPeer->Receive(); while (p) { if (p->data[0]==ID_CONNECTION_REQUEST_ACCEPTED) { if (p->systemAddress==facilitator) { printf("Connection to facilitator completed\n"); printf("(Q)uit. (C)onnect. (D)isconnect. (M)ute. ' ' for stats.\n"); } else { printf("ID_CONNECTION_REQUEST_ACCEPTED from %s\n", p->systemAddress.ToString()); rakVoice.RequestVoiceChannel(p->guid); } } else if (p->data[0]==ID_CONNECTION_ATTEMPT_FAILED) { if (p->systemAddress==facilitator) { printf("Connection to facilitator failed. Using direct connections\n"); useNatPunchthrough=false; printf("(Q)uit. (C)onnect. (D)isconnect. (M)ute. ' ' for stats.\n"); } else { printf("ID_CONNECTION_ATTEMPT_FAILED\n"); } } else if (p->data[0]==ID_RAKVOICE_OPEN_CHANNEL_REQUEST || p->data[0]==ID_RAKVOICE_OPEN_CHANNEL_REPLY) { printf("Got new channel from %s\n", p->systemAddress.ToString()); } else if (p->data[0]==ID_NAT_TARGET_NOT_CONNECTED) { RakNetGUID g; RakNet::BitStream b(p->data, p->length, false); b.IgnoreBits(8); // Ignore the ID_... b.Read(g); printf("ID_NAT_TARGET_NOT_CONNECTED for %s\n", g.ToString()); } else if (p->data[0]==ID_NAT_TARGET_UNRESPONSIVE) { RakNetGUID g; RakNet::BitStream b(p->data, p->length, false); b.IgnoreBits(8); // Ignore the ID_... b.Read(g); printf("ID_NAT_TARGET_UNRESPONSIVE for %s\n", g.ToString()); } else if (p->data[0]==ID_NAT_CONNECTION_TO_TARGET_LOST) { RakNetGUID g; RakNet::BitStream b(p->data, p->length, false); b.IgnoreBits(8); // Ignore the ID_... b.Read(g); printf("ID_NAT_CONNECTION_TO_TARGET_LOST for %s\n", g.ToString()); } else if (p->data[0]==ID_NAT_ALREADY_IN_PROGRESS) { RakNetGUID g; RakNet::BitStream b(p->data, p->length, false); b.IgnoreBits(8); // Ignore the ID_... b.Read(g); printf("ID_NAT_ALREADY_IN_PROGRESS for %s\n", g.ToString()); } else if (p->data[0]==ID_NAT_PUNCHTHROUGH_FAILED) { printf("ID_NAT_PUNCHTHROUGH_FAILED for %s\n", p->guid.ToString()); } else if (p->data[0]==ID_NAT_PUNCHTHROUGH_SUCCEEDED) { printf("ID_NAT_PUNCHTHROUGH_SUCCEEDED for %s. Connecting...\n", p->guid.ToString()); rakPeer->Connect(p->systemAddress.ToString(false),p->systemAddress.port,0,0); } else if (p->data[0]==ID_ALREADY_CONNECTED) { printf("ID_ALREADY_CONNECTED\n"); } else if (p->data[0]==ID_RAKVOICE_CLOSE_CHANNEL) { printf("ID_RAKVOICE_CLOSE_CHANNEL\n"); } else if (p->data[0]==ID_DISCONNECTION_NOTIFICATION) { printf("ID_DISCONNECTION_NOTIFICATION\n"); } else if (p->data[0]==ID_NEW_INCOMING_CONNECTION) { printf("ID_NEW_INCOMING_CONNECTION\n"); } else { printf("Unknown packet ID %i\n", p->data[0]); } rakPeer->DeallocatePacket(p); p=rakPeer->Receive(); } Pa_Sleep( 30 ); } } err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); rakPeer->Shutdown(300); RakNetworkFactory::DestroyRakPeerInterface(rakPeer); return 0; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return -1; }
/// RakNet stuff void CDemo::UpdateRakNet(void) { SystemAddress facilitatorSystemAddress(DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_IP, DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_PORT); Packet *packet; RakNetTime curTime = RakNet::GetTime(); RakNet::RakString targetName; for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive()) { if (strcmp(packet->systemAddress.ToString(false),DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_IP)==0) { targetName="NATPunchthroughServer"; } else { targetName=packet->systemAddress.ToString(true); } switch (packet->data[0]) { case ID_IP_RECENTLY_CONNECTED: { PushMessage(RakNet::RakString("This IP address recently connected from ") + targetName + RakNet::RakString(".")); if (packet->systemAddress==facilitatorSystemAddress) PushMessage("Multiplayer will not work without the NAT punchthrough server!"); } break; case ID_INCOMPATIBLE_PROTOCOL_VERSION: { PushMessage(RakNet::RakString("Incompatible protocol version from ") + targetName + RakNet::RakString(".")); if (packet->systemAddress==facilitatorSystemAddress) PushMessage("Multiplayer will not work without the NAT punchthrough server!"); } break; case ID_DISCONNECTION_NOTIFICATION: { PushMessage(RakNet::RakString("Disconnected from ") + targetName + RakNet::RakString(".")); if (packet->systemAddress==facilitatorSystemAddress) isConnectedToNATPunchthroughServer=false; } break; case ID_CONNECTION_LOST: { PushMessage(RakNet::RakString("Connection to ") + targetName + RakNet::RakString(" lost.")); if (packet->systemAddress==facilitatorSystemAddress) isConnectedToNATPunchthroughServer=false; } break; case ID_NO_FREE_INCOMING_CONNECTIONS: { PushMessage(RakNet::RakString("No free incoming connections to ") + targetName + RakNet::RakString(".")); if (packet->systemAddress==facilitatorSystemAddress) PushMessage("Multiplayer will not work without the NAT punchthrough server!"); } break; case ID_NEW_INCOMING_CONNECTION: { PushMessage(RakNet::RakString("New incoming connection from ") + targetName + RakNet::RakString(".")); // Add this system as a new player replicaManager3->PushConnection(replicaManager3->AllocConnection(packet->systemAddress, packet->guid)); } break; case ID_CONNECTION_REQUEST_ACCEPTED: { PushMessage(RakNet::RakString("Connection request to ") + targetName + RakNet::RakString(" accepted.")); if (packet->systemAddress==facilitatorSystemAddress) { isConnectedToNATPunchthroughServer=true; } else { // Add this system as a new player replicaManager3->PushConnection(replicaManager3->AllocConnection(packet->systemAddress, packet->guid)); } } break; case ID_CONNECTION_ATTEMPT_FAILED: { PushMessage(RakNet::RakString("Connection attempt to ") + targetName + RakNet::RakString(" failed.")); if (packet->systemAddress==facilitatorSystemAddress) PushMessage("Multiplayer will not work without the NAT punchthrough server!"); } break; case ID_NAT_TARGET_NOT_CONNECTED: { RakNetGUID recipientGuid; RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(sizeof(MessageID)); bs.Read(recipientGuid); targetName=recipientGuid.ToString(); PushMessage(RakNet::RakString("NAT target ") + targetName + RakNet::RakString(" not connected.")); } break; case ID_NAT_TARGET_UNRESPONSIVE: { RakNetGUID recipientGuid; RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(sizeof(MessageID)); bs.Read(recipientGuid); targetName=recipientGuid.ToString(); PushMessage(RakNet::RakString("NAT target ") + targetName + RakNet::RakString(" unresponsive.")); } break; case ID_NAT_CONNECTION_TO_TARGET_LOST: { RakNetGUID recipientGuid; RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(sizeof(MessageID)); bs.Read(recipientGuid); targetName=recipientGuid.ToString(); PushMessage(RakNet::RakString("NAT target connection to ") + targetName + RakNet::RakString(" lost.")); } break; case ID_NAT_ALREADY_IN_PROGRESS: { RakNetGUID recipientGuid; RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(sizeof(MessageID)); bs.Read(recipientGuid); targetName=recipientGuid.ToString(); PushMessage(RakNet::RakString("NAT punchthrough to ") + targetName + RakNet::RakString(" in progress (skipping).")); } break; case ID_NAT_PUNCHTHROUGH_FAILED: { targetName=packet->guid.ToString(); unsigned char weAreSender=packet->data[1]; if (weAreSender) { PushMessage(RakNet::RakString("Punchthrough to ") + targetName + RakNet::RakString(" failed. Using proxy.")); udpProxyClient->RequestForwarding(facilitatorSystemAddress, UNASSIGNED_SYSTEM_ADDRESS, packet->guid, 7000); } else { PushMessage(RakNet::RakString("Punchthrough to ") + targetName + RakNet::RakString(" failed. Remote system should connect via proxy.")); } } break; case ID_NAT_PUNCHTHROUGH_SUCCEEDED: { unsigned char weAreSender=packet->data[1]; if (weAreSender) { PushMessage(RakNet::RakString("Punchthrough to ") + targetName + RakNet::RakString(" succeeded. Connecting.")); rakPeer->Connect(packet->systemAddress.ToString(false), packet->systemAddress.port,0,0); } else { PushMessage(RakNet::RakString("Punchthrough to ") + targetName + RakNet::RakString(" succeeded.")); } } break; case ID_ADVERTISE_SYSTEM: if (packet->guid!=rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS)) { char hostIP[32]; packet->systemAddress.ToString(false,hostIP); rakPeer->Connect(hostIP,packet->systemAddress.port,0,0); } break; } } for (packet=tcpInterface->Receive(); packet; tcpInterface->DeallocatePacket(packet), packet=tcpInterface->Receive()) { httpConnection->ProcessTCPPacket(packet); } if (httpConnection->HasRead()) { RakNet::RakString httpResult = httpConnection->Read(); // Good response, let the PHPDirectoryServer2 class handle the data // If resultCode is not an empty string, then we got something other than a table // (such as delete row success notification, or the message is for HTTP only and not for this class). HTTPReadResult readResult = phpDirectoryServer2->ProcessHTTPRead(httpResult); if (readResult==HTTP_RESULT_GOT_TABLE) { /// Got a table which was stored internally. Print it out const DataStructures::Table *games = phpDirectoryServer2->GetLastDownloadedTable(); // __GAME_NAME is an automatic column passed to PHPDirectoryServer::UploadTable unsigned int gameNameIndex = games->ColumnIndex("__GAME_NAME"); // RakNetGUID is a column we manually added using our own GUID with PHPDirectoryServer::SetField // We need to use RakNetGUID because NAT punchthrough refers to systems by RakNetGUID, rather than by SystemAddress unsigned int guidIndex = games->ColumnIndex("RakNetGUID"); DataStructures::Table::Row *row; unsigned int i; unsigned int tableSize=0, connectionCount=0; DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur = games->GetRows().GetListHead(); while (cur) { for (i=0; i < (unsigned)cur->size; i++) { RakAssert(gameNameIndex!=-1); row = cur->data[i]; // Make sure it's the same game, since the PHPDirectoryServer can return other games too if (gameNameIndex!=-1 && strcmp(row->cells[gameNameIndex]->c, "IrrlichtDemo")==0) { tableSize++; RakNet::RakString guidStr = row->cells[guidIndex]->c; RakNetGUID guid; guid.FromString(guidStr.C_String()); // Connect as long as I'm not connecting to myself if (guid!=rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS)) { connectionCount++; systemsToConnectTo.Push(guid); } } } cur=cur->next; } PushMessage(RakNet::RakString("DirectoryServer returned %i rows, of which we are connecting to %i",tableSize,connectionCount)); } } // Update our two classes so they can do time-based updates httpConnection->Update(); phpDirectoryServer2->Update(); // Start punchthrough to all pending systems, which we got from the PHP directory server code about 20 lines above if (isConnectedToNATPunchthroughServer) { while (systemsToConnectTo.GetSize()>0) { RakNetGUID g = systemsToConnectTo.Pop(__FILE__,__LINE__); natPunchthroughClient->OpenNAT(g, facilitatorSystemAddress); targetName=g.ToString(); PushMessage(RakNet::RakString("Punchthrough to ") + targetName + RakNet::RakString(" started.")); } } // Update non-plugin helper classes. // This keeps our system listed on the PHP directory server httpConnection->Update(); phpDirectoryServer2->Update(); // Call the Update function for networked game objects added to BaseIrrlichtReplica once the game is ready if (currentScene>=1) { DataStructures::DefaultIndexType idx; for (idx=0; idx < replicaManager3->GetReplicaCount(); idx++) ((BaseIrrlichtReplica*)(replicaManager3->GetReplicaAtIndex(idx)))->Update(curTime);; } }