mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-01 23:35:41 +00:00
Major rewrite of the network
This commit is contained in:
parent
b0c6c2bac4
commit
131e64b706
@ -6,8 +6,10 @@ include_directories(${PROJECT_SOURCE_DIR}/curl)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
add_executable(BeamMP-Server src/main.cpp src/http.cpp src/logger.cpp src/config.cpp src/Network/Server.cpp
|
||||
src/Network/enet.hpp src/Network/DataParser.cpp src/heartbeat.cpp
|
||||
src/Network/ClientHandler.cpp src/Network/functions.cpp src/Settings.hpp
|
||||
src/Resources.cpp src/Network/TCPClientHandler.cpp)
|
||||
target_link_libraries(BeamMP-Server winmm ws2_32 libcurl_a)
|
||||
file(GLOB source_files
|
||||
"src/*.h" "src/*.hpp" "src/*.cpp"
|
||||
"src/Network 2.0/*.hpp" "src/Network 2.0/*.cpp"
|
||||
"src/curl/*.h")
|
||||
|
||||
add_executable(BeamMP-Server ${source_files})
|
||||
target_link_libraries(BeamMP-Server libcurl_a ws2_32)
|
70
src/Network 2.0/Client.cpp
Normal file
70
src/Network 2.0/Client.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 5/8/2020
|
||||
///
|
||||
#include "Client.hpp"
|
||||
|
||||
std::string Client::GetName(){
|
||||
return Name;
|
||||
}
|
||||
void Client::SetName(const std::string& name){
|
||||
Name = name;
|
||||
}
|
||||
void Client::SetDID(const std::string& did){
|
||||
DID = did;
|
||||
}
|
||||
std::string Client::GetDID(){
|
||||
return DID;
|
||||
}
|
||||
void Client::SetRole(const std::string& role){
|
||||
Role = role;
|
||||
}
|
||||
std::string Client::GetRole(){
|
||||
return Role;
|
||||
}
|
||||
int Client::GetID(){
|
||||
return ID;
|
||||
}
|
||||
void Client::SetID(int id){
|
||||
ID = id;
|
||||
}
|
||||
void Client::SetStatus(int state){
|
||||
Status = state;
|
||||
}
|
||||
int Client::GetStatus(){
|
||||
return Status;
|
||||
}
|
||||
void Client::SetUDPAddr(sockaddr_in Addr){
|
||||
UDPADDR = Addr;
|
||||
}
|
||||
sockaddr_in Client::GetUDPAddr(){
|
||||
return UDPADDR;
|
||||
}
|
||||
void Client::SetTCPSock(SOCKET CSock) {
|
||||
TCPSOCK = CSock;
|
||||
}
|
||||
SOCKET Client::GetTCPSock(){
|
||||
return TCPSOCK;
|
||||
}
|
||||
void Client::DeleteCar(int ident){
|
||||
for(const std::pair<int,std::string>& a : VehicleData){
|
||||
if(a.first == ident){
|
||||
VehicleData.erase(a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void Client::AddNewCar(int ident,const std::string& Data){
|
||||
VehicleData.insert(std::make_pair(ident,Data));
|
||||
}
|
||||
std::string Client::GetCarData(int ident){
|
||||
for(const std::pair<int,std::string>& a : VehicleData){
|
||||
if(a.first == ident){
|
||||
return a.second;
|
||||
}
|
||||
}
|
||||
DeleteCar(ident);
|
||||
return "";
|
||||
}
|
||||
int Client::GetCarCount(){
|
||||
return VehicleData.size();
|
||||
}
|
43
src/Network 2.0/Client.hpp
Normal file
43
src/Network 2.0/Client.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 5/8/2020
|
||||
///
|
||||
|
||||
#pragma once
|
||||
#include <WS2tcpip.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
class Client {
|
||||
private:
|
||||
std::set<std::pair<int,std::string>> VehicleData; //ID and Data;
|
||||
std::string Name = "Unknown Client";
|
||||
sockaddr_in UDPADDR;
|
||||
std::string Role;
|
||||
std::string DID; //Discord ID
|
||||
SOCKET TCPSOCK;
|
||||
int Status = 0;
|
||||
int ID = -1; //PlayerID
|
||||
|
||||
public:
|
||||
void AddNewCar(int ident,const std::string& Data);
|
||||
void SetName(const std::string& name);
|
||||
void SetRole(const std::string& role);
|
||||
void SetDID(const std::string& did);
|
||||
std::string GetCarData(int ident);
|
||||
void SetUDPAddr(sockaddr_in Addr);
|
||||
void SetTCPSock(SOCKET CSock);
|
||||
void SetStatus(int status);
|
||||
void DeleteCar(int ident);
|
||||
sockaddr_in GetUDPAddr();
|
||||
std::string GetRole();
|
||||
std::string GetName();
|
||||
std::string GetDID();
|
||||
SOCKET GetTCPSock();
|
||||
void SetID(int ID);
|
||||
int GetCarCount();
|
||||
int GetStatus();
|
||||
int GetID();
|
||||
};
|
||||
|
||||
extern std::set<Client*> Clients;
|
64
src/Network 2.0/ClientInterface.cpp
Normal file
64
src/Network 2.0/ClientInterface.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 2/4/2020.
|
||||
///
|
||||
#include "Client.hpp"
|
||||
#include "../logger.h"
|
||||
#include "../Settings.hpp"
|
||||
|
||||
void UDPSend(Client*c,const std::string&Data);
|
||||
void TCPSend(Client*c,const std::string&Data);
|
||||
|
||||
int OpenID(){
|
||||
int ID = 0;
|
||||
bool found;
|
||||
do {
|
||||
found = true;
|
||||
for (Client *c : Clients) {
|
||||
if(c->GetID() == ID){
|
||||
found = false;
|
||||
ID++;
|
||||
}
|
||||
}
|
||||
}while (!found);
|
||||
return ID;
|
||||
}
|
||||
|
||||
void Respond(Client*c, const std::string& MSG, bool Rel){
|
||||
if(Rel)TCPSend(c,MSG);
|
||||
else UDPSend(c,MSG);
|
||||
}
|
||||
|
||||
void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel){
|
||||
for(Client*client : Clients){
|
||||
if(Self || client != c){
|
||||
if(Rel)TCPSend(client,Data);
|
||||
else UDPSend(client,Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePlayers(){
|
||||
std::string Packet = "Ss" + std::to_string(Clients.size())+"/"+std::to_string(MaxPlayers) + ":";
|
||||
for (Client*c : Clients) {
|
||||
Packet += c->GetName() + ",";
|
||||
}
|
||||
Packet = Packet.substr(0,Packet.length()-1);
|
||||
SendToAll(nullptr, Packet,true,true);
|
||||
}
|
||||
|
||||
void OnDisconnect(Client*c,bool Timed){
|
||||
std::string Packet = "Od:" + std::to_string(c->GetID());
|
||||
SendToAll(c, Packet,false,true);
|
||||
//if(Timed)Packet = "L"+c->GetName()+" Timed out!";
|
||||
Packet = "L"+c->GetName()+" Left the server!";
|
||||
SendToAll(c, Packet,false,true);
|
||||
Packet.clear();
|
||||
Clients.erase(c); ///Removes the Client from the list
|
||||
}
|
||||
|
||||
void OnConnect(Client*c){
|
||||
c->SetID(OpenID());
|
||||
std::cout << "New Client Created! ID : " << c->GetID() << std::endl;
|
||||
Respond(c,"NR",true);
|
||||
Respond(c,"M"+MapName,true); //Send the Map on connect
|
||||
}
|
135
src/Network 2.0/DataParser.cpp
Normal file
135
src/Network 2.0/DataParser.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 4/2/2020
|
||||
///
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include "Client.hpp"
|
||||
#include "../logger.h"
|
||||
#include "../Settings.hpp"
|
||||
|
||||
void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel);
|
||||
std::string HTTP_REQUEST(const std::string& IP,int port);
|
||||
void Respond(Client*c, const std::string& MSG, bool Rel);
|
||||
void UpdatePlayers();
|
||||
|
||||
void FindAndSync(Client*c,int VehID){
|
||||
for (Client*client : Clients) {
|
||||
if (client != c){
|
||||
if(client->GetID() == VehID){ /////mark
|
||||
Respond(client,c->GetCarData(VehID),true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void VehicleParser(Client*c, std::string Packet){
|
||||
char Code = Packet.at(1);
|
||||
int ID = -1;
|
||||
std::string Data = Packet.substr(3);
|
||||
switch(Code){ //Spawned Destroyed Switched/Moved NotFound Reset
|
||||
case 's':
|
||||
if(Data.at(0) == '0'){
|
||||
if(c->GetCarCount() >= MaxCars){
|
||||
std::string Destroy = "Od:" + std::to_string(c->GetID()); ///to revise
|
||||
SendToAll(c,Destroy,true,true);
|
||||
c->DeleteCar(c->GetID());
|
||||
}
|
||||
Packet = "Os:"+c->GetRole()+":"+c->GetName()+":"+std::to_string(c->GetID())+Packet.substr(4);
|
||||
c->AddNewCar(c->GetID(),Packet); ///revise later
|
||||
}
|
||||
SendToAll(nullptr,Packet,true,true);
|
||||
break;
|
||||
case 'd':
|
||||
if(Data.find_first_not_of("0123456789") == std::string::npos){
|
||||
ID = stoi(Data);
|
||||
}
|
||||
if(ID != -1 && ID == c->GetID()){
|
||||
SendToAll(nullptr,Packet,true,true);
|
||||
c->DeleteCar(c->GetID());
|
||||
///std::cout << "Delete Requested from " << c->GetName() << std::endl;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
break;
|
||||
case 'n':
|
||||
if(Packet.substr(3).find_first_not_of("0123456789") == std::string::npos){
|
||||
ID = stoi(Packet.substr(3));
|
||||
}
|
||||
FindAndSync(c,ID);
|
||||
break;
|
||||
case 'r':
|
||||
SendToAll(c,Packet,false,true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SyncVehicles(Client*c){
|
||||
Respond(c,"Sn"+c->GetName(),true);
|
||||
SendToAll(c,"JWelcome "+c->GetName()+"!",false,true);
|
||||
for (Client*client : Clients) {
|
||||
if (client != c) {
|
||||
Respond(c,client->GetCarData(client->GetID()),true); ///revise later
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HTTP(Client*c){
|
||||
if(!c->GetDID().empty()){
|
||||
std::string a = HTTP_REQUEST("https://beamng-mp.com/entitlement?did="+c->GetDID(),443);
|
||||
if(!a.empty()){
|
||||
int pos = a.find('"');
|
||||
c->SetRole(a.substr(pos+1,a.find('"',pos+1)-2));
|
||||
if(Debug)debug("ROLE -> " + c->GetRole() + " ID -> " + c->GetDID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrabRole(Client*c){
|
||||
std::thread t1(HTTP,c);
|
||||
t1.detach();
|
||||
}
|
||||
|
||||
void GlobalParser(Client*c, const std::string&Packet){
|
||||
if(Packet.empty())return;
|
||||
if(Packet.find("TEST")!=std::string::npos)SyncVehicles(c);
|
||||
char Code = Packet.at(0),SubCode = 0;
|
||||
if(Packet.length() > 1)SubCode = Packet.at(1);
|
||||
switch (Code) {
|
||||
case 'P':
|
||||
Respond(c, "P" + std::to_string(c->GetID()),true);
|
||||
return;
|
||||
case 'p':
|
||||
Respond(c,"p",false);
|
||||
UpdatePlayers();
|
||||
return;
|
||||
case 'N':
|
||||
if(SubCode == 'R'){
|
||||
c->SetName(Packet.substr(2,Packet.find(':')-2));
|
||||
c->SetDID(Packet.substr(Packet.find(':')+1));
|
||||
GrabRole(c);
|
||||
}
|
||||
std::cout << "Name : " << c->GetName() << std::endl;
|
||||
return;
|
||||
case 'O':
|
||||
if(Packet.length() > 1000) {
|
||||
std::cout << "Received data from: " << c->GetName() << " Size: " << Packet.length() << std::endl;
|
||||
}
|
||||
VehicleParser(c,Packet);
|
||||
return;
|
||||
case 'J':
|
||||
SendToAll(c,Packet,false,true);
|
||||
break;
|
||||
case 'C':
|
||||
SendToAll(nullptr,Packet,true,true);
|
||||
break;
|
||||
case 'E':
|
||||
SendToAll(nullptr,Packet,true,true);
|
||||
break;
|
||||
}
|
||||
//V to Z
|
||||
if(Packet.length() > 1000){
|
||||
std::cout << "Received data from: " << c->GetName() << " Size: " << Packet.length() << std::endl;
|
||||
}
|
||||
|
||||
if(Code <= 90 && Code >= 86)SendToAll(c,Packet,false,false);
|
||||
if(Debug)debug("Data : " + Packet);
|
||||
}
|
58
src/Network 2.0/Handler.cpp
Normal file
58
src/Network 2.0/Handler.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 5/9/2020
|
||||
///
|
||||
///TCP
|
||||
|
||||
#include "Client.hpp"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
void TCPSend(Client*c,const std::string&Data){
|
||||
int BytesSent = send(c->GetTCPSock(), Data.c_str(), int(Data.length())+1, 0);
|
||||
if (BytesSent == 0){
|
||||
std::cout << "(TCP) Connection closing..." << std::endl;
|
||||
c->SetStatus(-1);
|
||||
}
|
||||
else if (BytesSent < 0) {
|
||||
std::cout << "(TCP) send failed with error: " << WSAGetLastError() << std::endl;
|
||||
closesocket(c->GetTCPSock());
|
||||
c->SetStatus(-2);
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalParser(Client*c, const std::string&Packet);
|
||||
void TCPRcv(Client*c){
|
||||
char buf[10240];
|
||||
int len = 10240;
|
||||
ZeroMemory(buf, len);
|
||||
int BytesRcv = recv(c->GetTCPSock(), buf, len,0);
|
||||
if (BytesRcv == 0){
|
||||
std::cout << "(TCP) Connection closing..." << std::endl;
|
||||
c->SetStatus(-1);
|
||||
}
|
||||
else if (BytesRcv < 0) {
|
||||
std::cout << "(TCP) recv failed with error: " << WSAGetLastError() << std::endl;
|
||||
closesocket(c->GetTCPSock());
|
||||
c->SetStatus(-2);
|
||||
}
|
||||
GlobalParser(c, std::string(buf));
|
||||
}
|
||||
|
||||
void OnConnect(Client*c);
|
||||
void OnDisconnect(Client*c,bool Timed);
|
||||
void TCPClient(Client*client){
|
||||
if(client->GetTCPSock() == -1)return;
|
||||
std::cout << "Client connected" << std::endl;
|
||||
OnConnect(client);
|
||||
while (client->GetStatus() > -1){
|
||||
TCPRcv(client);
|
||||
}
|
||||
//OnDisconnect
|
||||
OnDisconnect(client, client->GetStatus() == -2);
|
||||
std::cout << "Client Terminated" << std::endl;
|
||||
}
|
||||
|
||||
void CreateNewThread(Client*client){
|
||||
std::thread NewClient(TCPClient,client);
|
||||
NewClient.detach();
|
||||
}
|
13
src/Network 2.0/NetworkMain.cpp
Normal file
13
src/Network 2.0/NetworkMain.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "Client.hpp"
|
||||
#include <thread>
|
||||
|
||||
void TCPServerMain();
|
||||
void UDPServerMain();
|
||||
|
||||
std::set<Client*> Clients;
|
||||
void NetMain() {
|
||||
std::thread TCP(TCPServerMain);
|
||||
TCP.detach();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
UDPServerMain();
|
||||
}
|
85
src/Network 2.0/VehicleData.cpp
Normal file
85
src/Network 2.0/VehicleData.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 5/8/2020
|
||||
///
|
||||
///UDP
|
||||
|
||||
#include "Client.hpp"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "../logger.h"
|
||||
#include "../Settings.hpp"
|
||||
|
||||
SOCKET UDPSock;
|
||||
|
||||
void UDPSend(Client*c,const std::string&Data){
|
||||
sockaddr_in Addr = c->GetUDPAddr();
|
||||
int AddrSize = sizeof(c->GetUDPAddr());
|
||||
int sendOk = sendto(UDPSock, Data.c_str(), int(Data.length()) + 1, 0, (sockaddr*)&Addr, AddrSize);
|
||||
if (sendOk == SOCKET_ERROR)error("(UDP) Send Error! Code : " + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
|
||||
std::string UDPRcvFromClient(sockaddr_in& client){
|
||||
char buf[4096];
|
||||
int clientLength = sizeof(client);
|
||||
ZeroMemory(&client, clientLength);
|
||||
ZeroMemory(buf, 4096);
|
||||
int bytesIn = recvfrom(UDPSock, buf, 4096, 0, (sockaddr*)&client, &clientLength);
|
||||
if (bytesIn == -1)
|
||||
{
|
||||
error("(UDP) Error receiving from Client! Code : " + std::to_string(WSAGetLastError()));
|
||||
return "";
|
||||
}
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
void GlobalParser(Client*c, const std::string&Packet);
|
||||
|
||||
[[noreturn]] void UDPServerMain(){
|
||||
|
||||
WSADATA data;
|
||||
|
||||
if (WSAStartup(514, &data)) //2.2
|
||||
{
|
||||
|
||||
std::cout << "Can't start Winsock!" << std::endl;
|
||||
//return;
|
||||
}
|
||||
|
||||
UDPSock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
// Create a server hint structure for the server
|
||||
sockaddr_in serverAddr{};
|
||||
serverAddr.sin_addr.S_un.S_addr = ADDR_ANY; //Any Local
|
||||
serverAddr.sin_family = AF_INET; // Address format is IPv4
|
||||
serverAddr.sin_port = htons(Port); // Convert from little to big endian
|
||||
|
||||
// Try and bind the socket to the IP and port
|
||||
if (bind(UDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
|
||||
{
|
||||
std::cout << "Can't bind socket! " << WSAGetLastError() << std::endl;
|
||||
//return;
|
||||
}
|
||||
info("Vehicle data network online on port "+std::to_string(Port)+" with a Max of "+std::to_string(MaxPlayers)+" Clients");
|
||||
while (true)
|
||||
{
|
||||
sockaddr_in client{};
|
||||
std::string Data = UDPRcvFromClient(client); //Receives any data from Socket
|
||||
int Pos = Data.find(':');
|
||||
if(Data.empty() || Pos < 0 || Pos > 2)continue;
|
||||
/*char clientIp[256];
|
||||
ZeroMemory(clientIp, 256); ///Code to get IP we don't need that yet
|
||||
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);*/
|
||||
|
||||
uint8_t ID = Data.at(0)-1;
|
||||
for(Client*c : Clients){
|
||||
if(c->GetID() == ID){
|
||||
c->SetUDPAddr(client);
|
||||
GlobalParser(c,Data.substr(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
///UDPSendToClient(c->GetUDPAddr(), sizeof(c->GetUDPAddr()), Data);
|
||||
/*closesocket(UDPSock);
|
||||
WSACleanup();
|
||||
return;*/
|
||||
}
|
64
src/Network 2.0/VehicleEvent.cpp
Normal file
64
src/Network 2.0/VehicleEvent.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 5/9/2020
|
||||
///
|
||||
///TCP
|
||||
|
||||
#include "Client.hpp"
|
||||
#include <iostream>
|
||||
#include <WS2tcpip.h>
|
||||
#include "../logger.h"
|
||||
#include "../Settings.hpp"
|
||||
|
||||
void CreateNewThread(Client*client);
|
||||
void CreateClient(SOCKET TCPSock){
|
||||
auto *client = new Client;
|
||||
client->SetTCPSock(TCPSock);
|
||||
Clients.insert(client);
|
||||
CreateNewThread(client);
|
||||
}
|
||||
|
||||
void TCPServerMain(){
|
||||
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(514, &wsaData)) //2.2
|
||||
{
|
||||
std::cout << "Can't start Winsock!" << std::endl;
|
||||
return;
|
||||
}
|
||||
SOCKET client,Listener = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
|
||||
sockaddr_in addr{};
|
||||
addr.sin_addr.S_un.S_addr = ADDR_ANY;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(Port);
|
||||
|
||||
if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
|
||||
{
|
||||
std::cout << "Can't bind socket! " << WSAGetLastError() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if(Listener == -1)
|
||||
{
|
||||
printf("Invalid socket");
|
||||
return;
|
||||
}
|
||||
|
||||
if(listen(Listener,SOMAXCONN))
|
||||
{
|
||||
std::cout << "listener failed " << GetLastError();
|
||||
return;
|
||||
}
|
||||
info("Vehicle event network online");
|
||||
do{
|
||||
client = accept(Listener, nullptr, nullptr);
|
||||
if(client == -1)
|
||||
{
|
||||
std::cout << "invalid client socket" << std::endl;
|
||||
continue;
|
||||
}
|
||||
if(Clients.size() < MaxPlayers)CreateClient(client);
|
||||
}while(client);
|
||||
|
||||
closesocket(client);
|
||||
WSACleanup();
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 2/4/2020.
|
||||
///
|
||||
|
||||
#include <string>
|
||||
#include "enet.hpp"
|
||||
#include <thread>
|
||||
#include "../logger.h"
|
||||
#include "../Settings.hpp"
|
||||
|
||||
int FindID(ENetHost *server,ENetPeer*peer);
|
||||
void Respond(const std::string& MSG, ENetPeer*peer){
|
||||
enet_peer_send(peer, 0, enet_packet_create(MSG.c_str(), MSG.length() + 1, ENET_PACKET_FLAG_RELIABLE));
|
||||
}
|
||||
|
||||
void SendToAll(ENetHost *server, ENetPeer*peer,const std::string& Data, bool All, bool Rel){
|
||||
//std::cout << "Sending Code " << Data.at(0) << " length:" << Data.length() << " to all with the self switch : " << All << std::endl;
|
||||
for (int i = 0; i < server->connectedPeers; i++) {
|
||||
if (All || &server->peers[i] != peer) {
|
||||
//reliable is 1 unreliable is 8
|
||||
enet_peer_send(&server->peers[i], 0, enet_packet_create(Data.c_str(),Data.length()+1,Rel?1:8));
|
||||
enet_host_flush(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
void UpdatePlayers(ENetHost *server, ENetPeer*peer){
|
||||
std::string Packet = "Ss" + std::to_string(server->connectedPeers)+"/"+std::to_string(MaxPlayers) + ":";
|
||||
for (int i = 0; i < server->connectedPeers; i++) {
|
||||
ENetPeer*SPeer = &server->peers[i];
|
||||
Packet += SPeer->Name + ",";
|
||||
}
|
||||
Packet = Packet.substr(0,Packet.length()-1);
|
||||
SendToAll(server,peer, Packet,true,true);
|
||||
}
|
||||
|
||||
void OnDisconnect(ENetHost *server,ENetPeer*peer,bool Timed){
|
||||
std::string Packet = "Od:" + std::to_string(peer->PlayerID);
|
||||
SendToAll(server,peer, Packet,false,true);
|
||||
if(Timed)Packet = "L"+peer->Name+" Timed out!";
|
||||
else Packet = "L"+peer->Name+" Left the server!";
|
||||
SendToAll(server,peer, Packet,false,true);
|
||||
Packet.clear();
|
||||
peer->DID.clear();
|
||||
peer->Name.clear();
|
||||
peer->VehicleData.clear();
|
||||
}
|
||||
|
||||
void OnConnect(ENetHost *server,ENetPeer*peer){
|
||||
Respond("NR",peer);
|
||||
peer->PlayerID = FindID(server,peer); ///TODO: WHAT IF IT IS THE SECOND VEHICLE?
|
||||
std::string ID = "P" + std::to_string(peer->PlayerID);
|
||||
Respond(ID,peer);
|
||||
if(Debug)debug(peer->Name + " ID : " + std::to_string(peer->PlayerID));
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 4/2/2020
|
||||
///
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include "enet.hpp"
|
||||
#include "../logger.h"
|
||||
#include "../Settings.hpp"
|
||||
|
||||
void SendToAll(ENetHost *server, ENetPeer*peer,const std::string& Data,bool All, bool Reliable);
|
||||
std::string HTTP_REQUEST(const std::string& IP,int port);
|
||||
void Respond(const std::string& MSG, ENetPeer*peer);
|
||||
void UpdatePlayers(ENetHost *server, ENetPeer*peer);
|
||||
|
||||
void FindAndSync(ENetPeer*peer,ENetHost*server,int VehID){
|
||||
ENetPeer*ENetClient;
|
||||
for (int i = 0; i < server->connectedPeers; i++) {
|
||||
ENetClient = &server->peers[i];
|
||||
if (ENetClient != peer){
|
||||
if(ENetClient->PlayerID == VehID){ /////mark
|
||||
Respond(ENetClient->VehicleData,peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VehicleParser(std::string Packet,ENetPeer*peer,ENetHost*server){
|
||||
char Code = Packet.at(1);
|
||||
int ID = -1;
|
||||
std::string Data = Packet.substr(3);
|
||||
switch(Code){ //Spawned Destroyed Switched/Moved NotFound Reset
|
||||
case 's':
|
||||
if(Data.at(0) == '0'){
|
||||
Packet = "Os:"+peer->Role+":"+peer->Name+":"+std::to_string(peer->PlayerID)+Packet.substr(4);
|
||||
peer->VehicleData = Packet;
|
||||
}
|
||||
SendToAll(server,peer,Packet,true,true);
|
||||
break;
|
||||
case 'd':
|
||||
if(Packet.substr(3).find_first_not_of("0123456789") == std::string::npos){
|
||||
ID = stoi(Packet.substr(3));
|
||||
}
|
||||
peer->VehicleData.clear();
|
||||
if(ID != -1 && ID == peer->PlayerID){
|
||||
SendToAll(server,peer,Packet,true,true);
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
break;
|
||||
case 'n':
|
||||
if(Packet.substr(3).find_first_not_of("0123456789") == std::string::npos){
|
||||
ID = stoi(Packet.substr(3));
|
||||
}
|
||||
FindAndSync(peer,server,ID);
|
||||
break;
|
||||
case 'r':
|
||||
SendToAll(server,peer,Packet,false,true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SyncVehicles(ENetHost*server,ENetPeer*peer){
|
||||
ENetPeer*ENetClient;
|
||||
for (int i = 0; i < server->connectedPeers; i++) {
|
||||
ENetClient = &server->peers[i];
|
||||
if (ENetClient != peer) {
|
||||
if(!ENetClient->VehicleData.empty()){
|
||||
enet_peer_send(peer, 0, enet_packet_create(ENetClient->VehicleData.c_str(),ENetClient->VehicleData.length()+1,1));
|
||||
enet_host_flush(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HTTP(ENetPeer*peer){
|
||||
if(peer != nullptr && !peer->DID.empty()){
|
||||
std::string a = HTTP_REQUEST("https://beamng-mp.com/entitlement?did="+peer->DID,443);
|
||||
if(!a.empty()){
|
||||
int pos = a.find('"');
|
||||
peer->Role = a.substr(pos+1,a.find('"',pos+1)-2);
|
||||
if(Debug)debug("ROLE -> " + peer->Role + " ID -> " + peer->DID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrabRole(ENetPeer*peer){
|
||||
std::thread t1(HTTP,peer);
|
||||
t1.detach();
|
||||
}
|
||||
|
||||
void ParseData(ENetPacket*packet, ENetPeer*peer, ENetHost*server){
|
||||
std::string Packet = (char*)packet->data;
|
||||
if(Packet.empty())return;
|
||||
if(Packet.find("TEST")!=std::string::npos)SyncVehicles(server,peer);
|
||||
char Code = Packet.at(0),SubCode = 0;
|
||||
if(Packet.length() > 1)SubCode = Packet.at(1);
|
||||
switch (Code) {
|
||||
case 'p':
|
||||
Respond("p",peer);
|
||||
UpdatePlayers(server,peer);
|
||||
return;
|
||||
case 'N':
|
||||
if(SubCode == 'R'){
|
||||
peer->Name = Packet.substr(2,Packet.find(':')-2);
|
||||
peer->DID = Packet.substr(Packet.find(':')+1);
|
||||
Respond("Sn"+peer->Name,peer);
|
||||
SendToAll(server,peer,"JWelcome "+peer->Name+"!",false,true);
|
||||
GrabRole(peer);
|
||||
}
|
||||
std::cout << "Name : " << peer->Name << std::endl;
|
||||
return;
|
||||
case 'O':
|
||||
if(Packet.length() > 1000) {
|
||||
std::cout << "Received data from: " << peer->Name << " Size: " << Packet.length() << std::endl;
|
||||
}
|
||||
VehicleParser(Packet,peer,server);
|
||||
return;
|
||||
case 'J':
|
||||
SendToAll(server,peer,Packet,false,true);
|
||||
break;
|
||||
case 'C':
|
||||
SendToAll(server,peer,Packet, true,true);
|
||||
break;
|
||||
case 'E':
|
||||
SendToAll(server,peer,Packet, true,true);
|
||||
break;
|
||||
}
|
||||
//V to Z
|
||||
if(Packet.length() > 1000){
|
||||
std::cout << "Received data from: " << peer->Name << " Size: " << Packet.length() << std::endl;
|
||||
}
|
||||
|
||||
if(Code <= 90 && Code >= 86)SendToAll(server,peer,Packet,false,false);
|
||||
if(Debug)debug("Data : " + Packet);
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 4/2/2020
|
||||
///
|
||||
|
||||
#define ENET_IMPLEMENTATION
|
||||
#include <string>
|
||||
#include "enet.hpp"
|
||||
#include <cstdio>
|
||||
#include "../logger.h"
|
||||
#include "../Settings.hpp"
|
||||
|
||||
void ParseData(ENetPacket*packet,ENetPeer*peer,ENetHost *server);
|
||||
void OnDisconnect(ENetHost *server,ENetPeer*peer,bool Timed);
|
||||
void OnConnect(ENetHost *server,ENetPeer*peer);
|
||||
ENetPacket* packet;
|
||||
int PlayerCount = 0;
|
||||
|
||||
int FindID(ENetHost *server,ENetPeer*peer){
|
||||
int OpenID = 1;
|
||||
bool Found;
|
||||
do {
|
||||
Found = true;
|
||||
for (int i = 0; i < server->connectedPeers; i++) {
|
||||
if (&server->peers[i] != peer) {
|
||||
if(server->peers[i].PlayerID == OpenID) {
|
||||
Found = false;
|
||||
OpenID++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}while (!Found);
|
||||
return OpenID;
|
||||
}
|
||||
|
||||
|
||||
void host_server(ENetHost *server) {
|
||||
ENetEvent event;
|
||||
PlayerCount = server->connectedPeers;
|
||||
while (enet_host_service(server, &event, 1) > 0) {
|
||||
switch (event.type) {
|
||||
case ENET_EVENT_TYPE_CONNECT:
|
||||
printf("A new client connected from %x:%u.\n", event.peer->address.host, event.peer->address.port);
|
||||
//the data should be the client info could be name for now it's Client information
|
||||
event.peer->Name = "Client information";
|
||||
/*event.peer->gameVehicleID[0] = 0;
|
||||
event.peer->serverVehicleID[0] = FindID(server, event.peer);*/
|
||||
OnConnect(server,event.peer);
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_RECEIVE:
|
||||
ParseData(event.packet,event.peer,server);
|
||||
/*->dataLength,event.packet->data, (char *)event.peer->data, event.channelID*/ //We grab and Parse the Data
|
||||
/* Clean up the packet now that we're done using it. */
|
||||
enet_packet_destroy (event.packet);
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
std::cout << event.peer->Name << " disconnected." << std::endl;
|
||||
OnDisconnect(server,event.peer,false);
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
|
||||
std::cout << event.peer->Name << " timed out." << std::endl;
|
||||
OnDisconnect(server,event.peer,true);
|
||||
break;
|
||||
case ENET_EVENT_TYPE_NONE: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerMain(int Port, int MaxClients) {
|
||||
|
||||
if (enet_initialize() != 0) {
|
||||
printf("An error occurred while initializing.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ENetHost *server;
|
||||
ENetAddress address = {0};
|
||||
|
||||
address.host = ENET_HOST_ANY; //Bind the server to the default localhost.
|
||||
address.port = Port; // Sets the port
|
||||
|
||||
//create a server
|
||||
info("starting server with a maximum of " + to_string(MaxClients) + " Clients...");
|
||||
server = enet_host_create(&address, MaxClients, 2, 0, 0);
|
||||
if (server == nullptr) {
|
||||
error("An error occurred while trying to create a server host.");
|
||||
return;
|
||||
}
|
||||
info("Waiting for clients on port "+to_string(Port)+"...");
|
||||
while (true) {
|
||||
host_server(server);
|
||||
}
|
||||
|
||||
enet_host_destroy(server);
|
||||
enet_deinitialize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void CreateNewThread(void*);
|
||||
|
||||
void TCPMain(int Port){
|
||||
info("Starting TCP Server on port " + to_string(Port));
|
||||
|
||||
WSADATA wsaData;
|
||||
int iResult;
|
||||
sockaddr_in addr{};
|
||||
SOCKET sock,client;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(Port);
|
||||
|
||||
iResult = WSAStartup(MAKEWORD(2,2),&wsaData);
|
||||
|
||||
if(iResult)
|
||||
{
|
||||
printf("WSA startup failed");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
|
||||
|
||||
if(sock == INVALID_SOCKET)
|
||||
{
|
||||
printf("Invalid socket");
|
||||
return;
|
||||
}
|
||||
|
||||
iResult = bind(sock,(sockaddr*)&addr,sizeof(sockaddr_in ));
|
||||
|
||||
if(iResult)
|
||||
{
|
||||
|
||||
printf("bind failed %lu",GetLastError());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
iResult = listen(sock,SOMAXCONN);
|
||||
|
||||
if(iResult)
|
||||
{
|
||||
|
||||
printf("iResult failed %lu",GetLastError());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
while(client = accept(sock,nullptr,nullptr))
|
||||
{
|
||||
if(client == INVALID_SOCKET)
|
||||
{
|
||||
printf("invalid client socket\n");
|
||||
continue;
|
||||
}
|
||||
CreateNewThread((void*)&client);
|
||||
}
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 4/11/2020
|
||||
///
|
||||
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <WinSock2.h>
|
||||
#include "../Settings.hpp"
|
||||
|
||||
int ParseAndSend(SOCKET Client, std::string Data){
|
||||
std::string Response, Packet;
|
||||
char ID = Data.at(0);
|
||||
int Prev = 0,DataSent = 0, Size = 0;
|
||||
bool FileSent = true;
|
||||
switch (ID){
|
||||
case 'a' :
|
||||
Response = FileList+FileSizes;
|
||||
if(Response.empty())Response = " ";
|
||||
break;
|
||||
case 'b' :
|
||||
FileSent = false;
|
||||
break;
|
||||
case 'M' :
|
||||
Response = MapName;
|
||||
break;
|
||||
}
|
||||
std::string FLocation = Data.substr(1);
|
||||
if(FileList.find(FLocation) == std::string::npos)return -1;
|
||||
do {
|
||||
if(!FileSent){
|
||||
std::ifstream f;
|
||||
f.open(FLocation.c_str(), std::ios::binary);
|
||||
if(f.good()){
|
||||
if(!Size){
|
||||
Size = f.seekg(0, std::ios_base::end).tellg();
|
||||
Response.resize(Size);
|
||||
f.seekg(0, std::ios_base::beg);
|
||||
f.read(&Response[0], Size);
|
||||
f.close();
|
||||
}else f.close();
|
||||
|
||||
if(DataSent != Size){
|
||||
Packet.clear();
|
||||
if((Size-DataSent) < 65535){
|
||||
Packet = Response.substr(Prev,(Size-DataSent));
|
||||
DataSent += (Size-DataSent);
|
||||
Response.clear();
|
||||
}else{
|
||||
DataSent += 65535;
|
||||
Packet = Response.substr(Prev,65535);
|
||||
}
|
||||
Prev = DataSent;
|
||||
}else{
|
||||
Size = 0;
|
||||
DataSent = 0;
|
||||
Prev = 0;
|
||||
FileSent = true;
|
||||
Packet.clear();
|
||||
}
|
||||
}else{
|
||||
FileSent = true;
|
||||
Response = "Cannot Open";
|
||||
}
|
||||
}
|
||||
|
||||
int iSendResult;
|
||||
|
||||
if(!Packet.empty())iSendResult = send(Client, Packet.c_str(), Packet.length(), 0);
|
||||
else iSendResult = send(Client, Response.c_str(), Response.length(), 0);
|
||||
|
||||
if (iSendResult == SOCKET_ERROR) {
|
||||
printf("send failed with error: %d\n", WSAGetLastError());
|
||||
closesocket(Client);
|
||||
return -1;
|
||||
}
|
||||
}while(!FileSent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Client(void* ClientData){
|
||||
SOCKET Client = *(SOCKET*)ClientData;
|
||||
printf("Client connected\n");
|
||||
int iResult, iSendResult;
|
||||
char recvbuf[65535];
|
||||
int recvbuflen = 65535;
|
||||
|
||||
do {
|
||||
iResult = recv(Client, recvbuf, recvbuflen, 0);
|
||||
if (iResult > 0) {
|
||||
//printf("Bytes received: %d\n", iResult);
|
||||
std::string Data = recvbuf,Response;
|
||||
Data.resize(iResult);
|
||||
|
||||
if(ParseAndSend(Client,Data) == -1)break;
|
||||
|
||||
// Echo the buffer back to the sender
|
||||
/*iSendResult = send(Client, Response.c_str(), Response.length(), 0);
|
||||
if (iSendResult == SOCKET_ERROR) {
|
||||
printf("send failed with error: %d\n", WSAGetLastError());
|
||||
closesocket(Client);
|
||||
return;
|
||||
}
|
||||
printf("Bytes sent: %d\n", iSendResult);*/
|
||||
}
|
||||
else if (iResult == 0)
|
||||
printf("Connection closing...\n");
|
||||
else {
|
||||
printf("recv failed with error: %d\n", WSAGetLastError());
|
||||
closesocket(Client);
|
||||
break;
|
||||
}
|
||||
} while (iResult > 0);
|
||||
std::cout << "Client Closed" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void CreateNewThread(void* ClientData){
|
||||
std::cout << "New Client" << std::endl;
|
||||
std::thread NewClient(Client,ClientData);
|
||||
NewClient.detach();
|
||||
}
|
5911
src/Network/enet.hpp
5911
src/Network/enet.hpp
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,6 @@ extern bool Debug;
|
||||
extern int MaxPlayers;
|
||||
extern int Port;
|
||||
extern int MaxCars;
|
||||
extern int PlayerCount;
|
||||
extern std::string MapName;
|
||||
extern std::string ServerName;
|
||||
extern std::string Resource;
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include "logger.h"
|
||||
#include "Settings.hpp"
|
||||
#include "Network 2.0/Client.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -16,11 +16,12 @@ void PostHTTP(const std::string& IP,const std::string& Fields);
|
||||
|
||||
void Heartbeat()
|
||||
{
|
||||
|
||||
string UUID = HTTP_REQUEST("https://beamng-mp.com/new-server-startup",443);
|
||||
std::string State = Private ? "true" : "false";
|
||||
while(true)
|
||||
{
|
||||
PostHTTP("https://beamng-mp.com/heartbeat","uuid="+UUID+"&players="+to_string(PlayerCount)+"&maxplayers="+to_string(MaxPlayers)+"&port="
|
||||
PostHTTP("https://beamng-mp.com/heartbeat","uuid="+UUID+"&players="+to_string(Clients.size())+"&maxplayers="+to_string(MaxPlayers)+"&port="
|
||||
+ to_string(Port) + "&map=" + MapName + "&private="+State+"&version="+ServerVersion+"&clientversion="+ClientVersion+"&name="+ServerName);
|
||||
std::this_thread::sleep_for (std::chrono::seconds(5));
|
||||
}
|
||||
|
12
src/main.cpp
12
src/main.cpp
@ -15,12 +15,13 @@ void DebugData();
|
||||
void LogInit();
|
||||
void ParseConfig();
|
||||
void addToLog(const string& Data);
|
||||
void ServerMain(int Port, int MaxClients);
|
||||
//void ServerMain(int Port, int MaxClients);
|
||||
void HeartbeatInit();
|
||||
string ServerVersion = "0.1";
|
||||
string ClientVersion = "0.21";
|
||||
void HandleResources(const std::string& path);
|
||||
void TCPMain(int Port);
|
||||
//void TCPMain(int Port);
|
||||
void NetMain();
|
||||
//Entry
|
||||
int main() {
|
||||
LogInit();
|
||||
@ -29,9 +30,10 @@ int main() {
|
||||
HeartbeatInit();
|
||||
if(Debug)DebugData();
|
||||
setLoggerLevel(0); //0 for all
|
||||
std::thread TCPThread(TCPMain,Port);
|
||||
TCPThread.detach();
|
||||
ServerMain(Port, MaxPlayers);
|
||||
/*std::thread TCPThread(TCPMain,Port);
|
||||
TCPThread.detach();*/
|
||||
//ServerMain(Port, MaxPlayers);
|
||||
NetMain();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user