This commit is contained in:
Lion Kortlepel
2024-06-17 22:01:15 +02:00
parent 3488136ca4
commit a82b9fb36f
21 changed files with 1085 additions and 1017 deletions

View File

@@ -11,139 +11,149 @@
#include <ws2tcpip.h>
#elif defined(__linux__)
#include "linuxfixes.h"
#include <arpa/inet.h>
#include <cstring>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <cstring>
#endif
#include "Logger.h"
#include <charconv>
#include <mutex>
#include <string>
#include <thread>
#include <mutex>
std::chrono::time_point<std::chrono::high_resolution_clock> PingStart,PingEnd;
std::chrono::time_point<std::chrono::high_resolution_clock> PingStart, PingEnd;
bool GConnected = false;
bool CServer = true;
SOCKET CSocket = -1;
SOCKET GSocket = -1;
int KillSocket(uint64_t Dead){
if(Dead == (SOCKET)-1){
int KillSocket(uint64_t Dead) {
if (Dead == (SOCKET)-1) {
debug("Kill socket got -1 returning...");
return 0;
}
shutdown(Dead,SD_BOTH);
shutdown(Dead, SD_BOTH);
int a = closesocket(Dead);
if(a != 0){
if (a != 0) {
warn("Failed to close socket!");
}
return a;
}
bool CheckBytes(uint32_t Bytes){
if(Bytes == 0){
bool CheckBytes(uint32_t Bytes) {
if (Bytes == 0) {
debug("(Proxy) Connection closing");
return false;
}else if(Bytes < 0){
} else if (Bytes < 0) {
debug("(Proxy) send failed with error: " + std::to_string(WSAGetLastError()));
return false;
}
return true;
}
void GameSend(std::string Data){
void GameSend(std::string Data) {
static std::mutex Lock;
std::scoped_lock Guard(Lock);
if(TCPTerminate || !GConnected || CSocket == -1)return;
int32_t Size,Temp,Sent;
if (TCPTerminate || !GConnected || CSocket == -1)
return;
int32_t Size, Temp, Sent;
Data += '\n';
Size = int32_t(Data.size());
Sent = 0;
#ifdef DEBUG
if(Size > 1000){
debug("Launcher -> game (" +std::to_string(Size)+")");
}
#endif
do{
if(Sent > -1){
#ifdef DEBUG
if (Size > 1000) {
debug("Launcher -> game (" + std::to_string(Size) + ")");
}
#endif
do {
if (Sent > -1) {
Temp = send(CSocket, &Data[Sent], Size - Sent, 0);
}
if(!CheckBytes(Temp))return;
}
if (!CheckBytes(Temp))
return;
Sent += Temp;
}while(Sent < Size);
} while (Sent < Size);
}
void ServerSend(std::string Data, bool Rel){
if(Terminate || Data.empty())return;
if(Data.find("Zp") != std::string::npos && Data.size() > 500){
void ServerSend(std::string Data, bool Rel) {
if (Terminate || Data.empty())
return;
if (Data.find("Zp") != std::string::npos && Data.size() > 500) {
abort();
}
char C = 0;
bool Ack = false;
int DLen = int(Data.length());
if(DLen > 3)C = Data.at(0);
if (C == 'O' || C == 'T')Ack = true;
if(C == 'N' || C == 'W' || C == 'Y' || C == 'V' || C == 'E' || C == 'C')Rel = true;
if(Ack || Rel){
if(Ack || DLen > 1000)SendLarge(Data);
else TCPSend(Data,TCPSock);
}else UDPSend(Data);
if (DLen > 3)
C = Data.at(0);
if (C == 'O' || C == 'T')
Ack = true;
if (C == 'N' || C == 'W' || C == 'Y' || C == 'V' || C == 'E' || C == 'C')
Rel = true;
if (Ack || Rel) {
if (Ack || DLen > 1000)
SendLarge(Data);
else
TCPSend(Data, TCPSock);
} else
UDPSend(Data);
if (DLen > 1000) {
debug("(Launcher->Server) Bytes sent: " + std::to_string(Data.length()) + " : "
+ Data.substr(0, 10)
+ Data.substr(Data.length() - 10));
}else if(C == 'Z'){
//debug("(Game->Launcher) : " + Data);
+ Data.substr(0, 10)
+ Data.substr(Data.length() - 10));
} else if (C == 'Z') {
// debug("(Game->Launcher) : " + Data);
}
}
void NetReset(){
void NetReset() {
TCPTerminate = false;
GConnected = false;
Terminate = false;
UlStatus = "Ulstart";
MStatus = " ";
if(UDPSock != (SOCKET)(-1)){
if (UDPSock != (SOCKET)(-1)) {
debug("Terminating UDP Socket : " + std::to_string(TCPSock));
KillSocket(UDPSock);
}
UDPSock = -1;
if(TCPSock != (SOCKET)(-1)){
if (TCPSock != (SOCKET)(-1)) {
debug("Terminating TCP Socket : " + std::to_string(TCPSock));
KillSocket(TCPSock);
}
TCPSock = -1;
if(GSocket != (SOCKET)(-1)){
if (GSocket != (SOCKET)(-1)) {
debug("Terminating GTCP Socket : " + std::to_string(GSocket));
KillSocket(GSocket);
}
GSocket = -1;
}
SOCKET SetupListener(){
if(GSocket != -1)return GSocket;
struct addrinfo *result = nullptr;
struct addrinfo hints{};
SOCKET SetupListener() {
if (GSocket != -1)
return GSocket;
struct addrinfo* result = nullptr;
struct addrinfo hints { };
int iRes;
#ifdef _WIN32
#ifdef _WIN32
WSADATA wsaData;
iRes = WSAStartup(514, &wsaData); //2.2
iRes = WSAStartup(514, &wsaData); // 2.2
if (iRes != 0) {
error("(Proxy) WSAStartup failed with error: " + std::to_string(iRes));
return -1;
}
#endif
#endif
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
iRes = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT+1).c_str(), &hints, &result);
iRes = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT + 1).c_str(), &hints, &result);
if (iRes != 0) {
error("(Proxy) info failed with error: " + std::to_string(iRes));
WSACleanup();
@@ -155,7 +165,7 @@ SOCKET SetupListener(){
WSACleanup();
return -1;
}
iRes = bind(GSocket, result->ai_addr, (int) result->ai_addrlen);
iRes = bind(GSocket, result->ai_addr, (int)result->ai_addrlen);
if (iRes == SOCKET_ERROR) {
error("(Proxy) bind failed with error: " + std::to_string(WSAGetLastError()));
freeaddrinfo(result);
@@ -173,57 +183,61 @@ SOCKET SetupListener(){
}
return GSocket;
}
void AutoPing(){
while(!Terminate){
ServerSend("p",false);
void AutoPing() {
while (!Terminate) {
ServerSend("p", false);
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));
}
}
int ClientID = -1;
void ParserAsync(const std::string& Data){
if(Data.empty())return;
char Code = Data.at(0),SubCode = 0;
if(Data.length() > 1)SubCode = Data.at(1);
void ParserAsync(const std::string& Data) {
if (Data.empty())
return;
char Code = Data.at(0), SubCode = 0;
if (Data.length() > 1)
SubCode = Data.at(1);
switch (Code) {
case 'p':
PingEnd = std::chrono::high_resolution_clock::now();
if(PingStart > PingEnd)ping = 0;
else ping = int(std::chrono::duration_cast<std::chrono::milliseconds>(PingEnd-PingStart).count());
return;
case 'M':
MStatus = Data;
UlStatus = "Uldone";
return;
default:
break;
case 'p':
PingEnd = std::chrono::high_resolution_clock::now();
if (PingStart > PingEnd)
ping = 0;
else
ping = int(std::chrono::duration_cast<std::chrono::milliseconds>(PingEnd - PingStart).count());
return;
case 'M':
MStatus = Data;
UlStatus = "Uldone";
return;
default:
break;
}
GameSend(Data);
}
void ServerParser(const std::string& Data){
void ServerParser(const std::string& Data) {
ParserAsync(Data);
}
void NetMain(const std::string& IP, int Port){
void NetMain(const std::string& IP, int Port) {
std::thread Ping(AutoPing);
Ping.detach();
UDPClientMain(IP,Port);
UDPClientMain(IP, Port);
CServer = true;
Terminate = true;
info("Connection Terminated!");
}
void TCPGameServer(const std::string& IP, int Port){
void TCPGameServer(const std::string& IP, int Port) {
GSocket = SetupListener();
while (!TCPTerminate && GSocket != -1){
while (!TCPTerminate && GSocket != -1) {
debug("MAIN LOOP OF GAME SERVER");
GConnected = false;
if(!CServer){
if (!CServer) {
warn("Connection still alive terminating");
NetReset();
TCPTerminate = true;
Terminate = true;
break;
}
if(CServer) {
if (CServer) {
std::thread Client(TCPClientMain, IP, Port);
Client.detach();
}
@@ -234,45 +248,52 @@ void TCPGameServer(const std::string& IP, int Port){
}
debug("(Proxy) Game Connected!");
GConnected = true;
if(CServer){
if (CServer) {
std::thread t1(NetMain, IP, Port);
t1.detach();
CServer = false;
}
int32_t Size,Temp,Rcv;
char Header[10] = {0};
int32_t Size, Temp, Rcv;
char Header[10] = { 0 };
//Read byte by byte until '>' is rcved then get the size and read based on it
do{
// Read byte by byte until '>' is rcved then get the size and read based on it
do {
Rcv = 0;
do{
Temp = recv(CSocket,&Header[Rcv],1,0);
if(Temp < 1 || TCPTerminate)break;
}while(Header[Rcv++] != '>');
if(Temp < 1 || TCPTerminate)break;
if(std::from_chars(Header,&Header[Rcv],Size).ptr[0] != '>'){
debug("(Game) Invalid lua Header -> " + std::string(Header,Rcv));
do {
Temp = recv(CSocket, &Header[Rcv], 1, 0);
if (Temp < 1 || TCPTerminate)
break;
} while (Header[Rcv++] != '>');
if (Temp < 1 || TCPTerminate)
break;
if (std::from_chars(Header, &Header[Rcv], Size).ptr[0] != '>') {
debug("(Game) Invalid lua Header -> " + std::string(Header, Rcv));
break;
}
std::string Ret(Size,0);
std::string Ret(Size, 0);
Rcv = 0;
do{
Temp = recv(CSocket,&Ret[Rcv],Size-Rcv,0);
if(Temp < 1)break;
do {
Temp = recv(CSocket, &Ret[Rcv], Size - Rcv, 0);
if (Temp < 1)
break;
Rcv += Temp;
}while(Rcv < Size && !TCPTerminate);
if(Temp < 1 || TCPTerminate)break;
} while (Rcv < Size && !TCPTerminate);
if (Temp < 1 || TCPTerminate)
break;
ServerSend(Ret,false);
ServerSend(Ret, false);
}while(Temp > 0 && !TCPTerminate);
if(Temp == 0)debug("(Proxy) Connection closing");
else debug("(Proxy) recv failed error : " + std::to_string(WSAGetLastError()));
} while (Temp > 0 && !TCPTerminate);
if (Temp == 0)
debug("(Proxy) Connection closing");
else
debug("(Proxy) recv failed error : " + std::to_string(WSAGetLastError()));
}
TCPTerminate = true;
GConnected = false;
Terminate = true;
if(CSocket != SOCKET_ERROR)KillSocket(CSocket);
if (CSocket != SOCKET_ERROR)
KillSocket(CSocket);
debug("END OF GAME SERVER");
}