int main(int argc, char **argv) { if (argc<8) { printf("Arguments: serverIP, pathToGame, gameName, patchImmediately, localPort, serverPort, fullScan"); return 0; } RakNet::SystemAddress TCPServerAddress=RakNet::UNASSIGNED_SYSTEM_ADDRESS; RakNet::AutopatcherClient autopatcherClient; RakNet::FileListTransfer fileListTransfer; RakNet::CloudClient cloudClient; autopatcherClient.SetFileListTransferPlugin(&fileListTransfer); bool didRebalance=false; // So we only reconnect to a lower load server once, for load balancing bool fullScan = argv[7][0]=='1'; unsigned short localPort; localPort=atoi(argv[5]); unsigned short serverPort=atoi(argv[6]); RakNet::PacketizedTCP packetizedTCP; if (packetizedTCP.Start(localPort,1)==false) { printf("Failed to start TCP. Is the port already in use?"); return 1; } packetizedTCP.AttachPlugin(&autopatcherClient); packetizedTCP.AttachPlugin(&fileListTransfer); RakNet::RakPeerInterface *rakPeer; rakPeer = RakNet::RakPeerInterface::GetInstance(); RakNet::SocketDescriptor socketDescriptor(localPort,0); rakPeer->Startup(1,&socketDescriptor, 1); rakPeer->AttachPlugin(&cloudClient); DataStructures::List<RakNet::RakNetSocket2* > sockets; rakPeer->GetSockets(sockets); printf("Started on port %i\n", sockets[0]->GetBoundAddress().GetPort()); char buff[512]; strcpy(buff, argv[1]); rakPeer->Connect(buff, serverPort, 0, 0); printf("Connecting...\n"); char appDir[512]; strcpy(appDir, argv[2]); char appName[512]; strcpy(appName, argv[3]); bool patchImmediately=argc>=5 && argv[4][0]=='1'; RakNet::Packet *p; while (1) { RakNet::SystemAddress notificationAddress; notificationAddress=packetizedTCP.HasCompletedConnectionAttempt(); if (notificationAddress!=RakNet::UNASSIGNED_SYSTEM_ADDRESS) { printf("ID_CONNECTION_REQUEST_ACCEPTED\n"); TCPServerAddress=notificationAddress; } notificationAddress=packetizedTCP.HasNewIncomingConnection(); if (notificationAddress!=RakNet::UNASSIGNED_SYSTEM_ADDRESS) printf("ID_NEW_INCOMING_CONNECTION\n"); notificationAddress=packetizedTCP.HasLostConnection(); if (notificationAddress!=RakNet::UNASSIGNED_SYSTEM_ADDRESS) printf("ID_CONNECTION_LOST\n"); notificationAddress=packetizedTCP.HasFailedConnectionAttempt(); if (notificationAddress!=RakNet::UNASSIGNED_SYSTEM_ADDRESS) { printf("ID_CONNECTION_ATTEMPT_FAILED TCP\n"); autopatcherClient.SetFileListTransferPlugin(0); autopatcherClient.Clear(); packetizedTCP.Stop(); rakPeer->Shutdown(500,0); RakNet::RakPeerInterface::DestroyInstance(rakPeer); return 0; } p=packetizedTCP.Receive(); while (p) { if (p->data[0]==ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR) { char buff[256]; RakNet::BitStream temp(p->data, p->length, false); temp.IgnoreBits(8); RakNet::StringCompressor::Instance()->DecodeString(buff, 256, &temp); printf("ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR\n"); printf("%s\n", buff); autopatcherClient.SetFileListTransferPlugin(0); autopatcherClient.Clear(); packetizedTCP.Stop(); rakPeer->Shutdown(500,0); RakNet::RakPeerInterface::DestroyInstance(rakPeer); return 0; } else if (p->data[0]==ID_AUTOPATCHER_CANNOT_DOWNLOAD_ORIGINAL_UNMODIFIED_FILES) { printf("ID_AUTOPATCHER_CANNOT_DOWNLOAD_ORIGINAL_UNMODIFIED_FILES\n"); autopatcherClient.SetFileListTransferPlugin(0); autopatcherClient.Clear(); packetizedTCP.Stop(); rakPeer->Shutdown(500,0); RakNet::RakPeerInterface::DestroyInstance(rakPeer); return 0; } else if (p->data[0]==ID_AUTOPATCHER_FINISHED) { printf("ID_AUTOPATCHER_FINISHED with server time %f\n", autopatcherClient.GetServerDate()); double srvDate=autopatcherClient.GetServerDate(); FILE *fp = fopen("srvDate", "wb"); fwrite(&srvDate,sizeof(double),1,fp); fclose(fp); autopatcherClient.SetFileListTransferPlugin(0); autopatcherClient.Clear(); packetizedTCP.Stop(); rakPeer->Shutdown(500,0); RakNet::RakPeerInterface::DestroyInstance(rakPeer); return 0; } else if (p->data[0]==ID_AUTOPATCHER_RESTART_APPLICATION) { printf("ID_AUTOPATCHER_RESTART_APPLICATION"); autopatcherClient.SetFileListTransferPlugin(0); autopatcherClient.Clear(); packetizedTCP.Stop(); rakPeer->Shutdown(500,0); RakNet::RakPeerInterface::DestroyInstance(rakPeer); return 0; } // Launch \"AutopatcherClientRestarter.exe autopatcherRestart.txt\"\nQuit this application immediately after to unlock files.\n"); packetizedTCP.DeallocatePacket(p); p=packetizedTCP.Receive(); } p=rakPeer->Receive(); while (p) { if (p->data[0]==ID_CONNECTION_REQUEST_ACCEPTED) { // UploadInstanceToCloud(&cloudClient, p->guid); // GetClientSubscription(&cloudClient, p->guid); GetServers(&cloudClient, p->guid); break; } else if (p->data[0]==ID_CONNECTION_ATTEMPT_FAILED) { printf("ID_CONNECTION_ATTEMPT_FAILED UDP\n"); autopatcherClient.SetFileListTransferPlugin(0); autopatcherClient.Clear(); packetizedTCP.Stop(); rakPeer->Shutdown(500,0); RakNet::RakPeerInterface::DestroyInstance(rakPeer); return 0; } else if (p->data[0]==ID_CLOUD_GET_RESPONSE) { RakNet::CloudQueryResult cloudQueryResult; cloudClient.OnGetReponse(&cloudQueryResult, p); unsigned int rowIndex; const bool wasCallToGetServers=cloudQueryResult.cloudQuery.keys[0].primaryKey=="CloudConnCount"; printf("\n"); if (wasCallToGetServers) printf("Downloaded server list. %i servers.\n", cloudQueryResult.rowsReturned.Size()); unsigned short connectionsOnOurServer=65535; unsigned short lowestConnectionsServer=65535; RakNet::SystemAddress lowestConnectionAddress; for (rowIndex=0; rowIndex < cloudQueryResult.rowsReturned.Size(); rowIndex++) { RakNet::CloudQueryRow *row = cloudQueryResult.rowsReturned[rowIndex]; if (wasCallToGetServers) { unsigned short connCount; RakNet::BitStream bsIn(row->data, row->length, false); bsIn.Read(connCount); printf("%i. Server found at %s with %i connections\n", rowIndex+1, row->serverSystemAddress.ToString(true), connCount); unsigned short connectionsExcludingOurselves; if (row->serverGUID==p->guid) connectionsExcludingOurselves=connCount-1; else connectionsExcludingOurselves=connCount; // Find the lowest load server (optional) if (p->guid==row->serverGUID) { connectionsOnOurServer=connectionsExcludingOurselves; } else if (connectionsExcludingOurselves < lowestConnectionsServer) { lowestConnectionsServer=connectionsExcludingOurselves; lowestConnectionAddress=row->serverSystemAddress; } } } // Do load balancing by reconnecting to lowest load server (optional) if (didRebalance==false && wasCallToGetServers) { if (cloudQueryResult.rowsReturned.Size()>0 && connectionsOnOurServer>lowestConnectionsServer) { printf("Reconnecting to lower load server %s\n", lowestConnectionAddress.ToString(false)); rakPeer->CloseConnection(p->guid, true); // Wait for the thread to close, otherwise will immediately get back ID_CONNECTION_ATTEMPT_FAILED because no free outgoing connection slots // Alternatively, just call Startup() with 2 slots instead of 1 RakSleep(500); rakPeer->Connect(lowestConnectionAddress.ToString(false), lowestConnectionAddress.GetPort(), 0, 0); // TCP Connect to new IP address packetizedTCP.Connect(lowestConnectionAddress.ToString(false),serverPort,false); } else { // TCP Connect to original IP address packetizedTCP.Connect(buff,serverPort,false); } didRebalance=true; } cloudClient.DeallocateWithDefaultAllocator(&cloudQueryResult); } rakPeer->DeallocatePacket(p); p=rakPeer->Receive(); } if (TCPServerAddress!=RakNet::UNASSIGNED_SYSTEM_ADDRESS && patchImmediately==true) { patchImmediately=false; char restartFile[512]; strcpy(restartFile, appDir); strcat(restartFile, "/autopatcherRestart.txt"); double lastUpdateDate; if (fullScan==false) { FILE *fp = fopen("srvDate", "rb"); if (fp) { fread(&lastUpdateDate, sizeof(lastUpdateDate), 1, fp); fclose(fp); } else lastUpdateDate=0; } else lastUpdateDate=0; if (autopatcherClient.PatchApplication(appName, appDir, lastUpdateDate, TCPServerAddress, &transferCallback, restartFile, argv[0])) { printf("Patching process starting.\n"); } else { printf("Failed to start patching.\n"); autopatcherClient.SetFileListTransferPlugin(0); autopatcherClient.Clear(); packetizedTCP.Stop(); rakPeer->Shutdown(500,0); RakNet::RakPeerInterface::DestroyInstance(rakPeer); return 0; } } RakSleep(30); } // Dereference so the destructor doesn't crash autopatcherClient.SetFileListTransferPlugin(0); autopatcherClient.Clear(); packetizedTCP.Stop(); rakPeer->Shutdown(500,0); RakNet::RakPeerInterface::DestroyInstance(rakPeer); return 1; }
int main(int argc, char **argv) { printf("A simple client interface for the advanced autopatcher.\n"); printf("Use DirectoryDeltaTransfer for a simpler version of an autopatcher.\n"); printf("Difficulty: Intermediate\n\n"); printf("Client starting..."); RakNet::SystemAddress serverAddress=RakNet::UNASSIGNED_SYSTEM_ADDRESS; RakNet::AutopatcherClient autopatcherClient; RakNet::FileListTransfer fileListTransfer; autopatcherClient.SetFileListTransferPlugin(&fileListTransfer); unsigned short localPort=0; if (argc>=6) { localPort=atoi(argv[5]); } #ifdef USE_TCP RakNet::PacketizedTCP packetizedTCP; if (packetizedTCP.Start(localPort,1)==false) { printf("Failed to start TCP. Is the port already in use?"); return 1; } packetizedTCP.AttachPlugin(&autopatcherClient); packetizedTCP.AttachPlugin(&fileListTransfer); #else RakNet::RakPeerInterface *rakPeer; rakPeer = RakNet::RakPeerInterface::GetInstance(); RakNet::SocketDescriptor socketDescriptor(localPort,0); rakPeer->Startup(1,&socketDescriptor, 1); // Plugin will send us downloading progress notifications if a file is split to fit under the MTU 10 or more times rakPeer->SetSplitMessageProgressInterval(10); rakPeer->AttachPlugin(&autopatcherClient); rakPeer->AttachPlugin(&fileListTransfer); #endif printf("started\n"); char buff[512]; if (argc<2) { printf("Enter server IP: "); Gets(buff,sizeof(buff)); if (buff[0]==0) //strcpy(buff, "94.198.81.195"); strcpy(buff, "127.0.0.1"); } else strcpy(buff, argv[1]); #ifdef USE_TCP packetizedTCP.Connect(buff,60000,false); #else rakPeer->Connect(buff, 60000, 0, 0); #endif printf("Connecting...\n"); char appDir[512]; if (argc<3) { printf("Enter application directory: "); Gets(appDir,sizeof(appDir)); if (appDir[0]==0) { strcpy(appDir, "D:/temp2"); } } else strcpy(appDir, argv[2]); char appName[512]; if (argc<4) { printf("Enter application name: "); Gets(appName,sizeof(appName)); if (appName[0]==0) strcpy(appName, "TestApp"); } else strcpy(appName, argv[3]); bool patchImmediately=argc>=5 && argv[4][0]=='1'; if (patchImmediately==false) printf("Hit 'q' to quit, 'p' to patch, 'c' to cancel the patch. 'r' to reconnect. 'd' to disconnect.\n"); else printf("Hit 'q' to quit, 'c' to cancel the patch.\n"); char ch; RakNet::Packet *p; while (1) { #ifdef USE_TCP RakNet::SystemAddress notificationAddress; notificationAddress=packetizedTCP.HasCompletedConnectionAttempt(); if (notificationAddress!=RakNet::UNASSIGNED_SYSTEM_ADDRESS) { printf("ID_CONNECTION_REQUEST_ACCEPTED\n"); serverAddress=notificationAddress; } notificationAddress=packetizedTCP.HasNewIncomingConnection(); if (notificationAddress!=RakNet::UNASSIGNED_SYSTEM_ADDRESS) printf("ID_NEW_INCOMING_CONNECTION\n"); notificationAddress=packetizedTCP.HasLostConnection(); if (notificationAddress!=RakNet::UNASSIGNED_SYSTEM_ADDRESS) printf("ID_CONNECTION_LOST\n"); p=packetizedTCP.Receive(); while (p) { if (p->data[0]==ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR) { char buff[256]; RakNet::BitStream temp(p->data, p->length, false); temp.IgnoreBits(8); RakNet::StringCompressor::Instance()->DecodeString(buff, 256, &temp); printf("ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR\n"); printf("%s\n", buff); } else if (p->data[0]==ID_AUTOPATCHER_FINISHED) { printf("ID_AUTOPATCHER_FINISHED with server time %f\n", autopatcherClient.GetServerDate()); double srvDate=autopatcherClient.GetServerDate(); FILE *fp = fopen("srvDate", "wb"); fwrite(&srvDate,sizeof(double),1,fp); fclose(fp); } else if (p->data[0]==ID_AUTOPATCHER_RESTART_APPLICATION) printf("Launch \"AutopatcherClientRestarter.exe autopatcherRestart.txt\"\nQuit this application immediately after to unlock files.\n"); packetizedTCP.DeallocatePacket(p); p=packetizedTCP.Receive(); } #else p=rakPeer->Receive(); while (p) { if (p->data[0]==ID_DISCONNECTION_NOTIFICATION) printf("ID_DISCONNECTION_NOTIFICATION\n"); else if (p->data[0]==ID_CONNECTION_LOST) printf("ID_CONNECTION_LOST\n"); else if (p->data[0]==ID_CONNECTION_REQUEST_ACCEPTED) { printf("ID_CONNECTION_REQUEST_ACCEPTED\n"); serverAddress=p->systemAddress; } else if (p->data[0]==ID_CONNECTION_ATTEMPT_FAILED) printf("ID_CONNECTION_ATTEMPT_FAILED\n"); else if (p->data[0]==ID_NO_FREE_INCOMING_CONNECTIONS) printf("ID_NO_FREE_INCOMING_CONNECTIONS\n"); else if (p->data[0]==ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR) { char buff[256]; RakNet::BitStream temp(p->data, p->length, false); temp.IgnoreBits(8); RakNet::StringCompressor::Instance()->DecodeString(buff, 256, &temp); printf("ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR\n"); printf("%s\n", buff); } else if (p->data[0]==ID_AUTOPATCHER_FINISHED) { printf("ID_AUTOPATCHER_FINISHED with server time %f\n", autopatcherClient.GetServerDate()); double srvDate=autopatcherClient.GetServerDate(); FILE *fp = fopen("srvDate", "wb"); fwrite(&srvDate,sizeof(double),1,fp); fclose(fp); } else if (p->data[0]==ID_AUTOPATCHER_RESTART_APPLICATION) printf("Launch \"AutopatcherClientRestarter.exe autopatcherRestart.txt\"\nQuit this application immediately after to unlock files.\n"); rakPeer->DeallocatePacket(p); p=rakPeer->Receive(); } #endif if (kbhit()) ch=getch(); else ch=0; if (ch=='q') break; else if (ch=='r') { #ifdef USE_TCP packetizedTCP.Connect(buff,60000,false); #else rakPeer->Connect(buff, 60000, 0, 0); #endif } else if (ch=='d') { #ifdef USE_TCP packetizedTCP.CloseConnection(serverAddress); #else rakPeer->CloseConnection(serverAddress, true); #endif } else if (ch=='p' || (serverAddress!=RakNet::UNASSIGNED_SYSTEM_ADDRESS && patchImmediately==true)) { patchImmediately=false; char restartFile[512]; strcpy(restartFile, appDir); strcat(restartFile, "/autopatcherRestart.txt"); double lastUpdateDate; FILE *fp = fopen("srvDate", "rb"); if (fp) { fread(&lastUpdateDate, sizeof(lastUpdateDate), 1, fp); fclose(fp); } else lastUpdateDate=0; if (autopatcherClient.PatchApplication(appName, appDir, lastUpdateDate, serverAddress, &transferCallback, restartFile, argv[0])) { printf("Patching process starting.\n"); } else { printf("Failed to start patching.\n"); } } else if (ch=='c') { autopatcherClient.Clear(); printf("Autopatcher cleared.\n"); } RakSleep(30); } // Dereference so the destructor doesn't crash autopatcherClient.SetFileListTransferPlugin(0); #ifdef USE_TCP packetizedTCP.Stop(); #else rakPeer->Shutdown(500,0); RakNet::RakPeerInterface::DestroyInstance(rakPeer); #endif return 1; }