Proxy Rewrite, fixed some crashes

This commit is contained in:
Anonymous275 2020-05-04 01:16:50 +03:00
parent 1b013fb9eb
commit 93299f0fa4
4 changed files with 78 additions and 106 deletions

View File

@ -13,7 +13,7 @@ extern bool TCPTerminate;
extern bool MPDEV; extern bool MPDEV;
void Print(const std::string&MSG); void Print(const std::string&MSG);
std::queue<std::string> VNTCPQueue; std::queue<std::string> VNTCPQueue;
void RUDPSEND(const std::string&Data); void RUDPSEND(const std::string&Data,bool Rel);
#define DEFAULT_PORT "4446" #define DEFAULT_PORT "4446"
void Responder(const SOCKET *CS){ void Responder(const SOCKET *CS){
@ -135,7 +135,7 @@ void VehicleNetworkStart(){
std::cout << "Fail!" << std::endl; std::cout << "Fail!" << std::endl;
} }
} }
RUDPSEND(buff); RUDPSEND(buff,false);
//std::cout << "(Game->Launcher VN) Data : " << buff.length() << std::endl; //std::cout << "(Game->Launcher VN) Data : " << buff.length() << std::endl;
} else if (iResult == 0) { } else if (iResult == 0) {
if(MPDEV)std::cout << "(VN) Connection closing...\n"; if(MPDEV)std::cout << "(VN) Connection closing...\n";

View File

@ -3172,13 +3172,14 @@ int enet_host_check_events(ENetHost *host, ENetEvent *event) {
* @remarks enet_host_service should be called fairly regularly for adequate performance * @remarks enet_host_service should be called fairly regularly for adequate performance
* @ingroup host * @ingroup host
*/ */
int enet_host_service(ENetHost *host, ENetEvent *event, enet_uint32 timeout) { int enet_host_service(ENetHost *host, ENetEvent *event, enet_uint32 timeout) {
enet_uint32 waitCondition; enet_uint32 waitCondition;
if (event != NULL) { if (event != nullptr) {
event->type = ENET_EVENT_TYPE_NONE; event->type = ENET_EVENT_TYPE_NONE;
event->peer = NULL; event->peer = nullptr;
event->packet = NULL; event->packet = nullptr;
switch (enet_protocol_dispatch_incoming_commands(host, event)) { switch (enet_protocol_dispatch_incoming_commands(host, event)) {
case 1: case 1:
@ -3197,6 +3198,7 @@ int enet_host_service(ENetHost *host, ENetEvent *event, enet_uint32 timeout) {
} }
host->serviceTime = enet_time_get(); host->serviceTime = enet_time_get();
auto Start = std::chrono::high_resolution_clock::now();
timeout += host->serviceTime; timeout += host->serviceTime;
do { do {
@ -3249,7 +3251,7 @@ int enet_host_service(ENetHost *host, ENetEvent *event, enet_uint32 timeout) {
break; break;
} }
if (event != NULL) { if (event != nullptr) {
switch (enet_protocol_dispatch_incoming_commands(host, event)) { switch (enet_protocol_dispatch_incoming_commands(host, event)) {
case 1: case 1:
return 1; return 1;
@ -3266,19 +3268,13 @@ int enet_host_service(ENetHost *host, ENetEvent *event, enet_uint32 timeout) {
} }
} }
if (ENET_TIME_GREATER_EQUAL(host->serviceTime, timeout)) {
return 0;
}
do { do {
auto end = std::chrono::high_resolution_clock::now();
int D = std::chrono::duration_cast<std::chrono::microseconds>(Start - end).count();
if (D > timeout)return 0;
host->serviceTime = enet_time_get(); host->serviceTime = enet_time_get();
if (ENET_TIME_GREATER_EQUAL(host->serviceTime, timeout)) {
return 0;
}
waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT; waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT;
if (enet_socket_wait(host->socket, &waitCondition, ENET_TIME_DIFFERENCE(timeout, host->serviceTime)) != 0) { if (enet_socket_wait(host->socket, &waitCondition, timeout-D > 0)) {
return -1; return -1;
} }
} while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT); } while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT);

View File

@ -85,7 +85,7 @@ int main(int argc, char* argv[]){
const unsigned long long NPos = std::string::npos; const unsigned long long NPos = std::string::npos;
struct stat info{}; struct stat info{};
std::string ver = "0.901", Path = CheckDir(argv[0],ver),HTTP_Result; std::string ver = "0.91", Path = CheckDir(argv[0],ver),HTTP_Result;
CheckForUpdates(ver); CheckForUpdates(ver);
if(argc > 1){ if(argc > 1){
std::string Port = argv[1]; std::string Port = argv[1];

152
proxy.cpp
View File

@ -13,55 +13,76 @@
#include <queue> #include <queue>
int DEFAULT_PORT = 4445; int DEFAULT_PORT = 4445;
typedef struct { typedef struct {
ENetHost *host; ENetHost *host;
ENetPeer *peer; ENetPeer *peer;
} Client; } Client;
std::vector<std::string> Split(const std::string& String,const std::string& delimiter); std::vector<std::string> Split(const std::string& String,const std::string& delimiter);
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;
std::condition_variable RUDPLOCK,TCPLOCK;
std::queue<std::string> RUDPToSend;
std::queue<std::string> RUDPData; /////QUEUE WAS 196 SLOW?! NEED TO FIX
bool TCPTerminate = false; bool TCPTerminate = false;
bool Terminate = false; bool Terminate = false;
bool CServer = true; bool CServer = true;
ENetPeer*ServerPeer;
SOCKET*ClientSocket;
int ping = 0; int ping = 0;
extern bool MPDEV; extern bool MPDEV;
[[noreturn]] void CoreNetworkThread(); [[noreturn]] void CoreNetworkThread();
void TCPSEND(const std::string&Data){ void TCPSEND(const std::string&Data){
RUDPData.push(Data); if(!TCPTerminate) {
TCPLOCK.notify_all(); int iSendResult = send(*ClientSocket, (Data + "\n").c_str(), int(Data.length()) + 1, 0);
if (iSendResult == SOCKET_ERROR) {
if (MPDEV)std::cout << "(Proxy) send failed with error: " << WSAGetLastError() << std::endl;
TCPTerminate = true;
} else {
if (MPDEV && iSendResult > 1000) {
std::cout << "(Launcher->Game) Bytes sent: " << iSendResult << " : " << Data.substr(0, 10)
<< Data.substr(Data.length() - 10) << std::endl;
}
//std::cout << "(Launcher->Game) Bytes sent: " << iSendResult << " : " << RUDPData.front()<< std::endl;
}
}
} }
void RUDPSEND(const std::string&Data){ void RUDPSEND(const std::string&Data,bool Rel){
RUDPToSend.push(Data); if(!Terminate && ServerPeer != nullptr){
RUDPLOCK.notify_all(); char C = 0;
if(Data.length() > 3)C = Data.at(0);
if (C == 'O' || C == 'T')Rel = true;
enet_peer_send(ServerPeer, 0, enet_packet_create(Data.c_str(), Data.length()+1, Rel?1:8));
if (MPDEV && Data.length() > 1000) {
std::cout << "(Launcher->Server) Bytes sent: " << Data.length()
<< " : "
<< Data.substr(0, 10)
<< Data.substr(Data.length() - 10) << std::endl;
}
}
} }
void NameRespond(){
std::string Packet = "NR" + GlobalInfo.at(0)+":"+GlobalInfo.at(2);
RUDPSEND(Packet,true);
}
void AutoPing(ENetPeer*peer){ void AutoPing(ENetPeer*peer){
while(!Terminate && peer != nullptr){ while(!Terminate && peer != nullptr){
enet_peer_send(peer, 0, enet_packet_create("p", 2, ENET_PACKET_FLAG_RELIABLE)); RUDPSEND("p",true);
PingStart = std::chrono::high_resolution_clock::now(); PingStart = std::chrono::high_resolution_clock::now();
std::this_thread::sleep_for(std::chrono::seconds (1)); std::this_thread::sleep_for(std::chrono::seconds (1));
} }
} }
void NameRespond(ENetPeer*peer){
std::string Packet = "NR" + GlobalInfo.at(0)+":"+GlobalInfo.at(2);
enet_peer_send(peer, 0, enet_packet_create(Packet.c_str(), Packet.length()+1, ENET_PACKET_FLAG_RELIABLE));
}
void RUDPParser(const std::string& Data,ENetPeer*peer){ void RUDPParser(const std::string& Data){
char Code = Data.at(0),SubCode = 0; char Code = Data.at(0),SubCode = 0;
if(Data.length() > 1)SubCode = Data.at(1); if(Data.length() > 1)SubCode = Data.at(1);
switch (Code) { switch (Code) {
case 'p': case 'p':
PingEnd = std::chrono::high_resolution_clock::now(); PingEnd = std::chrono::high_resolution_clock::now();
ping = std::chrono::duration_cast<std::chrono::milliseconds>(PingEnd-PingStart).count(); ping = int(std::chrono::duration_cast<std::chrono::microseconds>(PingEnd-PingStart).count())/1000;
return; return;
case 'N': case 'N':
if(SubCode == 'R')NameRespond(peer); if(SubCode == 'R')NameRespond();
return; return;
} }
///std::cout << "Received: " << Data << std::endl; ///std::cout << "Received: " << Data << std::endl;
@ -76,7 +97,7 @@ void HandleEvent(ENetEvent event,Client client){
event.peer->data = (void*)"Connected Server"; event.peer->data = (void*)"Connected Server";
break; break;
case ENET_EVENT_TYPE_RECEIVE: case ENET_EVENT_TYPE_RECEIVE:
RUDPParser((char*)event.packet->data,event.peer); RUDPParser((char*)event.packet->data);
enet_packet_destroy(event.packet); enet_packet_destroy(event.packet);
break; break;
case ENET_EVENT_TYPE_DISCONNECT: case ENET_EVENT_TYPE_DISCONNECT:
@ -97,6 +118,7 @@ void HandleEvent(ENetEvent event,Client client){
} }
} }
void RUDPClientThread(const std::string& IP, int Port){ void RUDPClientThread(const std::string& IP, int Port){
std::condition_variable lock;
if (enet_initialize() != 0) { if (enet_initialize() != 0) {
std::cout << "An error occurred while initializing!\n"; std::cout << "An error occurred while initializing!\n";
} }
@ -112,36 +134,18 @@ void RUDPClientThread(const std::string& IP, int Port){
client.peer = enet_host_connect(client.host, &address, 2, 0); client.peer = enet_host_connect(client.host, &address, 2, 0);
if (client.peer == nullptr) { if (client.peer == nullptr) {
if(MPDEV)std::cout << "could not connect\n"; if(MPDEV)std::cout << "could not connect\n";
TCPSEND("TTimeout");
TCPTerminate = true;
Terminate = true;
} }
ServerPeer = client.peer;
std::thread Ping(AutoPing,client.peer); std::thread Ping(AutoPing,client.peer);
Ping.detach(); Ping.detach();
ENetEvent event; ENetEvent event;
do { while (!Terminate) {
enet_host_service(client.host, &event, 0); enet_host_service(client.host, &event, 1);
HandleEvent(event,client); HandleEvent(event,client);
while (!RUDPToSend.empty()){
if(RUDPToSend.front().length() > 3) {
int Rel = 8;
char C = RUDPToSend.front().at(0);
if (C == 'O' || C == 'T')Rel = 1;
ENetPacket *packet = enet_packet_create(RUDPToSend.front().c_str(),
RUDPToSend.front().length() + 1,
Rel);
enet_peer_send(client.peer, 0, packet);
if (RUDPToSend.front().length() > 1000) {
if(MPDEV){std::cout << "(Launcher->Server) Bytes sent: " << RUDPToSend.front().length() << " : "
<< RUDPToSend.front().substr(0, 10)
<< RUDPToSend.front().substr(RUDPToSend.front().length() - 10) << std::endl;}
} }
}
RUDPToSend.pop();
}
std::mutex Lock;
std::unique_lock<std::mutex> lk(Lock);
std::chrono::high_resolution_clock::time_point tp = std::chrono::high_resolution_clock::now() + std::chrono::nanoseconds (1);
RUDPLOCK.wait_until(lk, tp, [](){return !RUDPToSend.empty();});
} while (!Terminate);
enet_peer_disconnect(client.peer,0); enet_peer_disconnect(client.peer,0);
enet_host_service(client.host, &event, 0); enet_host_service(client.host, &event, 0);
HandleEvent(event,client); HandleEvent(event,client);
@ -149,33 +153,6 @@ void RUDPClientThread(const std::string& IP, int Port){
std::cout << "Connection Terminated!" << std::endl; std::cout << "Connection Terminated!" << std::endl;
} }
void TCPRespond(const SOCKET *CS){
SOCKET ClientSocket = *CS;
int iSendResult;
while(!TCPTerminate){
while (!RUDPData.empty()) {
std::string Data = RUDPData.front() + "\n";
iSendResult = send(ClientSocket, Data.c_str(), Data.length(), 0);
if (iSendResult == SOCKET_ERROR) {
if(MPDEV)std::cout << "(Proxy) send failed with error: " << WSAGetLastError() << std::endl;
TCPTerminate = true;
break;
} else {
if(iSendResult > 1000){
std::cout << "(Launcher->Game) Bytes sent: " << iSendResult << " : " << RUDPData.front().substr(0,10)
<< RUDPData.front().substr(RUDPData.front().length()-10) << std::endl;
}
//std::cout << "(Launcher->Game) Bytes sent: " << iSendResult << " : " << RUDPData.front()<< std::endl;
RUDPData.pop();
}
}
std::mutex Lock;
std::unique_lock<std::mutex> lk(Lock);
std::chrono::high_resolution_clock::time_point tp = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(1);
TCPLOCK.wait_until(lk, tp, [](){return !RUDPData.empty();});
}
}
std::string Compress(const std::string&Data); std::string Compress(const std::string&Data);
std::string Decompress(const std::string&Data); std::string Decompress(const std::string&Data);
void TCPServerThread(const std::string& IP, int Port){ void TCPServerThread(const std::string& IP, int Port){
@ -185,7 +162,7 @@ void TCPServerThread(const std::string& IP, int Port){
WSADATA wsaData; WSADATA wsaData;
int iResult; int iResult;
SOCKET ListenSocket = INVALID_SOCKET; SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET; SOCKET Socket = INVALID_SOCKET;
struct addrinfo *result = nullptr; struct addrinfo *result = nullptr;
struct addrinfo hints{}; struct addrinfo hints{};
@ -196,7 +173,6 @@ void TCPServerThread(const std::string& IP, int Port){
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) { if (iResult != 0) {
if(MPDEV)std::cout << "(Proxy) WSAStartup failed with error: " << iResult << std::endl; if(MPDEV)std::cout << "(Proxy) WSAStartup failed with error: " << iResult << std::endl;
std::cin.get();
exit(-1); exit(-1);
} }
@ -241,8 +217,8 @@ void TCPServerThread(const std::string& IP, int Port){
WSACleanup(); WSACleanup();
continue; continue;
} }
ClientSocket = accept(ListenSocket, NULL, NULL); Socket = accept(ListenSocket, nullptr, nullptr);
if (ClientSocket == INVALID_SOCKET) { if (Socket == INVALID_SOCKET) {
if(MPDEV)std::cout << "(Proxy) accept failed with error: " << WSAGetLastError() << std::endl; if(MPDEV)std::cout << "(Proxy) accept failed with error: " << WSAGetLastError() << std::endl;
closesocket(ListenSocket); closesocket(ListenSocket);
WSACleanup(); WSACleanup();
@ -255,17 +231,16 @@ void TCPServerThread(const std::string& IP, int Port){
t1.detach(); t1.detach();
CServer = false; CServer = false;
} }
std::thread TCPSend(TCPRespond,&ClientSocket); ClientSocket = &Socket;
TCPSend.detach();
do { do {
//std::cout << "(Proxy) Waiting for Game Data..." << std::endl; //std::cout << "(Proxy) Waiting for Game Data..." << std::endl;
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); iResult = recv(Socket, recvbuf, recvbuflen, 0);
if (iResult > 0) { if (iResult > 0) {
std::string buff; std::string buff;
buff.resize(iResult*2); buff.resize(iResult*2);
memcpy(&buff[0],recvbuf,iResult); memcpy(&buff[0],recvbuf,iResult);
buff.resize(iResult); buff.resize(iResult);
if(MPDEV && buff.length() > 1000) { /*if(MPDEV && buff.length() > 1000) {
std::string cmp = Compress(buff), dcm = Decompress(cmp); std::string cmp = Compress(buff), dcm = Decompress(cmp);
std::cout << "Compressed Size : " << cmp.length() << std::endl; std::cout << "Compressed Size : " << cmp.length() << std::endl;
std::cout << "Decompressed Size : " << dcm.length() << std::endl; std::cout << "Decompressed Size : " << dcm.length() << std::endl;
@ -274,31 +249,31 @@ void TCPServerThread(const std::string& IP, int Port){
} else { } else {
std::cout << "Fail!" << std::endl; std::cout << "Fail!" << std::endl;
} }
} }*/
RUDPSEND(buff); RUDPSEND(buff,false);
//std::cout << "(Game->Launcher) Data : " << buff.length() << std::endl; //std::cout << "(Game->Launcher) Data : " << buff.length() << std::endl;
} else if (iResult == 0) { } else if (iResult == 0) {
if(MPDEV)std::cout << "(Proxy) Connection closing...\n"; if(MPDEV)std::cout << "(Proxy) Connection closing...\n";
closesocket(ClientSocket); closesocket(Socket);
WSACleanup(); WSACleanup();
continue; continue;
} else { } else {
if(MPDEV)std::cout << "(Proxy) recv failed with error: " << WSAGetLastError() << std::endl; if(MPDEV)std::cout << "(Proxy) recv failed with error: " << WSAGetLastError() << std::endl;
closesocket(ClientSocket); closesocket(Socket);
WSACleanup(); WSACleanup();
continue; continue;
} }
} while (iResult > 0); } while (iResult > 0);
iResult = shutdown(ClientSocket, SD_SEND); iResult = shutdown(Socket, SD_SEND);
if (iResult == SOCKET_ERROR) { if (iResult == SOCKET_ERROR) {
if(MPDEV)std::cout << "(Proxy) shutdown failed with error: " << WSAGetLastError() << std::endl; if(MPDEV)std::cout << "(Proxy) shutdown failed with error: " << WSAGetLastError() << std::endl;
closesocket(ClientSocket); closesocket(Socket);
WSACleanup(); WSACleanup();
continue; continue;
} }
closesocket(ClientSocket); closesocket(Socket);
WSACleanup(); WSACleanup();
}while (!TCPTerminate); }while (!TCPTerminate);
} }
@ -310,12 +285,13 @@ void ProxyStart(){
if(MPDEV)std::cout << "Core Network Started!\n"; if(MPDEV)std::cout << "Core Network Started!\n";
t1.join(); t1.join();
} }
void Reset(){ void Reset() {
Terminate = false; ClientSocket = nullptr;
ServerPeer = nullptr;
TCPTerminate = false; TCPTerminate = false;
while(!RUDPToSend.empty()) RUDPToSend.pop(); Terminate = false;
while(!RUDPData.empty()) RUDPData.pop();
} }
void ProxyThread(const std::string& IP, int Port){ void ProxyThread(const std::string& IP, int Port){
Reset(); Reset();
std::thread t1(TCPServerThread,IP,Port); std::thread t1(TCPServerThread,IP,Port);