Fix Console on Unix, adapt console behavior to that of a traditional

console, add Assert.h, add clang-format file with modified WebKit style
This commit is contained in:
Lion Kortlepel 2020-11-03 09:00:42 +01:00
parent 13e79e407c
commit eead954bf9
7 changed files with 306 additions and 178 deletions

5
.clang-format Normal file
View File

@ -0,0 +1,5 @@
---
BasedOnStyle: WebKit
BreakBeforeBraces: Attach
...

59
include/Assert.h Normal file
View File

@ -0,0 +1,59 @@
// Author: lionkor
#pragma once
#include <cstdio>
#include <cstdlib>
#include "Logger.h"
static const char* const ANSI_RESET = "\u001b[0m";
static const char* const ANSI_BLACK = "\u001b[30m";
static const char* const ANSI_RED = "\u001b[31m";
static const char* const ANSI_GREEN = "\u001b[32m";
static const char* const ANSI_YELLOW = "\u001b[33m";
static const char* const ANSI_BLUE = "\u001b[34m";
static const char* const ANSI_MAGENTA = "\u001b[35m";
static const char* const ANSI_CYAN = "\u001b[36m";
static const char* const ANSI_WHITE = "\u001b[37m";
static const char* const ANSI_BLACK_BOLD = "\u001b[30;1m";
static const char* const ANSI_RED_BOLD = "\u001b[31;1m";
static const char* const ANSI_GREEN_BOLD = "\u001b[32;1m";
static const char* const ANSI_YELLOW_BOLD = "\u001b[33;1m";
static const char* const ANSI_BLUE_BOLD = "\u001b[34;1m";
static const char* const ANSI_MAGENTA_BOLD = "\u001b[35;1m";
static const char* const ANSI_CYAN_BOLD = "\u001b[36;1m";
static const char* const ANSI_WHITE_BOLD = "\u001b[37;1m";
static const char* const ANSI_BOLD = "\u001b[1m";
static const char* const ANSI_UNDERLINE = "\u001b[4m";
inline void _assert(const char* file, const char* function, unsigned line,
const char* condition_string, bool result) {
if (!result) {
#if DEBUG
fprintf(stderr,
"%sASSERTION FAILED%s at %s%s:%u%s \n\t-> in %s%s%s, Line %u: \n\t\t-> "
"Failed Condition: %s%s%s\n",
ANSI_RED_BOLD, ANSI_RESET, ANSI_UNDERLINE, file, line, ANSI_RESET,
ANSI_BOLD, function, ANSI_RESET, line, ANSI_RED, condition_string,
ANSI_RESET);
fprintf(stderr, "%s... terminating with SIGABRT ...%s\n", ANSI_BOLD, ANSI_RESET);
abort();
#else
char buf[2048];
sprintf(buf,
"%s=> ASSERTION `%s` FAILED IN RELEASE BUILD%s%s -> IGNORING FAILED ASSERTION "
"& HOPING IT WON'T CRASH%s\n",
ANSI_RED_BOLD, condition_string, ANSI_RESET, ANSI_RED, ANSI_RESET);
error(buf);
#endif
}
}
#ifndef ASSERT
#define Assert(cond) _assert(__FILE__, __func__, __LINE__, #cond, (cond))
#endif // ASSERT
#define AssertNotReachable() _assert(__FILE__, __func__, __LINE__, "reached unreachable code", false)

View File

@ -3,12 +3,13 @@
/// ///
#pragma once #pragma once
#include <mutex> #include <mutex>
#include "Assert.h"
class Client; class Client;
void GParser(Client*c, const std::string&Packet); void GParser(Client*c, const std::string&Packet);
class Buffer{ class Buffer{
public: public:
void Handle(Client*c,const std::string& Data){ void Handle(Client*c,const std::string& Data){
if(c == nullptr)return; Assert(c);
Buf += Data; Buf += Data;
Manage(c); Manage(c);
} }
@ -18,6 +19,7 @@ public:
private: private:
std::string Buf; std::string Buf;
void Manage(Client*c){ void Manage(Client*c){
Assert(c);
if(!Buf.empty()){ if(!Buf.empty()){
std::string::size_type p; std::string::size_type p;
if (Buf.at(0) == '\n'){ if (Buf.at(0) == '\n'){

View File

@ -8,6 +8,8 @@
#include <conio.h> #include <conio.h>
#else // *nix #else // *nix
typedef unsigned long DWORD, *PDWORD, *LPDWORD; typedef unsigned long DWORD, *PDWORD, *LPDWORD;
#include <termios.h>
#include <unistd.h>
#endif // __WIN32 #endif // __WIN32
#include "Logger.h" #include "Logger.h"
#include <iostream> #include <iostream>
@ -20,6 +22,7 @@ std::string CInputBuff;
std::mutex MLock; std::mutex MLock;
Lua* LuaConsole; Lua* LuaConsole;
void HandleInput(const std::string& cmd){ void HandleInput(const std::string& cmd){
std::cout << std::endl;
if (cmd == "exit") { if (cmd == "exit") {
exit(0); exit(0);
}else LuaConsole->Execute(cmd); }else LuaConsole->Execute(cmd);
@ -28,13 +31,12 @@ void HandleInput(const std::string& cmd){
void ProcessOut(){ void ProcessOut(){
static size_t len = 2; static size_t len = 2;
if(QConsoleOut.empty() && len == CInputBuff.length())return; if(QConsoleOut.empty() && len == CInputBuff.length())return;
printf("%c[2K\r", 27);
for(const std::string& msg : QConsoleOut) for(const std::string& msg : QConsoleOut)
if(!msg.empty())std::cout << msg; if(!msg.empty())std::cout << msg;
MLock.lock(); MLock.lock();
QConsoleOut.clear(); QConsoleOut.clear();
MLock.unlock(); MLock.unlock();
std::cout << "> " << CInputBuff; std::cout << "> " << CInputBuff << std::flush;
len = CInputBuff.length(); len = CInputBuff.length();
} }
@ -50,6 +52,32 @@ void ConsoleOut(const std::string& msg){
ProcessOut(); ProcessOut();
} }
} }
#ifndef __WIN32
static int _getch()
{
char buf = 0;
struct termios old;
fflush(stdout);
if(tcgetattr(0, &old) < 0)
perror("tcsetattr()");
old.c_lflag &= ~unsigned(ICANON);
old.c_lflag &= ~unsigned(ECHO);
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if(tcsetattr(0, TCSANOW, &old) < 0)
perror("tcsetattr ICANON");
if(read(0, &buf, 1) < 0)
perror("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if(tcsetattr(0, TCSADRAIN, &old) < 0)
perror("tcsetattr ~ICANON");
// no echo printf("%c\n", buf);
return buf;
}
#endif // __WIN32
void SetupConsole(){ void SetupConsole(){
#ifdef __WIN32 #ifdef __WIN32
DWORD outMode = 0; DWORD outMode = 0;
@ -71,19 +99,28 @@ void SetupConsole(){
std::this_thread::sleep_for(std::chrono::seconds(3)); std::this_thread::sleep_for(std::chrono::seconds(3));
exit(GetLastError()); exit(GetLastError());
} }
#else
#endif // __WIN32 #endif // __WIN32
} }
[[noreturn]] void ReadCin(){ [[noreturn]] void ReadCin(){
while (true){ while (true){
int In = getchar(); int In = _getch();
if (In == 13) { if (In == 13 || In == '\n') {
if(!CInputBuff.empty()) { if(!CInputBuff.empty()) {
HandleInput(CInputBuff); HandleInput(CInputBuff);
CInputBuff.clear(); CInputBuff.clear();
} }
}else if(In == 8){ }else if(In == 8){
if(!CInputBuff.empty())CInputBuff.pop_back(); if(!CInputBuff.empty())CInputBuff.pop_back();
}else CInputBuff += char(In); } else if (In == 4) {
CInputBuff = "exit";
HandleInput(CInputBuff);
CInputBuff.clear();
}else {
printf("%c[2K\r", 27);
CInputBuff += char(In);
}
} }
} }
void ConsoleInit(){ void ConsoleInit(){

View File

@ -163,7 +163,7 @@ void GlobalParser(Client*c, const std::string& Pack){
} }
switch (Code) { switch (Code) {
case 'P': case 'P': // initial connection
Respond(c, Sec("P") + std::to_string(c->GetID()),true); Respond(c, Sec("P") + std::to_string(c->GetID()),true);
SyncClient(c); SyncClient(c);
return; return;

View File

@ -1,10 +1,10 @@
/// ///
/// Created by Anonymous275 on 8/1/2020 /// Created by Anonymous275 on 8/1/2020
/// ///
#include "Security/Enc.h"
#include "Client.hpp" #include "Client.hpp"
#include "Settings.h"
#include "Logger.h" #include "Logger.h"
#include "Security/Enc.h"
#include "Settings.h"
#include "UnixCompat.h" #include "UnixCompat.h"
#include <fstream> #include <fstream>
@ -13,22 +13,25 @@
#include <sys/stat.h> #include <sys/stat.h>
#endif // __linux #endif // __linux
void STCPSend(Client*c,std::string Data){ void STCPSend(Client* c, std::string Data) {
if(c == nullptr)return; if (c == nullptr)
return;
ssize_t BytesSent = send(c->GetTCPSock(), Data.c_str(), size_t(Data.size()), 0); ssize_t BytesSent = send(c->GetTCPSock(), Data.c_str(), size_t(Data.size()), 0);
Data.clear(); Data.clear();
if (BytesSent == 0){ if (BytesSent == 0) {
if(c->GetStatus() > -1)c->SetStatus(-1); if (c->GetStatus() > -1)
}else if (BytesSent < 0) { c->SetStatus(-1);
if(c->GetStatus() > -1)c->SetStatus(-1); } else if (BytesSent < 0) {
if (c->GetStatus() > -1)
c->SetStatus(-1);
closesocket(c->GetTCPSock()); closesocket(c->GetTCPSock());
} }
} }
void SendFile(Client*c,const std::string&Name){ void SendFile(Client* c, const std::string& Name) {
info(c->GetName()+Sec(" requesting : ")+Name.substr(Name.find_last_of('/'))); info(c->GetName() + Sec(" requesting : ") + Name.substr(Name.find_last_of('/')));
struct stat Info{}; struct stat Info {};
if(stat(Name.c_str(), &Info) != 0){ if (stat(Name.c_str(), &Info) != 0) {
STCPSend(c,Sec("Cannot Open")); STCPSend(c, Sec("Cannot Open"));
return; return;
} }
std::ifstream f(Name.c_str(), std::ios::binary); std::ifstream f(Name.c_str(), std::ios::binary);
@ -38,72 +41,81 @@ void SendFile(Client*c,const std::string&Name){
size_t Sent = 0; size_t Sent = 0;
size_t Diff; size_t Diff;
ssize_t Split = 64000; ssize_t Split = 64000;
while(c->GetStatus() > -1 && Sent < Size){ while (c->GetStatus() > -1 && Sent < Size) {
Diff = Size - Sent; Diff = Size - Sent;
if(Diff > size_t(Split)){ if (Diff > size_t(Split)) {
std::string Data(size_t(Split),0); std::string Data(size_t(Split), 0);
f.seekg(ssize_t(Sent), std::ios_base::beg); f.seekg(ssize_t(Sent), std::ios_base::beg);
f.read(&Data[0], Split); f.read(&Data[0], Split);
STCPSend(c,Data); STCPSend(c, Data);
Sent += size_t(Split); Sent += size_t(Split);
}else{ } else {
std::string Data(Diff,0); std::string Data(Diff, 0);
f.seekg(ssize_t(Sent), std::ios_base::beg); f.seekg(ssize_t(Sent), std::ios_base::beg);
f.read(&Data[0], ssize_t(Diff)); f.read(&Data[0], ssize_t(Diff));
STCPSend(c,Data); STCPSend(c, Data);
Sent += Diff; Sent += Diff;
} }
} }
f.close(); f.close();
} }
void Parse(Client*c,const std::string&Packet){ void Parse(Client* c, const std::string& Packet) {
if(c == nullptr || Packet.empty())return; if (c == nullptr || Packet.empty())
char Code = Packet.at(0),SubCode = 0; return;
if(Packet.length() > 1)SubCode = Packet.at(1); char Code = Packet.at(0), SubCode = 0;
if (Packet.length() > 1)
SubCode = Packet.at(1);
switch (Code) { switch (Code) {
case 'f': case 'f':
SendFile(c,Packet.substr(1)); SendFile(c, Packet.substr(1));
return; return;
case 'S': case 'S':
if(SubCode == 'R'){ if (SubCode == 'R') {
debug(Sec("Sending Mod Info")); debug(Sec("Sending Mod Info"));
std::string ToSend = FileList+FileSizes; std::string ToSend = FileList + FileSizes;
if(ToSend.empty())ToSend = "-"; if (ToSend.empty())
STCPSend(c,ToSend); ToSend = "-";
} STCPSend(c, ToSend);
return; }
default: return;
return; default:
return;
} }
} }
bool STCPRecv(Client*c){ bool STCPRecv(Client* c) {
if(c == nullptr)return false; if (c == nullptr)
return false;
char buf[200]; char buf[200];
size_t len = 200; size_t len = 200;
ZeroMemory(buf, len); ZeroMemory(buf, len);
ssize_t BytesRcv = recv(c->GetTCPSock(), buf, len,0); ssize_t BytesRcv = recv(c->GetTCPSock(), buf, len, 0);
if (BytesRcv == 0){ if (BytesRcv == 0) {
if(c->GetStatus() > -1)c->SetStatus(-1); if (c->GetStatus() > -1)
c->SetStatus(-1);
closesocket(c->GetTCPSock()); closesocket(c->GetTCPSock());
return false; return false;
}else if (BytesRcv < 0) { } else if (BytesRcv < 0) {
if(c->GetStatus() > -1)c->SetStatus(-1); if (c->GetStatus() > -1)
c->SetStatus(-1);
closesocket(c->GetTCPSock()); closesocket(c->GetTCPSock());
return false; return false;
} }
if(strcmp(buf,"Done") == 0)return false; if (strcmp(buf, "Done") == 0)
return false;
std::string Ret(buf, size_t(BytesRcv)); std::string Ret(buf, size_t(BytesRcv));
Parse(c,Ret); Parse(c, Ret);
return true; return true;
} }
void SyncResources(Client*c){ void SyncResources(Client* c) {
if(c == nullptr)return; if (c == nullptr)
try{ return;
STCPSend(c,Sec("WS")); try {
while(c->GetStatus() > -1 && STCPRecv(c)); STCPSend(c, Sec("WS"));
}catch (std::exception& e){ while (c->GetStatus() > -1 && STCPRecv(c))
;
} catch (std::exception& e) {
except(Sec("Exception! : ") + std::string(e.what())); except(Sec("Exception! : ") + std::string(e.what()));
c->SetStatus(-1); c->SetStatus(-1);
} }

View File

@ -2,147 +2,155 @@
/// Created by Anonymous275 on 5/8/2020 /// Created by Anonymous275 on 5/8/2020
/// ///
///UDP ///UDP
#include "Security/Enc.h"
#include "Compressor.h"
#include "Client.hpp" #include "Client.hpp"
#include "Settings.h" #include "Compressor.h"
#include "Network.h"
#include "Logger.h" #include "Logger.h"
#include "Network.h"
#include "Security/Enc.h"
#include "Settings.h"
#include "UnixCompat.h" #include "UnixCompat.h"
#include <sstream>
#include <vector>
#include <thread>
#include <array> #include <array>
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
int FC(const std::string& s,const std::string& p,int n); #include <sstream>
struct PacketData{ #include <thread>
#include <vector>
int FC(const std::string& s, const std::string& p, int n);
struct PacketData {
int ID; int ID;
::Client* Client; ::Client* Client;
std::string Data; std::string Data;
int Tries; int Tries;
}; };
struct SplitData{ struct SplitData {
int Total{}; int Total {};
int ID{}; int ID {};
std::set<std::pair<int,std::string>> Fragments; std::set<std::pair<int, std::string>> Fragments;
}; };
SOCKET UDPSock; SOCKET UDPSock;
std::set<PacketData*> DataAcks; std::set<PacketData*> DataAcks;
std::set<SplitData*> SplitPackets; std::set<SplitData*> SplitPackets;
void UDPSend(Client*c,std::string Data){ void UDPSend(Client* c, std::string Data) {
if(c == nullptr || !c->isConnected || c->GetStatus() < 0)return; if (c == nullptr || !c->isConnected || c->GetStatus() < 0)
return;
sockaddr_in Addr = c->GetUDPAddr(); sockaddr_in Addr = c->GetUDPAddr();
socklen_t AddrSize = sizeof(c->GetUDPAddr()); socklen_t AddrSize = sizeof(c->GetUDPAddr());
Data = Data.substr(0,Data.find(char(0))); Data = Data.substr(0, Data.find(char(0)));
if(Data.length() > 400){ if (Data.length() > 400) {
std::string CMP(Comp(Data)); std::string CMP(Comp(Data));
Data = "ABG:" + CMP; Data = "ABG:" + CMP;
} }
ssize_t sendOk = sendto(UDPSock, Data.c_str(), Data.size(), 0, (sockaddr *) &Addr, AddrSize); ssize_t sendOk = sendto(UDPSock, Data.c_str(), Data.size(), 0, (sockaddr*)&Addr, AddrSize);
#ifdef __WIN32 #ifdef __WIN32
if (sendOk != 0) { if (sendOk != 0) {
debug(Sec("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError())); debug(Sec("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError()));
if(c->GetStatus() > -1)c->SetStatus(-1); if (c->GetStatus() > -1)
c->SetStatus(-1);
} }
#else // unix #else // unix
if (sendOk != 0) { if (sendOk != 0) {
debug(Sec("(UDP) Send Failed Code : ") + std::string(strerror(errno))); debug(Sec("(UDP) Send Failed Code : ") + std::string(strerror(errno)));
if(c->GetStatus() > -1)c->SetStatus(-1); if (c->GetStatus() > -1)
c->SetStatus(-1);
} }
#endif // __WIN32 #endif // __WIN32
} }
void AckID(int ID){ void AckID(int ID) {
for(PacketData* p : DataAcks){ for (PacketData* p : DataAcks) {
if(p != nullptr && p->ID == ID){ if (p != nullptr && p->ID == ID) {
DataAcks.erase(p); DataAcks.erase(p);
break; break;
} }
} }
} }
int PacktID(){ int PacktID() {
static int ID = -1; static int ID = -1;
if(ID > 999999)ID = 0; if (ID > 999999)
else ID++; ID = 0;
else
ID++;
return ID; return ID;
} }
int SplitID(){ int SplitID() {
static int SID = -1; static int SID = -1;
if(SID > 999999)SID = 0; if (SID > 999999)
else SID++; SID = 0;
else
SID++;
return SID; return SID;
} }
void SendLarge(Client*c,std::string Data){ void SendLarge(Client* c, std::string Data) {
Data = Data.substr(0,Data.find(char(0))); Data = Data.substr(0, Data.find(char(0)));
int ID = PacktID(); int ID = PacktID();
std::string Packet; std::string Packet;
if(Data.length() > 1000){ if (Data.length() > 1000) {
std::string pckt = Data; std::string pckt = Data;
int S = 1,Split = int(ceil(float(pckt.length()) / 1000)); int S = 1, Split = int(ceil(float(pckt.length()) / 1000));
int SID = SplitID(); int SID = SplitID();
while(pckt.length() > 1000){ while (pckt.length() > 1000) {
Packet = "SC|"+std::to_string(S)+"|"+std::to_string(Split)+"|"+std::to_string(ID)+"|"+ Packet = "SC|" + std::to_string(S) + "|" + std::to_string(Split) + "|" + std::to_string(ID) + "|" + std::to_string(SID) + "|" + pckt.substr(0, 1000);
std::to_string(SID)+"|"+pckt.substr(0,1000); DataAcks.insert(new PacketData { ID, c, Packet, 1 });
DataAcks.insert(new PacketData{ID,c,Packet,1}); UDPSend(c, Packet);
UDPSend(c,Packet);
pckt = pckt.substr(1000); pckt = pckt.substr(1000);
S++; S++;
ID = PacktID(); ID = PacktID();
} }
Packet = "SC|"+std::to_string(S)+"|"+std::to_string(Split)+"|"+ Packet = "SC|" + std::to_string(S) + "|" + std::to_string(Split) + "|" + std::to_string(ID) + "|" + std::to_string(SID) + "|" + pckt;
std::to_string(ID)+"|"+std::to_string(SID)+"|"+pckt; DataAcks.insert(new PacketData { ID, c, Packet, 1 });
DataAcks.insert(new PacketData{ID,c,Packet,1}); UDPSend(c, Packet);
UDPSend(c,Packet); } else {
}else{
Packet = "BD:" + std::to_string(ID) + ":" + Data; Packet = "BD:" + std::to_string(ID) + ":" + Data;
DataAcks.insert(new PacketData{ID,c,Packet,1}); DataAcks.insert(new PacketData { ID, c, Packet, 1 });
UDPSend(c,Packet); UDPSend(c, Packet);
} }
} }
struct HandledC{ struct HandledC {
size_t Pos = 0; size_t Pos = 0;
Client *c = nullptr; Client* c = nullptr;
std::array<int, 100> HandledIDs = {-1}; std::array<int, 100> HandledIDs = { -1 };
}; };
std::set<HandledC*> HandledIDs; std::set<HandledC*> HandledIDs;
void ResetIDs(HandledC*H){ void ResetIDs(HandledC* H) {
for(size_t C = 0;C < 100;C++){ for (size_t C = 0; C < 100; C++) {
H->HandledIDs.at(C) = -1; H->HandledIDs.at(C) = -1;
} }
} }
HandledC*GetHandled(Client*c){ HandledC* GetHandled(Client* c) {
for(HandledC*h : HandledIDs){ for (HandledC* h : HandledIDs) {
if(h->c == c){ if (h->c == c) {
return h; return h;
} }
} }
return new HandledC(); return new HandledC();
} }
bool Handled(Client*c,int ID){ bool Handled(Client* c, int ID) {
bool handle = false; bool handle = false;
for(HandledC*h : HandledIDs){ for (HandledC* h : HandledIDs) {
if(h->c == c){ if (h->c == c) {
for(int id : h->HandledIDs){ for (int id : h->HandledIDs) {
if(id == ID)return true; if (id == ID)
return true;
} }
if(h->Pos > 99)h->Pos = 0; if (h->Pos > 99)
h->Pos = 0;
h->HandledIDs.at(h->Pos) = ID; h->HandledIDs.at(h->Pos) = ID;
h->Pos++; h->Pos++;
handle = true; handle = true;
} }
} }
for(HandledC*h : HandledIDs){ for (HandledC* h : HandledIDs) {
if(h->c == nullptr || !h->c->isConnected){ if (h->c == nullptr || !h->c->isConnected) {
HandledIDs.erase(h); HandledIDs.erase(h);
break; break;
} }
} }
if(!handle){ if (!handle) {
HandledC *h = GetHandled(c); HandledC* h = GetHandled(c);
ResetIDs(h); ResetIDs(h);
if (h->Pos > 99)h->Pos = 0; if (h->Pos > 99)
h->Pos = 0;
h->HandledIDs.at(h->Pos) = ID; h->HandledIDs.at(h->Pos) = ID;
h->Pos++; h->Pos++;
h->c = c; h->c = c;
@ -150,12 +158,12 @@ bool Handled(Client*c,int ID){
} }
return false; return false;
} }
std::string UDPRcvFromClient(sockaddr_in& client){ std::string UDPRcvFromClient(sockaddr_in& client) {
size_t clientLength = sizeof(client); size_t clientLength = sizeof(client);
ZeroMemory(&client, clientLength); ZeroMemory(&client, clientLength);
std::string Ret(10240,0); std::string Ret(10240, 0);
ssize_t Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&client, (socklen_t*)&clientLength); ssize_t Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&client, (socklen_t*)&clientLength);
if (Rcv == -1){ if (Rcv == -1) {
#ifdef __WIN32 #ifdef __WIN32
error(Sec("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError())); error(Sec("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError()));
#else // unix #else // unix
@ -166,77 +174,80 @@ std::string UDPRcvFromClient(sockaddr_in& client){
return Ret; return Ret;
} }
SplitData*GetSplit(int SplitID){ SplitData* GetSplit(int SplitID) {
for(SplitData* a : SplitPackets){ for (SplitData* a : SplitPackets) {
if(a->ID == SplitID)return a; if (a->ID == SplitID)
return a;
} }
auto* SP = new SplitData(); auto* SP = new SplitData();
SplitPackets.insert(SP); SplitPackets.insert(SP);
return SP; return SP;
} }
void HandleChunk(Client*c,const std::string&Data){ void HandleChunk(Client* c, const std::string& Data) {
int pos = FC(Data,"|",5); int pos = FC(Data, "|", 5);
if(pos == -1)return; if (pos == -1)
std::stringstream ss(Data.substr(0,size_t(pos++))); return;
std::stringstream ss(Data.substr(0, size_t(pos++)));
std::string t; std::string t;
int I = -1; int I = -1;
//Current Max ID SID //Current Max ID SID
std::vector<int> Num(4,0); std::vector<int> Num(4, 0);
while (std::getline(ss, t, '|')) { while (std::getline(ss, t, '|')) {
if(I >= 0)Num.at(size_t(I)) = std::stoi(t); if (I >= 0)
Num.at(size_t(I)) = std::stoi(t);
I++; I++;
} }
std::string ack = "TRG:" + std::to_string(Num.at(2)); std::string ack = "TRG:" + std::to_string(Num.at(2));
UDPSend(c,ack); UDPSend(c, ack);
if(Handled(c,Num.at(2))){ if (Handled(c, Num.at(2))) {
return; return;
} }
std::string Packet = Data.substr(size_t(pos)); std::string Packet = Data.substr(size_t(pos));
SplitData* SData = GetSplit(Num.at(3)); SplitData* SData = GetSplit(Num.at(3));
SData->Total = Num.at(1); SData->Total = Num.at(1);
SData->ID = Num.at(3); SData->ID = Num.at(3);
SData->Fragments.insert(std::make_pair(Num.at(0),Packet)); SData->Fragments.insert(std::make_pair(Num.at(0), Packet));
if(SData->Fragments.size() == size_t(SData->Total)) { if (SData->Fragments.size() == size_t(SData->Total)) {
std::string ToHandle; std::string ToHandle;
for(const std::pair<int,std::string>& a : SData->Fragments){ for (const std::pair<int, std::string>& a : SData->Fragments) {
ToHandle += a.second; ToHandle += a.second;
} }
GParser(c,ToHandle); GParser(c, ToHandle);
SplitPackets.erase(SData); SplitPackets.erase(SData);
delete SData; delete SData;
SData = nullptr; SData = nullptr;
} }
} }
void UDPParser(Client*c,std::string Packet){ void UDPParser(Client* c, std::string Packet) {
if(Packet.substr(0,4) == "ABG:"){ if (Packet.substr(0, 4) == "ABG:") {
Packet = DeComp(Packet.substr(4)); Packet = DeComp(Packet.substr(4));
} }
if(Packet.substr(0,4) == "TRG:"){ if (Packet.substr(0, 4) == "TRG:") {
std::string pkt = Packet.substr(4); std::string pkt = Packet.substr(4);
if(Packet.find_first_not_of("0123456789") == std::string::npos){ if (Packet.find_first_not_of("0123456789") == std::string::npos) {
AckID(stoi(Packet)); AckID(stoi(Packet));
} }
return; return;
}else if(Packet.substr(0,3) == "BD:"){ } else if (Packet.substr(0, 3) == "BD:") {
auto pos = Packet.find(':',4); auto pos = Packet.find(':', 4);
int ID = stoi(Packet.substr(3,pos-3)); int ID = stoi(Packet.substr(3, pos - 3));
std::string pkt = "TRG:" + std::to_string(ID); std::string pkt = "TRG:" + std::to_string(ID);
UDPSend(c,pkt); UDPSend(c, pkt);
if(!Handled(c,ID)) { if (!Handled(c, ID)) {
pkt = Packet.substr(pos + 1); pkt = Packet.substr(pos + 1);
GParser(c, pkt); GParser(c, pkt);
} }
return; return;
}else if(Packet.substr(0,2) == "SC"){ } else if (Packet.substr(0, 2) == "SC") {
HandleChunk(c,Packet); HandleChunk(c, Packet);
return; return;
} }
GParser(c,Packet); GParser(c, Packet);
} }
void LOOP(){ void LOOP() {
while(UDPSock != -1) { while (UDPSock != -1) {
for (PacketData* p : DataAcks){ for (PacketData* p : DataAcks) {
if(p != nullptr) { if (p != nullptr) {
if (p->Client == nullptr || p->Client->GetTCPSock() == -1) { if (p->Client == nullptr || p->Client->GetTCPSock() == -1) {
DataAcks.erase(p); DataAcks.erase(p);
break; break;
@ -253,23 +264,23 @@ void LOOP(){
std::this_thread::sleep_for(std::chrono::milliseconds(300)); std::this_thread::sleep_for(std::chrono::milliseconds(300));
} }
} }
[[noreturn]] void UDPServerMain(){ [[noreturn]] void UDPServerMain() {
#ifdef __WIN32 #ifdef __WIN32
WSADATA data; WSADATA data;
if (WSAStartup(514, &data)){ if (WSAStartup(514, &data)) {
error(Sec("Can't start Winsock!")); error(Sec("Can't start Winsock!"));
//return; //return;
} }
UDPSock = socket(AF_INET, SOCK_DGRAM, 0); UDPSock = socket(AF_INET, SOCK_DGRAM, 0);
// Create a server hint structure for the server // Create a server hint structure for the server
sockaddr_in serverAddr{}; sockaddr_in serverAddr {};
serverAddr.sin_addr.S_un.S_addr = ADDR_ANY; //Any Local serverAddr.sin_addr.S_un.S_addr = ADDR_ANY; //Any Local
serverAddr.sin_family = AF_INET; // Address format is IPv4 serverAddr.sin_family = AF_INET; // Address format is IPv4
serverAddr.sin_port = htons(Port); // Convert from little to big endian serverAddr.sin_port = htons(Port); // Convert from little to big endian
// Try and bind the socket to the IP and port // Try and bind the socket to the IP and port
if (bind(UDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR){ if (bind(UDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
error(Sec("Can't bind socket!") + std::to_string(WSAGetLastError())); error(Sec("Can't bind socket!") + std::to_string(WSAGetLastError()));
std::this_thread::sleep_for(std::chrono::seconds(5)); std::this_thread::sleep_for(std::chrono::seconds(5));
exit(-1); exit(-1);
@ -280,21 +291,22 @@ void LOOP(){
std::thread Ack(LOOP); std::thread Ack(LOOP);
Ack.detach(); Ack.detach();
info(Sec("Vehicle data network online on port ")+std::to_string(Port)+Sec(" with a Max of ")+std::to_string(MaxPlayers)+Sec(" Clients")); info(Sec("Vehicle data network online on port ") + std::to_string(Port) + Sec(" with a Max of ") + std::to_string(MaxPlayers) + Sec(" Clients"));
while (true){ while (true) {
sockaddr_in client{}; sockaddr_in client {};
std::string Data = UDPRcvFromClient(client); //Receives any data from Socket std::string Data = UDPRcvFromClient(client); //Receives any data from Socket
auto Pos = Data.find(':'); auto Pos = Data.find(':');
if(Data.empty() || Pos < 0 || Pos > 2)continue; if (Data.empty() || Pos < 0 || Pos > 2)
continue;
/*char clientIp[256]; /*char clientIp[256];
ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/ inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/
uint8_t ID = Data.at(0)-1; uint8_t ID = Data.at(0) - 1;
for(Client*c : CI->Clients){ for (Client* c : CI->Clients) {
if(c != nullptr && c->GetID() == ID){ if (c != nullptr && c->GetID() == ID) {
c->SetUDPAddr(client); c->SetUDPAddr(client);
c->isConnected = true; c->isConnected = true;
UDPParser(c,Data.substr(2)); UDPParser(c, Data.substr(2));
} }
} }
} }
@ -304,13 +316,13 @@ void LOOP(){
#else // unix #else // unix
UDPSock = socket(AF_INET, SOCK_DGRAM, 0); UDPSock = socket(AF_INET, SOCK_DGRAM, 0);
// Create a server hint structure for the server // Create a server hint structure for the server
sockaddr_in serverAddr{}; sockaddr_in serverAddr {};
serverAddr.sin_addr.s_addr = INADDR_ANY; //Any Local serverAddr.sin_addr.s_addr = INADDR_ANY; //Any Local
serverAddr.sin_family = AF_INET; // Address format is IPv4 serverAddr.sin_family = AF_INET; // Address format is IPv4
serverAddr.sin_port = htons(uint16_t(Port)); // Convert from little to big endian serverAddr.sin_port = htons(uint16_t(Port)); // Convert from little to big endian
// Try and bind the socket to the IP and port // Try and bind the socket to the IP and port
if (bind(UDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) != 0){ if (bind(UDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) != 0) {
error(Sec("Can't bind socket!") + std::string(strerror(errno))); error(Sec("Can't bind socket!") + std::string(strerror(errno)));
std::this_thread::sleep_for(std::chrono::seconds(5)); std::this_thread::sleep_for(std::chrono::seconds(5));
exit(-1); exit(-1);
@ -321,21 +333,22 @@ void LOOP(){
std::thread Ack(LOOP); std::thread Ack(LOOP);
Ack.detach(); Ack.detach();
info(Sec("Vehicle data network online on port ")+std::to_string(Port)+Sec(" with a Max of ")+std::to_string(MaxPlayers)+Sec(" Clients")); info(Sec("Vehicle data network online on port ") + std::to_string(Port) + Sec(" with a Max of ") + std::to_string(MaxPlayers) + Sec(" Clients"));
while (true){ while (true) {
sockaddr_in client{}; sockaddr_in client {};
std::string Data = UDPRcvFromClient(client); //Receives any data from Socket std::string Data = UDPRcvFromClient(client); //Receives any data from Socket
size_t Pos = Data.find(':'); size_t Pos = Data.find(':');
if(Data.empty() || Pos > 2)continue; if (Data.empty() || Pos > 2)
continue;
/*char clientIp[256]; /*char clientIp[256];
ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/ inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/
uint8_t ID = uint8_t(Data.at(0)) - 1; uint8_t ID = uint8_t(Data.at(0)) - 1;
for(Client*c : CI->Clients){ for (Client* c : CI->Clients) {
if(c != nullptr && c->GetID() == ID){ if (c != nullptr && c->GetID() == ID) {
c->SetUDPAddr(client); c->SetUDPAddr(client);
c->isConnected = true; c->isConnected = true;
UDPParser(c,Data.substr(2)); UDPParser(c, Data.substr(2));
} }
} }
} }