diff --git a/CMakeLists.txt b/CMakeLists.txt index 95af9f4..c766ad7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,15 +2,11 @@ cmake_minimum_required(VERSION 3.10) project(Launcher) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") -if (WIN32) - message(STATUS "MSVC -> forcing use of statically-linked runtime.") - STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) - STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) -endif() + file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "src/*/*.hpp" "include/*.h" "include/*/*.h" "include/*/*/*.h") add_executable(${PROJECT_NAME} ${source_files}) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "BeamMP-Launcher") -find_package(CURL CONFIG REQUIRED) find_package(ZLIB REQUIRED) +find_package(CURL CONFIG REQUIRED) target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32 rstrtmgr discord-rpc CURL::libcurl ZLIB::ZLIB) target_include_directories(${PROJECT_NAME} PUBLIC $) \ No newline at end of file diff --git a/cmake-build-debug/discord-rpc.lib b/cmake-build-debug/discord-rpc.lib deleted file mode 100644 index 1de29ea..0000000 Binary files a/cmake-build-debug/discord-rpc.lib and /dev/null differ diff --git a/cmake-build-debug/key b/cmake-build-debug/key new file mode 100644 index 0000000..b35affe --- /dev/null +++ b/cmake-build-debug/key @@ -0,0 +1 @@ +4baf8552-5a00-4b18-89e2-d3a9bef18ad0 \ No newline at end of file diff --git a/cmake-build-release/discord-rpc.lib b/cmake-build-release/discord-rpc.lib deleted file mode 100644 index 3730920..0000000 Binary files a/cmake-build-release/discord-rpc.lib and /dev/null differ diff --git a/include/Network/network.h b/include/Network/network.h index 5a0bf60..8bd7d7c 100644 --- a/include/Network/network.h +++ b/include/Network/network.h @@ -8,21 +8,26 @@ extern bool Dev; extern int ping; void CoreNetwork(); extern int ClientID; +extern int LastPort; extern bool ModLoaded; extern bool Terminate; extern int DEFAULT_PORT; extern uint64_t UDPSock; extern uint64_t TCPSock; extern bool TCPTerminate; +extern std::string LastIP; extern std::string MStatus; extern std::string UlStatus; extern std::string PublicKey; extern std::string ListOfMods; int KillSocket(uint64_t Dead); +void UUl(const std::string& R); void UDPSend(std::string Data); +bool CheckBytes(int32_t Bytes); void GameSend(std::string Data); void SendLarge(std::string Data); std::string TCPRcv(uint64_t Sock); +void SyncResources(uint64_t TCPSock); std::string GetAddr(const std::string&IP); void ServerParser(const std::string& Data); std::string Login(const std::string& fields); diff --git a/src/Network/Core.cpp b/src/Network/Core.cpp index 6060943..fa812dd 100644 --- a/src/Network/Core.cpp +++ b/src/Network/Core.cpp @@ -29,14 +29,14 @@ int ping = -1; void StartSync(const std::string &Data){ std::string IP = GetAddr(Data.substr(1,Data.find(':')-1)); if(IP.find('.') == -1){ - if(IP == "DNS")UlStatus = Sec("UlConnection Failed! (DNS Lookup Failed)"); - else UlStatus = Sec("UlConnection Failed! (WSA failed to start)"); + if(IP == "DNS")UlStatus ="UlConnection Failed! (DNS Lookup Failed)"; + else UlStatus = "UlConnection Failed! (WSA failed to start)"; ListOfMods = "-"; Terminate = true; return; } CheckLocalKey(); - UlStatus = Sec("UlLoading..."); + UlStatus = "UlLoading..."; TCPTerminate = false; Terminate = false; ConfList->clear(); @@ -56,7 +56,7 @@ void Parse(std::string Data,SOCKET CSocket){ NetReset(); Terminate = true; TCPTerminate = true; - Data = Code + HTTP_REQUEST(Sec("https://beammp.com/servers-info"),443); + Data = Code + HTTP_REQUEST("https://beammp.com/servers-info",443); break; case 'C': ListOfMods.clear(); @@ -137,7 +137,7 @@ void GameHandler(SOCKET Client){ Temp = recv(Client,&Header[Rcv],1,0); if(Temp < 1)break; if(!isdigit(Header[Rcv]) && Header[Rcv] != '>') { - error(Sec("(Core) Invalid lua communication")); + error("(Core) Invalid lua communication"); KillSocket(Client); return; } diff --git a/src/Network/GlobalHandler.cpp b/src/Network/GlobalHandler.cpp index f025ff0..9363727 100644 --- a/src/Network/GlobalHandler.cpp +++ b/src/Network/GlobalHandler.cpp @@ -169,9 +169,6 @@ void ParserAsync(const std::string& Data){ char Code = Data.at(0),SubCode = 0; if(Data.length() > 1)SubCode = Data.at(1); switch (Code) { - case 'P': - ClientID = std::stoi(Data.substr(1)); - break; case 'p': PingEnd = std::chrono::high_resolution_clock::now(); if(PingStart > PingEnd)ping = 0; diff --git a/src/Network/Resources.cpp b/src/Network/Resources.cpp index 84bd546..16755fa 100644 --- a/src/Network/Resources.cpp +++ b/src/Network/Resources.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace fs = std::experimental::filesystem; std::string ListOfMods; @@ -34,8 +35,8 @@ std::vector Split(const std::string& String,const std::string& deli void CheckForDir(){ struct stat info{}; - if(stat( Sec("Resources"), &info) != 0){ - _wmkdir(SecW(L"Resources")); + if(stat( "Resources", &info) != 0){ + _wmkdir(L"Resources"); } } void WaitForConfirm(){ @@ -66,11 +67,19 @@ std::string Auth(SOCKET Sock){ if(Terminate)return ""; Res = TCPRcv(Sock); - if(Res.empty() || Res[0] == 'E' || Res != "WS"){ + if(Res.empty() || Res[0] != 'P'){ Abord(); return ""; } + Res = Res.substr(1); + if(Res.find_first_not_of("0123456789") == std::string::npos){ + ClientID = std::stoi(Res); + }else{ + Abord(); + UUl("Authentication failed!"); + return ""; + } TCPSend("SR",Sock); if(Terminate)return ""; @@ -91,11 +100,117 @@ std::string Auth(SOCKET Sock){ return Res; } +void UpdateUl(bool D,const std::string&msg){ + if(D)UlStatus = "UlDownloading Resource: " + msg; + else UlStatus = "UlLoading Resource: " + msg; +} + +void AsyncUpdate(uint64_t& Rcv,uint64_t Size,const std::string& Name){ + do { + double pr = Rcv / double(Size) * 100; + std::string Per = std::to_string(trunc(pr * 10) / 10); + UpdateUl(true, Name + " (" + Per.substr(0, Per.find('.') + 2) + "%)"); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + }while(!Terminate && Rcv < Size); +} + +std::string TCPRcvRaw(SOCKET Sock,uint64_t& GRcv, uint64_t Size){ + if(Sock == -1){ + Terminate = true; + UUl("Invalid Socket"); + return ""; + } + char* File = new char[Size]; + uint64_t Rcv = 0; + int32_t Temp; + do{ + int Len = int(Size-Rcv); + if(Len > 1000000)Len = 1000000; + Temp = recv(Sock, &File[Rcv], Len, MSG_WAITALL); + if(Temp < 1){ + info(std::to_string(Temp)); + UUl("Socket Closed Code 1"); + KillSocket(Sock); + Terminate = true; + delete[] File; + return ""; + } + Rcv += Temp; + GRcv += Temp; + }while(Rcv < Size && !Terminate); + std::string Ret = std::string(File,Size); + delete[] File; + return Ret; +} +void MultiKill(SOCKET Sock,SOCKET Sock1){ + KillSocket(Sock1); + KillSocket(Sock); + Terminate = true; +} +SOCKET InitDSock(){ + SOCKET DSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + SOCKADDR_IN ServerAddr; + if(DSock < 1){ + Terminate = true; + return 0; + } + ServerAddr.sin_family = AF_INET; + ServerAddr.sin_port = htons(LastPort); + inet_pton(AF_INET, LastIP.c_str(), &ServerAddr.sin_addr); + if(connect(DSock, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr)) != 0){ + KillSocket(DSock); + Terminate = true; + return 0; + } + char Code[2] = {'D',char(ClientID)}; + if(send(DSock,Code,2,0) != 2){ + KillSocket(DSock); + Terminate = true; + return 0; + } + return DSock; +} + +std::string MultiDownload(SOCKET MSock,SOCKET DSock, uint64_t Size, const std::string& Name){ + + uint64_t GRcv = 0, MSize = Size/2, DSize = Size - MSize; + + std::thread Au(AsyncUpdate,std::ref(GRcv),Size,Name); + Au.detach(); + + std::packaged_task task([&] { return TCPRcvRaw(MSock,GRcv,MSize); }); + std::future f1 = task.get_future(); + std::thread Dt(std::move(task)); + Dt.detach(); + + std::string Ret = TCPRcvRaw(DSock,GRcv,DSize); + + if(Ret.empty()){ + MultiKill(MSock,DSock); + return ""; + } + + f1.wait(); + std::string Temp = f1.get(); + + if(Temp.empty()){ + MultiKill(MSock,DSock); + return ""; + } + if(Au.joinable())Au.join(); + + + Ret += Temp; + return Ret; +} + + void SyncResources(SOCKET Sock){ std::string Ret = Auth(Sock); if(Ret.empty())return; - info(Sec("Checking Resources...")); + info("Checking Resources..."); CheckForDir(); std::vector list = Split(Ret, ";"); @@ -103,6 +218,7 @@ void SyncResources(SOCKET Sock){ std::vector FSizes(list.begin() + (list.size() / 2), list.end()); list.clear(); Ret.clear(); + int Amount = 0,Pos = 0; std::string a,t; for(const std::string&name : FNames){ @@ -118,23 +234,23 @@ void SyncResources(SOCKET Sock){ if (pos == std::string::npos)continue; Amount++; } - if(!FNames.empty())info(Sec("Syncing...")); + if(!FNames.empty())info("Syncing..."); for(auto FN = FNames.begin(),FS = FSizes.begin(); FN != FNames.end() && !Terminate; ++FN,++FS) { auto pos = FN->find_last_of('/'); if (pos != std::string::npos) { - a = Sec("Resources") + FN->substr(pos); + a = "Resources" + FN->substr(pos); } else continue; Pos++; if (fs::exists(a)) { if (FS->find_first_not_of("0123456789") != std::string::npos)continue; if (fs::file_size(a) == std::stoi(*FS)){ - UlStatus = Sec("UlLoading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) + - "): " + a.substr(a.find_last_of('/')); + UpdateUl(false,"(" + std::to_string(Pos) + "/" + std::to_string(Amount) + "): " + a.substr(a.find_last_of('/'))); std::this_thread::sleep_for(std::chrono::milliseconds(50)); try { - fs::copy_file(a, Sec("BeamNG/mods") + a.substr(a.find_last_of('/')), + fs::copy_file(a, "BeamNG/mods" + a.substr(a.find_last_of('/')), fs::copy_options::overwrite_existing); - } catch (...) { + } catch (std::exception& e) { + error("Failed copy to the mods folder! " + std::string(e.what())); Terminate = true; continue; } @@ -143,40 +259,36 @@ void SyncResources(SOCKET Sock){ }else remove(a.c_str()); } CheckForDir(); + std::string FName = a.substr(a.find_last_of('/')); + SOCKET DSock = InitDSock(); do { TCPSend("f" + *FN,Sock); - int Recv = 0,Size = std::stoi(*FS); - char*File = new char[Size]; - ZeroMemory(File,Size); - do { - auto Data = TCPRcv(Sock); - size_t BytesRcv = Data.size(); - if (Data == "Cannot Open" || Terminate)break; - memcpy_s(File+Recv,BytesRcv,&Data[0],BytesRcv); - Recv += int(BytesRcv); - float per = float(Recv)/std::stof(*FS) * 100; - std::string Percent = std::to_string(truncf(per * 10) / 10); - UlStatus = Sec("UlDownloading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) + - "): " + a.substr(a.find_last_of('/')) + " (" + - Percent.substr(0, Percent.find('.') + 2) + "%)"; - } while (Recv != Size && Recv < Size && !Terminate); + + std::string Data = TCPRcv(Sock); + if (Data == "CO" || Terminate){ + Terminate = true; + UUl("Server cannot find " + FName); + break; + } + + std::string Name = "(" + std::to_string(Pos) + "/" + std::to_string(Amount) + "): " + FName; + + Data = MultiDownload(Sock,DSock,std::stoull(*FS), Name); + if(Terminate)break; - UlStatus = Sec("UlLoading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) + - "): " + a.substr(a.find_last_of('/')); + UpdateUl(false,"("+std::to_string(Pos)+"/"+std::to_string(Amount)+"): "+FName); std::ofstream LFS; LFS.open(a.c_str(), std::ios_base::app | std::ios::binary); if (LFS.is_open()) { - LFS.write(File, Recv); + LFS.write(Data.c_str(), Data.size()); LFS.close(); } - delete[] File; + }while(fs::file_size(a) != std::stoi(*FS) && !Terminate); - if(!Terminate)fs::copy_file(a,Sec("BeamNG/mods")+a.substr(a.find_last_of('/')), fs::copy_options::overwrite_existing); + KillSocket(DSock); + if(!Terminate)fs::copy_file(a,"BeamNG/mods"+FName, fs::copy_options::overwrite_existing); WaitForConfirm(); } - FNames.clear(); - FSizes.clear(); - a.clear(); if(!Terminate){ TCPSend("Done",Sock); info("Done!"); diff --git a/src/Network/VehicleData.cpp b/src/Network/VehicleData.cpp index 6aba019..010caea 100644 --- a/src/Network/VehicleData.cpp +++ b/src/Network/VehicleData.cpp @@ -60,9 +60,8 @@ void UDPClientMain(const std::string& IP,int Port){ ToServer->sin_port = htons(Port); inet_pton(AF_INET, IP.c_str(), &ToServer->sin_addr); UDPSock = socket(AF_INET, SOCK_DGRAM, 0); - - TCPSend("P",TCPSock); - UDPSend(Sec("p")); + TCPSend("H",TCPSock); + UDPSend("p"); while(!Terminate)UDPRcv(); KillSocket(UDPSock); WSACleanup(); diff --git a/src/Network/VehicleEvent.cpp b/src/Network/VehicleEvent.cpp index ebe34b4..590e462 100644 --- a/src/Network/VehicleEvent.cpp +++ b/src/Network/VehicleEvent.cpp @@ -11,7 +11,11 @@ #include "Security/Enc.h" #include "Network/network.h" + +int LastPort; +std::string LastIP; SOCKET TCPSock = -1; + bool CheckBytes(int32_t Bytes){ if (Bytes == 0){ debug("(TCP) Connection closing... CheckBytes(16)"); @@ -25,14 +29,14 @@ bool CheckBytes(int32_t Bytes){ } return true; } -void UpdateUl(const std::string& R){ +void UUl(const std::string& R){ UlStatus = "UlDisconnected: " + R; } void TCPSend(const std::string&Data,uint64_t Sock){ if(Sock == -1){ Terminate = true; - UpdateUl("Invalid Socket"); + UUl("Invalid Socket"); return; } @@ -47,12 +51,12 @@ void TCPSend(const std::string&Data,uint64_t Sock){ do{ if (size_t(Sent) >= Send.size()) { error("string OOB in " + std::string(__func__)); - UpdateUl("TCP Send OOB"); + UUl("TCP Send OOB"); return; } Temp = send(Sock, &Send[Sent], Size - Sent, 0); if(!CheckBytes(Temp)){ - UpdateUl("Socket Closed"); + UUl("Socket Closed Code 2"); return; } Sent += Temp; @@ -62,7 +66,7 @@ void TCPSend(const std::string&Data,uint64_t Sock){ std::string TCPRcv(SOCKET Sock){ if(Sock == -1){ Terminate = true; - UpdateUl("Invalid Socket"); + UUl("Invalid Socket"); return ""; } int32_t Header,BytesRcv = 0,Temp; @@ -70,7 +74,7 @@ std::string TCPRcv(SOCKET Sock){ do{ Temp = recv(Sock,&Data[BytesRcv],4-BytesRcv,0); if(!CheckBytes(Temp)){ - UpdateUl("Socket Closed"); + UUl("Socket Closed Code 3"); return ""; } BytesRcv += Temp; @@ -78,7 +82,7 @@ std::string TCPRcv(SOCKET Sock){ memcpy(&Header,&Data[0],sizeof(Header)); if(!CheckBytes(BytesRcv)){ - UpdateUl("Socket Closed"); + UUl("Socket Closed Code 4"); return ""; } Data.resize(Header); @@ -86,7 +90,7 @@ std::string TCPRcv(SOCKET Sock){ do{ Temp = recv(Sock,&Data[BytesRcv],Header-BytesRcv,0); if(!CheckBytes(Temp)){ - UpdateUl("Socket Closed"); + UUl("Socket Closed Code 5"); return ""; } BytesRcv += Temp; @@ -101,13 +105,13 @@ std::string TCPRcv(SOCKET Sock){ #ifdef DEBUG //debug("Parsing from server -> " + std::to_string(Ret.size())); #endif - if(Ret[0] == 'E')UpdateUl(Ret.substr(1)); + if(Ret[0] == 'E')UUl(Ret.substr(1)); return Ret; } - -void SyncResources(SOCKET TCPSock); void TCPClientMain(const std::string& IP,int Port){ + LastIP = IP; + LastPort = Port; WSADATA wsaData; SOCKADDR_IN ServerAddr; int RetCode; @@ -124,24 +128,25 @@ void TCPClientMain(const std::string& IP,int Port){ inet_pton(AF_INET, IP.c_str(), &ServerAddr.sin_addr); RetCode = connect(TCPSock, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr)); if(RetCode != 0){ - UlStatus = Sec("UlConnection Failed!"); - std::cout << Sec("Client: connect failed! Error code: ") << WSAGetLastError() << std::endl; + UlStatus = "UlConnection Failed!"; + std::cout << "Client: connect failed! Error code: " << WSAGetLastError() << std::endl; KillSocket(TCPSock); WSACleanup(); Terminate = true; return; } getsockname(TCPSock, (SOCKADDR *)&ServerAddr, (int *)sizeof(ServerAddr)); - + char Code = 'C'; + send(TCPSock,&Code,1,0); SyncResources(TCPSock); while(!Terminate){ ServerParser(TCPRcv(TCPSock)); } - GameSend(Sec("T")); + GameSend("T"); ////Game Send Terminate if(KillSocket(TCPSock) != 0) - debug(Sec("(TCP) Cannot close socket. Error code: ") + std::to_string(WSAGetLastError())); + debug("(TCP) Cannot close socket. Error code: " + std::to_string(WSAGetLastError())); if(WSACleanup() != 0) - debug(Sec("(TCP) Client: WSACleanup() failed!...")); + debug("(TCP) Client: WSACleanup() failed!..."); } diff --git a/src/Startup.cpp b/src/Startup.cpp index 616ac09..ef50628 100644 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -19,7 +19,7 @@ std::string GetEN(){ return "BeamMP-Launcher.exe"; } std::string GetVer(){ - return "1.71"; + return "1.72"; } std::string GetPatch(){ return "";