Major rewrite, speed, and stability improvements

This commit is contained in:
Anonymous275 2020-06-04 01:52:48 +03:00
parent 4a3235f445
commit 422e94f833
6 changed files with 153 additions and 47 deletions

View File

@ -21,8 +21,8 @@ extern bool TCPTerminate;
extern bool MPDEV; extern bool MPDEV;
void StartSync(const std::string &Data){ void StartSync(const std::string &Data){
std::thread t1(ProxyThread,Data.substr(1,Data.find(':')-1),std::stoi(Data.substr(Data.find(':')+1))); //std::thread t1(ProxyThread,Data.substr(1,Data.find(':')-1),std::stoi(Data.substr(Data.find(':')+1)));
//std::thread t1(ProxyThread,"127.0.0.1",30814); std::thread t1(ProxyThread,"127.0.0.1",30814);
t1.detach(); t1.detach();
} }

View File

@ -26,17 +26,28 @@ void DeleteKey(){
RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey); RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey);
RegDeleteValueA(hKey, TEXT("userpath_override")); RegDeleteValueA(hKey, TEXT("userpath_override"));
} }
void RollBack(const std::string&Val){ void RollBack(const std::string&Val,int T){
std::this_thread::sleep_for(std::chrono::seconds(7)); std::this_thread::sleep_for(std::chrono::seconds(T));
if(!Val.empty())Write(Val); if(!Val.empty())Write(Val);
else DeleteKey(); else DeleteKey();
} }
void StartGame(const std::string&ExeDir,const std::string&Current){ void StartGame(const std::string&ExeDir,const std::string&Current){
BOOL bSuccess = FALSE;
PROCESS_INFORMATION pi;
STARTUPINFO si = {0};
si.cb = sizeof(si);
std::string BaseDir = ExeDir.substr(0,ExeDir.find_last_of('\\'));
bSuccess = CreateProcessA(ExeDir.c_str(), nullptr, nullptr, nullptr, TRUE, 0, nullptr, BaseDir.c_str(), &si, &pi);
if (bSuccess)
{
std::cout << "Game Launched!\n"; std::cout << "Game Launched!\n";
std::thread RB(RollBack,Write(Current)); DWORD dwPid = pi.dwProcessId; //Gets the PID
std::thread RB(RollBack,Write(Current),7);
RB.detach(); RB.detach();
SystemExec(ExeDir + " -nocrashreport"); WaitForSingleObject(pi.hProcess, INFINITE);
std::cout << "\nGame Closed! launcher closing in 5 secs\n"; std::cout << "\nGame Closed! launcher closing in 5 secs\n";
}else std::cout << "\nFailed to Launch the game! launcher closing in 5 secs\n";
RollBack(Write(Current),0);
std::this_thread::sleep_for(std::chrono::seconds(5)); std::this_thread::sleep_for(std::chrono::seconds(5));
exit(2); exit(2);
} }

View File

@ -12,7 +12,6 @@
#include <vector> #include <vector>
int ClientID = -1; int ClientID = -1;
extern int DEFAULT_PORT; extern int DEFAULT_PORT;
std::chrono::time_point<std::chrono::steady_clock> PingStart,PingEnd; std::chrono::time_point<std::chrono::steady_clock> PingStart,PingEnd;
extern std::vector<std::string> GlobalInfo; extern std::vector<std::string> GlobalInfo;
@ -36,20 +35,19 @@ void GameSend(const std::string&Data){
//std::cout << "(Launcher->Game) Bytes sent: " << iSendResult << " : " << Data << std::endl; //std::cout << "(Launcher->Game) Bytes sent: " << iSendResult << " : " << Data << std::endl;
} }
} }
void TCPSendLarge(const std::string&Data); void SendLarge(const std::string&Data);
void TCPSend(const std::string&Data); void TCPSend(const std::string&Data);
void UDPSend(const std::string&Data); void UDPSend(const std::string&Data);
void ServerSend(const std::string&Data, bool Rel){ void ServerSend(const std::string&Data, bool Rel){
if(Terminate || Data.empty())return; if(Terminate || Data.empty())return;
char C = 0; char C = 0;
bool Ack = false;
if(Data.length() > 3)C = Data.at(0); if(Data.length() > 3)C = Data.at(0);
if (C == 'O' || C == 'T')Rel = true; if (C == 'O' || C == 'T')Ack = true;
if(Ack || Rel){
if(Rel){ if(Ack || Data.length() > 1000)SendLarge(Data);
if(Data.length() > 1000 || Data.substr(0,2) == "Od")TCPSendLarge(Data);
else TCPSend(Data); else TCPSend(Data);
} }else UDPSend(Data);
else UDPSend(Data);
if (MPDEV && Data.length() > 1000) { if (MPDEV && Data.length() > 1000) {
std::cout << "(Launcher->Server) Bytes sent: " << Data.length() std::cout << "(Launcher->Server) Bytes sent: " << Data.length()

View File

@ -6,16 +6,29 @@
#include <WS2tcpip.h> #include <WS2tcpip.h>
#include <iostream> #include <iostream>
#include <thread> #include <thread>
#include <set>
#include <string> #include <string>
#include <array>
#include <set>
extern bool Terminate; extern bool Terminate;
extern int ClientID; extern int ClientID;
extern bool MPDEV; extern bool MPDEV;
SOCKET UDPSock; SOCKET UDPSock;
sockaddr_in ToServer{}; sockaddr_in ToServer{};
struct PacketData{
int ID;
std::string Data;
int Tries;
};
std::set<std::pair<int,std::string>> BigDataAcks; struct SplitData{
int Total;
int ID;
std::set<std::pair<int,std::string>> Fragments;
};
std::set<SplitData*> SplitPackets;
std::set<PacketData*> BigDataAcks;
void UDPSend(const std::string&Data){ void UDPSend(const std::string&Data){
if(ClientID == -1 || UDPSock == INVALID_SOCKET)return; if(ClientID == -1 || UDPSock == INVALID_SOCKET)return;
std::string Packet = char(ClientID+1) + std::string(":") + Data; std::string Packet = char(ClientID+1) + std::string(":") + Data;
@ -25,42 +38,132 @@ void UDPSend(const std::string&Data){
void LOOP(){ void LOOP(){
while(UDPSock != -1) { while(UDPSock != -1) {
for (const std::pair<int, std::string>& a : BigDataAcks) { for (PacketData* p : BigDataAcks) {
UDPSend(a.second); if(p->Tries < 20){
p->Tries++;
UDPSend(p->Data);
}else{
BigDataAcks.erase(p);
break;
} }
std::this_thread::sleep_for(std::chrono::seconds(2)); }
std::this_thread::sleep_for(std::chrono::milliseconds(200));
} }
} }
void AckID(int ID){ void AckID(int ID){
for(const std::pair<int,std::string>& a : BigDataAcks){ for(PacketData* p : BigDataAcks){
if(a.first == ID){ if(p->ID == ID){
BigDataAcks.erase(a); BigDataAcks.erase(p);
break; break;
} }
} }
} }
void TCPSendLarge(const std::string&Data){ int PacktID(){
static int ID = 0; static int ID = -1;
std::string Header = "BD:" + std::to_string(ID) + ":"; if(ID > 999999)ID = 0;
BigDataAcks.insert(std::make_pair(ID,Header+Data));
if(ID > 483647)ID = 0;
else ID++; else ID++;
return ID;
}
int SplitID(){
static int SID = -1;
if(SID > 999999)SID = 0;
else SID++;
return SID;
}
void SendLarge(const std::string&Data){
int ID = PacktID();
std::string Packet;
if(Data.length() > 1000){
std::string pckt = Data;
int S = 1,Split = ceil(float(pckt.length()) / 1000);
int SID = SplitID();
while(pckt.length() > 1000){
Packet = "SC"+std::to_string(S)+"/"+std::to_string(Split)+":"+std::to_string(ID)+"|"+
std::to_string(SID)+":"+pckt.substr(0,1000);
BigDataAcks.insert(new PacketData{ID,Packet,1});
UDPSend(Packet);
pckt = pckt.substr(1000);
S++;
ID = PacktID();
}
Packet = "SC"+std::to_string(S)+"/"+std::to_string(Split)+":"+
std::to_string(ID)+"|"+std::to_string(SID)+":"+pckt;
BigDataAcks.insert(new PacketData{ID,Packet,1});
UDPSend(Packet);
}else{
Packet = "BD:" + std::to_string(ID) + ":" + Data;
BigDataAcks.insert(new PacketData{ID,Packet,1});
UDPSend(Packet);
}
}
std::array<int, 50> HandledIDs;
void IDReset(){
for(int C = 0;C < 50;C++){
HandledIDs.at(C) = -1;
}
}
bool Handled(int ID){
static int Pos = 0;
for(int id : HandledIDs){
if(id == ID)return true;
}
if(Pos > 49)Pos = 0;
HandledIDs.at(Pos) = ID;
Pos++;
return false;
}
SplitData*GetSplit(int SplitID){
for(SplitData* a : SplitPackets){
if(a->ID == SplitID)return a;
}
SplitData* a = new SplitData();
SplitPackets.insert(a);
return a;
} }
void ServerParser(const std::string& Data); void ServerParser(const std::string& Data);
void HandleChunk(const std::string&Data){
int pos1 = Data.find(':')+1,pos2 = Data.find(':',pos1),pos3 = Data.find('/');
int pos4 = Data.find('|');
int Max = stoi(Data.substr(pos3+1,pos1-pos3-2));
int Current = stoi(Data.substr(2,pos3-2));
int ID = stoi(Data.substr(pos1,pos4-pos1));
int SplitID = stoi(Data.substr(pos4+1,pos2-pos4-1));
std::string ack = "ACK:" + Data.substr(pos1,pos4-pos1);
UDPSend(ack);
if(Handled(ID))return;
SplitData* SData = GetSplit(SplitID);
SData->Total = Max;
SData->ID = SplitID;
SData->Fragments.insert(std::make_pair(Current,Data.substr(pos2+1)));
if(SData->Fragments.size() == SData->Total){
std::string ToHandle;
for(const std::pair<int,std::string>& a : SData->Fragments){
ToHandle += a.second;
}
ServerParser(ToHandle);
SplitPackets.erase(SData);
}
}
void UDPParser(const std::string&Packet){ void UDPParser(const std::string&Packet){
if(Packet.substr(0,4) == "ACK:"){ if(Packet.substr(0,4) == "ACK:"){
AckID(stoi(Packet.substr(4))); AckID(stoi(Packet.substr(4)));
if(MPDEV)std::cout << "Got Ack for sending large data" << std::endl; if(MPDEV)std::cout << "Got Ack for data" << std::endl;
return; return;
}else if(Packet.substr(0,3) == "BD:"){ }else if(Packet.substr(0,3) == "BD:"){
int pos = Packet.find(':',4); int pos = Packet.find(':',4);
std::string pckt = "ACK:" + Packet.substr(3,pos-3); int ID = stoi(Packet.substr(3,pos-3));
std::string pckt = "ACK:" + std::to_string(ID);
UDPSend(pckt); UDPSend(pckt);
if(!Handled(ID)) {
pckt = Packet.substr(pos + 1); pckt = Packet.substr(pos + 1);
ServerParser(pckt); ServerParser(pckt);
}
return;
}else if(Packet.substr(0,2) == "SC"){
HandleChunk(Packet);
return; return;
} }
ServerParser(Packet); ServerParser(Packet);
@ -89,7 +192,6 @@ void UDPClientMain(const std::string& IP,int Port){
std::cout << "Can't start Winsock! " << std::endl; std::cout << "Can't start Winsock! " << std::endl;
return; return;
} }
ToServer.sin_family = AF_INET; ToServer.sin_family = AF_INET;
ToServer.sin_port = htons(Port); ToServer.sin_port = htons(Port);
inet_pton(AF_INET, IP.c_str(), &ToServer.sin_addr); inet_pton(AF_INET, IP.c_str(), &ToServer.sin_addr);
@ -97,12 +199,10 @@ void UDPClientMain(const std::string& IP,int Port){
BigDataAcks.clear(); BigDataAcks.clear();
std::thread Ack(LOOP); std::thread Ack(LOOP);
Ack.detach(); Ack.detach();
IDReset();
TCPSend("P"); TCPSend("P");
UDPSend("p"); UDPSend("p");
while (!Terminate){ while(!Terminate)UDPRcv();
UDPRcv();
}
closesocket(UDPSock); closesocket(UDPSock);
WSACleanup(); WSACleanup();
} }

View File

@ -4,7 +4,6 @@
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
#include <string>
#include <WS2tcpip.h> #include <WS2tcpip.h>
#include <thread> #include <thread>
@ -58,7 +57,7 @@ void TCPRcv(){
ServerParser(std::string(buf)); ServerParser(std::string(buf));
} }
void GameSend(const std::string&Data);
void SyncResources(SOCKET TCPSock); void SyncResources(SOCKET TCPSock);
void TCPClientMain(const std::string& IP,int Port){ void TCPClientMain(const std::string& IP,int Port){
WSADATA wsaData; WSADATA wsaData;
@ -89,11 +88,9 @@ void TCPClientMain(const std::string& IP,int Port){
getsockname(TCPSock, (SOCKADDR *)&ServerAddr, (int *)sizeof(ServerAddr)); getsockname(TCPSock, (SOCKADDR *)&ServerAddr, (int *)sizeof(ServerAddr));
SyncResources(TCPSock); SyncResources(TCPSock);
while(!Terminate){ while(!Terminate)TCPRcv();
TCPRcv(); GameSend("T");
} ////Game Send Terminate
if( shutdown(TCPSock, SD_SEND) != 0 && MPDEV) if( shutdown(TCPSock, SD_SEND) != 0 && MPDEV)
std::cout << "(TCP) shutdown error code: " << WSAGetLastError() << std::endl; std::cout << "(TCP) shutdown error code: " << WSAGetLastError() << std::endl;

View File

@ -126,7 +126,7 @@ int main(int argc, char* argv[]){
std::string GamePath = SData.at(2); std::string GamePath = SData.at(2);
if(MPDEV)std::cout << "You own BeamNG on this machine!" << std::endl; if(MPDEV)std::cout << "You own BeamNG on this machine!" << std::endl;
std::cout << "Game Version : " << CheckVer(GamePath) << std::endl; std::cout << "Game Version : " << CheckVer(GamePath) << std::endl;
std::string ExeDir = "\""+GamePath.substr(0,GamePath.find_last_of('\\')) + R"(\Bin64\BeamNG.drive.x64.exe")"; std::string ExeDir = GamePath.substr(0,GamePath.find_last_of('\\')) + R"(\Bin64\BeamNG.drive.x64.exe)";
std::string Settings = Path + "\\settings\\uiapps-layouts.json"; std::string Settings = Path + "\\settings\\uiapps-layouts.json";
if(stat(Settings.c_str(),&info)!=0){ if(stat(Settings.c_str(),&info)!=0){
link = "https://beamng-mp.com/client-data"; link = "https://beamng-mp.com/client-data";