mirror of
https://github.com/SantaSpeen/BeamMP-Server.git
synced 2026-04-24 12:26:36 +00:00
Compare commits
57 Commits
v1.0
...
v1.20-linu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0b7dd76fd | ||
|
|
fc4bc14ce5 | ||
|
|
61776d6a1b | ||
|
|
0f30706a0a | ||
|
|
cb92833bfd | ||
|
|
a21ca74c58 | ||
|
|
e2611e13e0 | ||
|
|
5fb7c459c6 | ||
|
|
d8e1d389bf | ||
|
|
ae03b5f5ce | ||
|
|
2c6386013d | ||
|
|
3cb4c7cb67 | ||
|
|
229010647c | ||
|
|
03968f34b1 | ||
|
|
941287d22c | ||
|
|
8e4e0c0896 | ||
|
|
c5d1682d5e | ||
|
|
04cf7ca092 | ||
|
|
639c94e0f2 | ||
|
|
623437e864 | ||
|
|
fb420eac1b | ||
|
|
0f33367f6b | ||
|
|
1a2c956d9e | ||
|
|
de859f4762 | ||
|
|
db152e09e9 | ||
|
|
561c0bb381 | ||
|
|
f60a44f65f | ||
|
|
a944565fb9 | ||
|
|
0f4c08c068 | ||
|
|
f0ad3732f4 | ||
|
|
4adfda64c1 | ||
|
|
306fbc5eb4 | ||
|
|
fac1b43b44 | ||
|
|
b22a9566f9 | ||
|
|
6f0c69904c | ||
|
|
e049b1bbf4 | ||
|
|
ef8f8645f7 | ||
|
|
f94252d37b | ||
|
|
8f042a3ee4 | ||
|
|
435c397d02 | ||
|
|
97d8f9506e | ||
|
|
2e7f2cc6bd | ||
|
|
19b7f7f579 | ||
|
|
6a29384b5c | ||
|
|
69da77937d | ||
|
|
5cf97850d7 | ||
|
|
ad844db7fe | ||
|
|
6a8d097dc5 | ||
|
|
e2a45601b3 | ||
|
|
a78f65b274 | ||
|
|
04de729d7c | ||
|
|
667a22b0f8 | ||
|
|
e12b7da27f | ||
|
|
450f6d7139 | ||
|
|
086bcb5ecc | ||
|
|
ac05cb5d0e | ||
|
|
92c44b19c5 |
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/BeamNG-MP-Server.iml" filepath="$PROJECT_DIR$/.idea/BeamNG-MP-Server.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
project(Server)
|
project(Server)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
@@ -7,31 +7,37 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
|||||||
if (UNIX)
|
if (UNIX)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -static-libstdc++")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -static-libstdc++")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -g")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -g")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -s")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -s -fno-builtin")
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
# This might cause issues with old windows headers, but it's worth the trouble to keep the code
|
# This might cause issues with old windows headers, but it's worth the trouble to keep the code
|
||||||
# completely cross platform. For fixes to common issues arising from /permissive- visit:
|
# completely cross platform. For fixes to common issues arising from /permissive- visit:
|
||||||
# https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance
|
# https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /permissive-")
|
|
||||||
|
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /permissive-")
|
||||||
message(STATUS "MSVC -> forcing use of statically-linked runtime.")
|
message(STATUS "MSVC -> forcing use of statically-linked runtime.")
|
||||||
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
||||||
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||||
#-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
|
#-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
find_package(Boost 1.70.0 REQUIRED COMPONENTS system thread)
|
#find_package(Boost 1.70.0 REQUIRED COMPONENTS system thread)
|
||||||
file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "include/*.h" "include/*/*.h" "include/*.hpp" "include/*/*.hpp")
|
|
||||||
|
file(GLOB source_files "src/*.cpp" "include/*.h" "include/*/*.h" "include/*/*/*.h" "include/*.hpp" "include/*/*.hpp" "src/*/*.cpp")
|
||||||
add_executable(BeamMP-Server ${source_files})
|
add_executable(BeamMP-Server ${source_files})
|
||||||
|
|
||||||
target_include_directories(BeamMP-Server SYSTEM PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
target_include_directories(BeamMP-Server PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
||||||
find_package(Lua 5.3 REQUIRED)
|
|
||||||
target_include_directories(BeamMP-Server SYSTEM PUBLIC ${LUA_INCLUDE_DIR} ${Boost_INCLUDE_DIRS})
|
find_package(Lua REQUIRED)
|
||||||
|
target_include_directories(BeamMP-Server PUBLIC ${LUA_INCLUDE_DIR})
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
target_link_libraries(BeamMP-Server curl z pthread stdc++fs ${Boost_LINK_DIRS} ${LUA_LIBRARIES})
|
target_link_libraries(BeamMP-Server z pthread stdc++fs ${Boost_LINK_DIRS} ${LUA_LIBRARIES} curl dl)
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
include(FindLua)
|
include(FindLua)
|
||||||
find_package(CURL CONFIG REQUIRED)
|
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
target_link_libraries(BeamMP-Server PRIVATE urlmon ws2_32 CURL::libcurl ZLIB::ZLIB ${Boost_LINK_DIRS} ${LUA_LIBRARIES})
|
find_package(CURL CONFIG REQUIRED)
|
||||||
|
find_package(RapidJSON CONFIG REQUIRED)
|
||||||
|
target_include_directories(BeamMP-Server PRIVATE ${RAPIDJSON_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(BeamMP-Server PRIVATE ws2_32 CURL::libcurl ZLIB::ZLIB ${LUA_LIBRARIES})
|
||||||
|
#${Boost_LINK_DIRS}
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
1
LICENSE
Normal file
1
LICENSE
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Copyright (c) 2019-present Anonymous275. BeamMP Server code is not in the public domain and is not free software. One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries, the only permission that has been granted is to use the software in its compiled form as distributed from the BeamMP.com website. Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
53
README.md
53
README.md
@@ -1,36 +1,41 @@
|
|||||||
# BeamNG-MP-Server
|
# BeamMP-Server
|
||||||
|
|
||||||
## Unix specific build instructions
|
The Server is the way we link client to each other and handle authentication, compression, and data management. It also allows lua plugins, that system is always being reviewed and improved with detailed instructions on wiki.beammp.com.
|
||||||
|
|
||||||
1. You need boost >= 1.70.0
|
## Supported Operating Systems
|
||||||
|
|
||||||
Check with your ditro's package manager whether it provides this. If it does, you should use that.
|
The code itself supports (latest stable) Linux and Windows. In terms of actual build support, for now we only distribute windows binaries and instructions to build on Debian 10 (stable). For any other distro or OS, you just have to find the same libraries listed in the Linux Build [Prerequisites](#prerequisites) further down the page, and it should build fine. We don't currently support ARM or any big-endian architectures.
|
||||||
|
|
||||||
|
Recommended compilers: MSVC, GCC.
|
||||||
|
|
||||||
If it doesnt provide it or you want to link it statically (like we do with our releases), then you have to do this:
|
## Linux / POSIX specific build instructions
|
||||||
|
|
||||||
download the latest boost source code.
|
Currently only linux and windows are supported (generally). On systems to which we do not provide binaries (so anything but windows), you are allowed to compile the program and use it. Other restrictions, such as not being allowed to distribute those binaries, still apply (see [copyright notice](#copyright)).
|
||||||
Then, go to the downloaded directory and run
|
|
||||||
```sh
|
|
||||||
b2 link=static runtime-link=static threading=multi
|
|
||||||
```
|
|
||||||
And then either symlink, edit CMakeLists to find it, or simply run
|
|
||||||
```sh
|
|
||||||
b2 link=static runtime-link=static threading=multi install
|
|
||||||
```
|
|
||||||
(warning: installs boost into your system, you might not want this).
|
|
||||||
|
|
||||||
Then on invocation of cmake, ensure that you define `Boost_USE_STATIC_RUNTIME=ON`.
|
### Prerequisites
|
||||||
|
|
||||||
|
All package names are ones found in debian's (debian 10 stable) repositories, but will exist under similar names in other distros. Feel free to PR your own guide for a different distro.
|
||||||
|
|
||||||
2. Building
|
- `git`
|
||||||
|
- `make`
|
||||||
|
- `cmake`
|
||||||
|
- `g++` (must support ISO C++17)
|
||||||
|
- `liblua5.3`
|
||||||
|
- `libz-dev`
|
||||||
|
- `rapidjson-dev`
|
||||||
|
- `libcurl4-openssl-dev` (or other `libcurl4-*-dev`)
|
||||||
|
|
||||||
Run cmake, and then make.
|
### How to build
|
||||||
|
|
||||||
Example:
|
1. Make sure you have all [prerequisites](#prerequisites) installed
|
||||||
|
2. Clone the repository in a location of your choice with `git clone --recursive https://github.com/BeamMP/BeamMP-Server`
|
||||||
|
3. `cd` into it with `cd BeamMP-Server`
|
||||||
|
4. Run `cmake .` (with `.`)
|
||||||
|
5. Run `make`
|
||||||
|
6. You will now have a `BeamMP-Server` file in your directory, which is executable with `./BeamMP-Server`. Follow the (windows or linux, doesnt matter) instructions on the [wiki](https://wiki.beammp.com/en/home/Server_Mod) for further setup after installation (which we just did), such as port-forwarding and getting a key to actually run the server.
|
||||||
|
|
||||||
```bash
|
*tip: to run the server in the background, simply (in bash, zsh, etc) run:* `nohup ./BeamMP-Server &`*.*
|
||||||
~/src/Server $ cmake -S . -B bin -DCMAKE_BUILD_TYPE=Release
|
|
||||||
...
|
## Copyright
|
||||||
~/src/Server $ make -C bin -j 5
|
|
||||||
```
|
Copyright (c) 2019-present Anonymous275. BeamMP Server code is not in the public domain and is not free software. One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries, the only permission that has been granted is to use the software in its compiled form as distributed from the BeamMP.com website. Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
|
|||||||
Binary file not shown.
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 5/8/2020
|
/// Created by Anonymous275 on 5/8/2020
|
||||||
///
|
///
|
||||||
@@ -10,11 +14,11 @@
|
|||||||
#define SOCKET int
|
#define SOCKET int
|
||||||
#endif
|
#endif
|
||||||
#include "CustomAssert.h"
|
#include "CustomAssert.h"
|
||||||
#include <string>
|
#include <algorithm>
|
||||||
#include <vector>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <algorithm>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct VData {
|
struct VData {
|
||||||
int ID = -1;
|
int ID = -1;
|
||||||
@@ -24,39 +28,41 @@ struct VData{
|
|||||||
class Client {
|
class Client {
|
||||||
private:
|
private:
|
||||||
std::set<std::unique_ptr<VData>> VehicleData; //ID and Data;
|
std::set<std::unique_ptr<VData>> VehicleData; //ID and Data;
|
||||||
std::string Name = Sec("Unknown Client");
|
std::string Name = "Unknown Client";
|
||||||
|
SOCKET SOCK[2] { SOCKET(-1) };
|
||||||
sockaddr_in UDPADDR;
|
sockaddr_in UDPADDR;
|
||||||
std::string Role;
|
std::string Role;
|
||||||
std::string DID;
|
std::string DID;
|
||||||
SOCKET TCPSOCK;
|
|
||||||
int Status = 0;
|
int Status = 0;
|
||||||
int ID = -1;
|
int ID = -1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
bool isConnected = false;
|
||||||
|
bool isSynced = false;
|
||||||
|
bool isGuest = false;
|
||||||
|
|
||||||
void AddNewCar(int ident, const std::string& Data);
|
void AddNewCar(int ident, const std::string& Data);
|
||||||
void SetCarData(int ident, const std::string& Data);
|
void SetCarData(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);
|
|
||||||
std::set<std::unique_ptr<VData>>& GetAllCars();
|
std::set<std::unique_ptr<VData>>& GetAllCars();
|
||||||
const std::set<std::unique_ptr<VData>>& GetAllCars() const;
|
void SetName(const std::string& name) { Name = name; }
|
||||||
void SetTCPSock(SOCKET CSock);
|
void SetRoles(const std::string& role) { Role = role; }
|
||||||
void SetStatus(int status);
|
std::string GetCarData(int ident);
|
||||||
|
void SetUDPAddr(sockaddr_in Addr) { UDPADDR = Addr; }
|
||||||
|
void SetDownSock(SOCKET CSock) { SOCK[1] = CSock; }
|
||||||
|
void SetTCPSock(SOCKET CSock) { SOCK[0] = CSock; }
|
||||||
|
void SetStatus(int status) { Status = status; }
|
||||||
void DeleteCar(int ident);
|
void DeleteCar(int ident);
|
||||||
sockaddr_in GetUDPAddr();
|
sockaddr_in GetUDPAddr() { return UDPADDR; }
|
||||||
bool isConnected = false;
|
std::string GetRoles() { return Role; }
|
||||||
std::string GetRole();
|
std::string GetName() { return Name; }
|
||||||
std::string GetName();
|
SOCKET GetDownSock() { return SOCK[1]; }
|
||||||
bool isSynced = false;
|
SOCKET GetTCPSock() { return SOCK[0]; }
|
||||||
std::string GetDID();
|
void SetID(int ID) { this->ID = ID; }
|
||||||
SOCKET GetTCPSock();
|
|
||||||
void SetID(int ID);
|
|
||||||
int GetOpenCarID();
|
int GetOpenCarID();
|
||||||
int GetCarCount();
|
int GetCarCount();
|
||||||
void ClearCars();
|
void ClearCars();
|
||||||
int GetStatus();
|
int GetStatus() { return Status; }
|
||||||
int GetID();
|
int GetID() { return ID; }
|
||||||
};
|
};
|
||||||
struct ClientInterface {
|
struct ClientInterface {
|
||||||
std::set<std::unique_ptr<Client>> Clients;
|
std::set<std::unique_ptr<Client>> Clients;
|
||||||
@@ -75,7 +81,7 @@ struct ClientInterface{
|
|||||||
}
|
}
|
||||||
void AddClient(Client*&& c) {
|
void AddClient(Client*&& c) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
Clients.insert(std::move(std::unique_ptr<Client>(c)));
|
Clients.insert(std::unique_ptr<Client>(c));
|
||||||
}
|
}
|
||||||
int Size() {
|
int Size() {
|
||||||
return int(Clients.size());
|
return int(Clients.size());
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/24/2020
|
/// Created by Anonymous275 on 7/24/2020
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/18/2020
|
/// Created by Anonymous275 on 7/18/2020
|
||||||
///
|
///
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
std::string HttpRequest(const std::string& IP, int port);
|
std::string HttpRequest(const std::string& IP, int port);
|
||||||
std::string PostHTTP(const std::string& IP, const std::string& Fields);
|
std::string PostHTTP(const std::string& IP, const std::string& Fields, bool json);
|
||||||
12
include/Json.h
Normal file
12
include/Json.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
|
///
|
||||||
|
/// Created by Anonymous275 on 11/27/2020
|
||||||
|
///
|
||||||
|
#pragma once
|
||||||
|
#include "rapidjson/document.h"
|
||||||
|
#include "rapidjson/stringbuffer.h"
|
||||||
|
#include "rapidjson/writer.h"
|
||||||
|
namespace json = rapidjson;
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 4/2/2020.
|
/// Created by Anonymous275 on 4/2/2020.
|
||||||
///
|
///
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Security/Xor.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -10,7 +14,6 @@ void InitLog();
|
|||||||
#define DebugPrintTID() DebugPrintTIDInternal(__func__, false)
|
#define DebugPrintTID() DebugPrintTIDInternal(__func__, false)
|
||||||
void DebugPrintTIDInternal(const std::string& func, bool overwrite = true); // prints the current thread id in debug mode, to make tracing of crashes and asserts easier
|
void DebugPrintTIDInternal(const std::string& func, bool overwrite = true); // prints the current thread id in debug mode, to make tracing of crashes and asserts easier
|
||||||
void ConsoleOut(const std::string& msg);
|
void ConsoleOut(const std::string& msg);
|
||||||
void QueueAbort();
|
|
||||||
void except(const std::string& toPrint);
|
void except(const std::string& toPrint);
|
||||||
void debug(const std::string& toPrint);
|
void debug(const std::string& toPrint);
|
||||||
void error(const std::string& toPrint);
|
void error(const std::string& toPrint);
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 5/20/2020
|
/// Created by Anonymous275 on 5/20/2020
|
||||||
///
|
///
|
||||||
@@ -72,6 +76,6 @@ public:
|
|||||||
void SetStopThread(bool StopThread) { _StopThread = StopThread; }
|
void SetStopThread(bool StopThread) { _StopThread = StopThread; }
|
||||||
bool GetStopThread() const { return _StopThread; }
|
bool GetStopThread() const { return _StopThread; }
|
||||||
};
|
};
|
||||||
int CallFunction(Lua* lua, const std::string& FuncName, std::unique_ptr<LuaArg> args);
|
std::any CallFunction(Lua* lua, const std::string& FuncName, std::shared_ptr<LuaArg> args);
|
||||||
int TriggerLuaEvent(const std::string& Event, bool local, Lua* Caller, std::unique_ptr<LuaArg> arg, bool Wait);
|
std::any TriggerLuaEvent(const std::string& Event, bool local, Lua* Caller, std::shared_ptr<LuaArg> arg, bool Wait);
|
||||||
extern std::set<std::unique_ptr<Lua>> PluginEngine;
|
extern std::set<std::unique_ptr<Lua>> PluginEngine;
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/31/2020
|
/// Created by Anonymous275 on 7/31/2020
|
||||||
///
|
///
|
||||||
@@ -7,13 +11,15 @@
|
|||||||
void TCPServerMain();
|
void TCPServerMain();
|
||||||
void UpdatePlayers();
|
void UpdatePlayers();
|
||||||
void OnConnect(Client* c);
|
void OnConnect(Client* c);
|
||||||
void InitClient(Client* c);
|
void TCPClient(Client* c);
|
||||||
|
std::string TCPRcv(Client* c);
|
||||||
void SyncResources(Client* c);
|
void SyncResources(Client* c);
|
||||||
[[noreturn]] void UDPServerMain();
|
[[noreturn]] void UDPServerMain();
|
||||||
void OnDisconnect(Client* c, bool kicked);
|
void OnDisconnect(Client* c, bool kicked);
|
||||||
void UDPSend(Client* c, std::string Data);
|
void UDPSend(Client* c, std::string Data);
|
||||||
void TCPSend(Client* c, const std::string& Data);
|
|
||||||
void SendLarge(Client* c, std::string Data);
|
void SendLarge(Client* c, std::string Data);
|
||||||
|
bool TCPSend(Client* c, const std::string& Data);
|
||||||
void GParser(Client* c, const std::string& Packet);
|
void GParser(Client* c, const std::string& Packet);
|
||||||
|
std::string StaticReason(bool Set, const std::string& R);
|
||||||
void Respond(Client* c, const std::string& MSG, bool Rel);
|
void Respond(Client* c, const std::string& MSG, bool Rel);
|
||||||
void SendToAll(Client* c, const std::string& Data, bool Self, bool Rel);
|
void SendToAll(Client* c, const std::string& Data, bool Self, bool Rel);
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/28/2020
|
/// Created by Anonymous275 on 7/28/2020
|
||||||
///
|
///
|
||||||
@@ -7,15 +11,5 @@
|
|||||||
#else
|
#else
|
||||||
#include <WS2tcpip.h>
|
#include <WS2tcpip.h>
|
||||||
#endif
|
#endif
|
||||||
#include "Xor.h"
|
|
||||||
#include <string>
|
#include <string>
|
||||||
struct RSA {
|
|
||||||
int n = 0;
|
|
||||||
int e = 0;
|
|
||||||
int d = 0;
|
|
||||||
};
|
|
||||||
std::string RSA_E(const std::string& Data, int e, int n);
|
|
||||||
std::string RSA_E(const std::string& Data, RSA* k);
|
|
||||||
std::string RSA_D(const std::string& Data, RSA* k);
|
|
||||||
int Handle(EXCEPTION_POINTERS* ep, char* Origin);
|
int Handle(EXCEPTION_POINTERS* ep, char* Origin);
|
||||||
RSA* GenKey();
|
|
||||||
|
|||||||
@@ -1,132 +0,0 @@
|
|||||||
///
|
|
||||||
/// Created by Anonymous275 on 8/11/2020
|
|
||||||
///
|
|
||||||
#pragma once
|
|
||||||
#include <array>
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define BEGIN_NAMESPACE(x) namespace x {
|
|
||||||
#define END_NAMESPACE }
|
|
||||||
|
|
||||||
BEGIN_NAMESPACE(XorCompileTime)
|
|
||||||
|
|
||||||
constexpr auto time = __TIME__;
|
|
||||||
constexpr auto seed = static_cast<int>(time[7]) + static_cast<int>(time[6]) * 10 + static_cast<int>(time[4]) * 60 + static_cast<int>(time[3]) * 600 + static_cast<int>(time[1]) * 3600 + static_cast<int>(time[0]) * 36000;
|
|
||||||
|
|
||||||
// 1988, Stephen Park and Keith Miller
|
|
||||||
// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard"
|
|
||||||
// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation:
|
|
||||||
// with 32-bit math and without division
|
|
||||||
|
|
||||||
template <int N>
|
|
||||||
struct RandomGenerator {
|
|
||||||
private:
|
|
||||||
static constexpr unsigned a = 16807; // 7^5
|
|
||||||
static constexpr unsigned m = 2147483647; // 2^31 - 1
|
|
||||||
|
|
||||||
static constexpr unsigned s = RandomGenerator<N - 1>::value;
|
|
||||||
static constexpr unsigned lo = a * (s & 0xFFFFu); // Multiply lower 16 bits by 16807
|
|
||||||
static constexpr unsigned hi = a * (s >> 16u); // Multiply higher 16 bits by 16807
|
|
||||||
static constexpr unsigned lo2 = lo + ((hi & 0x7FFFu) << 16u); // Combine lower 15 bits of hi with lo's upper bits
|
|
||||||
static constexpr unsigned hi2 = hi >> 15u; // Discard lower 15 bits of hi
|
|
||||||
static constexpr unsigned lo3 = lo2 + hi;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr unsigned max = m;
|
|
||||||
static constexpr unsigned value = lo3 > m ? lo3 - m : lo3;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct RandomGenerator<0> {
|
|
||||||
static constexpr unsigned value = seed;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int N, int M>
|
|
||||||
struct RandomInt {
|
|
||||||
static constexpr auto value = RandomGenerator<N + 1>::value % M;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int N>
|
|
||||||
struct RandomChar {
|
|
||||||
static const char value = static_cast<char>(1 + RandomInt<N, 0x7F - 1>::value);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t N, int K, typename Char>
|
|
||||||
struct XorString {
|
|
||||||
private:
|
|
||||||
const char _key;
|
|
||||||
std::array<Char, N + 1> _encrypted;
|
|
||||||
|
|
||||||
constexpr Char enc(Char c) const {
|
|
||||||
return c ^ _key;
|
|
||||||
}
|
|
||||||
|
|
||||||
Char dec(Char c) const {
|
|
||||||
return c ^ _key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
template <size_t... Is>
|
|
||||||
constexpr inline XorString(const Char* str, std::index_sequence<Is...>)
|
|
||||||
: _key(RandomChar<K>::value)
|
|
||||||
, _encrypted { enc(str[Is])... } { }
|
|
||||||
|
|
||||||
inline decltype(auto) decrypt() {
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
|
||||||
_encrypted[i] = dec(_encrypted[i]);
|
|
||||||
}
|
|
||||||
_encrypted[N] = '\0';
|
|
||||||
return _encrypted.data();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static auto w_printf = [](const char* fmt, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vprintf(fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
};
|
|
||||||
|
|
||||||
static auto w_printf_s = [](const char* fmt, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vprintf(fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*static auto w_sprintf = [](char* buf, const char* fmt, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsprintf(buf, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
};*/
|
|
||||||
|
|
||||||
/*static auto w_sprintf_ret = [](char* buf, const char* fmt, ...) {
|
|
||||||
int ret;
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
ret = vsprintf(buf, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
return ret;
|
|
||||||
};*/
|
|
||||||
|
|
||||||
static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsnprintf(buf, buf_size, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
};
|
|
||||||
|
|
||||||
static auto w_sprintf_s_ret = [](char* buf, size_t buf_size, const char* fmt, ...) {
|
|
||||||
int ret;
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
ret = vsnprintf(buf, buf_size, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
#define Sec(s) [] { constexpr XorCompileTime::XorString< sizeof(s)/sizeof(char) - 1, __COUNTER__, char > expr( s, std::make_index_sequence< sizeof(s)/sizeof(char) - 1>() ); return expr; }().decrypt()
|
|
||||||
#define SecW(s) [] { constexpr XorCompileTime::XorString< sizeof(s)/sizeof(wchar_t) - 1, __COUNTER__, wchar_t > expr( s, std::make_index_sequence< sizeof(s)/sizeof(wchar_t) - 1>() ); return expr; }().decrypt()
|
|
||||||
END_NAMESPACE
|
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/28/2020
|
/// Created by Anonymous275 on 7/28/2020
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/28/2020
|
/// Created by Anonymous275 on 7/28/2020
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -12,8 +12,9 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
// ZeroMemory is just a {0} or a memset(addr, 0, len), and it's a macro on MSVC
|
// ZeroMemory is just a {0} or a memset(addr, 0, len), and it's a macro on MSVC
|
||||||
inline void ZeroMemory(void* dst, size_t len) {
|
inline void ZeroMemory([[maybe_unused]] void* dst, [[maybe_unused]] size_t len) {
|
||||||
Assert(std::memset(dst, 0, len) != nullptr);
|
[[maybe_unused]] auto res = std::memset(dst, 0, len);
|
||||||
|
Assert(res != nullptr);
|
||||||
}
|
}
|
||||||
// provides unix equivalent of closesocket call in win32
|
// provides unix equivalent of closesocket call in win32
|
||||||
inline void CloseSocketProper(int socket) {
|
inline void CloseSocketProper(int socket) {
|
||||||
@@ -30,7 +31,6 @@ inline void CloseSocketProper(int socket) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else // win32
|
#else // win32
|
||||||
|
|
||||||
inline void CloseSocketProper(uint64_t socket) {
|
inline void CloseSocketProper(uint64_t socket) {
|
||||||
shutdown(socket, SD_BOTH);
|
shutdown(socket, SD_BOTH);
|
||||||
closesocket(socket);
|
closesocket(socket);
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/15/2020
|
/// Created by Anonymous275 on 7/15/2020
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 10/29/2020
|
/// Created by Anonymous275 on 10/29/2020
|
||||||
///
|
///
|
||||||
@@ -25,20 +29,17 @@ std::mutex MLock;
|
|||||||
std::unique_ptr<Lua> LuaConsole;
|
std::unique_ptr<Lua> LuaConsole;
|
||||||
void HandleInput(const std::string& cmd) {
|
void HandleInput(const std::string& cmd) {
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
if (cmd == Sec("exit")) {
|
if (cmd == ("exit")) {
|
||||||
_Exit(0);
|
_Exit(0);
|
||||||
} else if (cmd == Sec("clear") || cmd == Sec("cls")) {
|
} else if (cmd == ("clear") || cmd == ("cls")) {
|
||||||
// 2J is clearscreen, H is reset position to top-left
|
// 2J is clearscreen, H is reset position to top-left
|
||||||
ConsoleOut(Sec("\x1b[2J\x1b[H"));
|
ConsoleOut(("\x1b[2J\x1b[H"));
|
||||||
} else {
|
} else {
|
||||||
LuaConsole->Execute(cmd);
|
LuaConsole->Execute(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessOut() {
|
void ProcessOut() {
|
||||||
static size_t len = 2;
|
|
||||||
if (QConsoleOut.empty() && len == CInputBuff.length())
|
|
||||||
return;
|
|
||||||
printf("%c[2K\r", 27);
|
printf("%c[2K\r", 27);
|
||||||
for (const std::string& msg : QConsoleOut)
|
for (const std::string& msg : QConsoleOut)
|
||||||
if (!msg.empty())
|
if (!msg.empty())
|
||||||
@@ -47,7 +48,6 @@ void ProcessOut() {
|
|||||||
QConsoleOut.clear();
|
QConsoleOut.clear();
|
||||||
MLock.unlock();
|
MLock.unlock();
|
||||||
std::cout << "> " << CInputBuff << std::flush;
|
std::cout << "> " << CInputBuff << std::flush;
|
||||||
len = CInputBuff.length();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleOut(const std::string& msg) {
|
void ConsoleOut(const std::string& msg) {
|
||||||
@@ -99,37 +99,56 @@ char _getch(void) {
|
|||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
void SetupConsole() {
|
void SetupConsole() {
|
||||||
#if defined(WIN32) && !defined(DEBUG)
|
#if defined(WIN32)
|
||||||
DWORD outMode = 0;
|
DWORD outMode = 0;
|
||||||
HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
if (stdoutHandle == INVALID_HANDLE_VALUE) {
|
if (stdoutHandle == INVALID_HANDLE_VALUE) {
|
||||||
error("Invalid handle");
|
error("Invalid console handle! Inputs will not work properly");
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
return;
|
||||||
_Exit(GetLastError());
|
|
||||||
}
|
}
|
||||||
if (!GetConsoleMode(stdoutHandle, &outMode)) {
|
if (!GetConsoleMode(stdoutHandle, &outMode)) {
|
||||||
error("Invalid console mode");
|
error("Invalid console mode! Inputs will not work properly");
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
return;
|
||||||
_Exit(GetLastError());
|
|
||||||
}
|
}
|
||||||
// Enable ANSI escape codes
|
// Enable ANSI escape codes
|
||||||
outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
if (!SetConsoleMode(stdoutHandle, outMode)) {
|
if (!SetConsoleMode(stdoutHandle, outMode)) {
|
||||||
error("failed to set console mode");
|
error("failed to set console mode! Inputs will not work properly");
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
return;
|
||||||
_Exit(GetLastError());
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> ConsoleHistory {};
|
static std::vector<std::string> ConsoleHistory {};
|
||||||
|
// buffer used to revert back to what we were writing when we go all the way forward in history
|
||||||
|
static std::string LastInputBuffer {};
|
||||||
static size_t ConsoleHistoryReadIndex { 0 };
|
static size_t ConsoleHistoryReadIndex { 0 };
|
||||||
|
|
||||||
static inline void ConsoleHistoryAdd(const std::string& cmd) {
|
static inline void ConsoleHistoryAdd(const std::string& cmd) {
|
||||||
|
LastInputBuffer.clear();
|
||||||
ConsoleHistory.push_back(cmd);
|
ConsoleHistory.push_back(cmd);
|
||||||
ConsoleHistoryReadIndex = ConsoleHistory.size();
|
ConsoleHistoryReadIndex = ConsoleHistory.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ConsoleHistoryEnsureBounds() {
|
||||||
|
if (ConsoleHistoryReadIndex >= ConsoleHistory.size()) {
|
||||||
|
ConsoleHistoryReadIndex = ConsoleHistory.size() - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ConsoleHistoryGoBack() {
|
||||||
|
if (ConsoleHistoryReadIndex > 0) {
|
||||||
|
--ConsoleHistoryReadIndex;
|
||||||
|
ConsoleHistoryEnsureBounds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ConsoleHistoryGoForward() {
|
||||||
|
++ConsoleHistoryReadIndex;
|
||||||
|
ConsoleHistoryEnsureBounds();
|
||||||
|
}
|
||||||
|
|
||||||
static std::string CompositeInput;
|
static std::string CompositeInput;
|
||||||
static bool CompositeInputExpected { false };
|
static bool CompositeInputExpected { false };
|
||||||
|
|
||||||
@@ -141,11 +160,8 @@ static void ProcessCompositeInput() {
|
|||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
// UP ARROW
|
// UP ARROW
|
||||||
// info(std::to_string(ConsoleHistoryReadIndex));
|
|
||||||
if (!ConsoleHistory.empty()) {
|
if (!ConsoleHistory.empty()) {
|
||||||
if (ConsoleHistoryReadIndex != 0) {
|
ConsoleHistoryGoBack();
|
||||||
ConsoleHistoryReadIndex -= 1;
|
|
||||||
}
|
|
||||||
CInputBuff = ConsoleHistory.at(ConsoleHistoryReadIndex);
|
CInputBuff = ConsoleHistory.at(ConsoleHistoryReadIndex);
|
||||||
}
|
}
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -156,12 +172,11 @@ static void ProcessCompositeInput() {
|
|||||||
|
|
||||||
// DOWN ARROW
|
// DOWN ARROW
|
||||||
if (!ConsoleHistory.empty()) {
|
if (!ConsoleHistory.empty()) {
|
||||||
if (ConsoleHistoryReadIndex != ConsoleHistory.size() - 1) {
|
if (ConsoleHistoryReadIndex == ConsoleHistory.size() - 1) {
|
||||||
ConsoleHistoryReadIndex += 1;
|
CInputBuff = LastInputBuffer;
|
||||||
CInputBuff = ConsoleHistory.at(ConsoleHistoryReadIndex);
|
|
||||||
} else {
|
} else {
|
||||||
CInputBuff = "";
|
ConsoleHistoryGoForward();
|
||||||
ConsoleHistoryReadIndex = ConsoleHistory.size();
|
CInputBuff = ConsoleHistory.at(ConsoleHistoryReadIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -171,17 +186,25 @@ static void ProcessCompositeInput() {
|
|||||||
// ensure history doesnt grow too far beyond a max
|
// ensure history doesnt grow too far beyond a max
|
||||||
static constexpr size_t MaxHistory = 10;
|
static constexpr size_t MaxHistory = 10;
|
||||||
if (ConsoleHistory.size() > 2 * MaxHistory) {
|
if (ConsoleHistory.size() > 2 * MaxHistory) {
|
||||||
std::vector<std::string> NewHistory(ConsoleHistory.begin() + ConsoleHistory.size() - MaxHistory, ConsoleHistory.end());
|
decltype(ConsoleHistory) NewHistory(ConsoleHistory.begin() + ConsoleHistory.size() - MaxHistory, ConsoleHistory.end());
|
||||||
ConsoleHistory = std::move(NewHistory);
|
ConsoleHistory = std::move(NewHistory);
|
||||||
ConsoleHistoryReadIndex = ConsoleHistory.size();
|
ConsoleHistoryReadIndex = ConsoleHistory.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] void ReadCin() {
|
void ReadCin() {
|
||||||
DebugPrintTID();
|
DebugPrintTID();
|
||||||
|
size_t null_byte_counter = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
int In = _getch();
|
int In = _getch();
|
||||||
//info(std::to_string(In));
|
//info(std::to_string(In));
|
||||||
|
if (In == 0) {
|
||||||
|
++null_byte_counter;
|
||||||
|
if (null_byte_counter > 50) {
|
||||||
|
info(("too many null bytes in input, this is now assumed to be a background thread - console input is now disabled"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (CompositeInputExpected) {
|
if (CompositeInputExpected) {
|
||||||
CompositeInput += char(In);
|
CompositeInput += char(In);
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -224,12 +247,14 @@ static void ProcessCompositeInput() {
|
|||||||
// ignore
|
// ignore
|
||||||
} else {
|
} else {
|
||||||
CInputBuff += char(In);
|
CInputBuff += char(In);
|
||||||
|
LastInputBuffer = CInputBuff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ConsoleInit() {
|
void ConsoleInit() {
|
||||||
SetupConsole();
|
SetupConsole();
|
||||||
LuaConsole = std::make_unique<Lua>(true);
|
LuaConsole = std::make_unique<Lua>(true);
|
||||||
|
LuaConsole->Init();
|
||||||
printf("> ");
|
printf("> ");
|
||||||
std::thread In(ReadCin);
|
std::thread In(ReadCin);
|
||||||
In.detach();
|
In.detach();
|
||||||
|
|||||||
121
src/Enc.cpp
121
src/Enc.cpp
@@ -1,102 +1,23 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/28/2020
|
/// Created by Anonymous275 on 7/28/2020
|
||||||
///
|
///
|
||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include "CustomAssert.h"
|
#include "CustomAssert.h"
|
||||||
#include "Settings.h"
|
|
||||||
//#include <windows.h>
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <random>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
int Rand() {
|
|
||||||
std::random_device r;
|
|
||||||
std::default_random_engine e1(r());
|
|
||||||
std::uniform_int_distribution<int> uniform_dist(1, 5000);
|
|
||||||
return uniform_dist(e1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int log_power(int n, unsigned int p, int mod) {
|
|
||||||
int result = 1;
|
|
||||||
for (; p; p >>= 1u) {
|
|
||||||
if (p & 1u)
|
|
||||||
result = int((1LL * result * n) % mod);
|
|
||||||
n = int((1LL * n * n) % mod);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
bool rabin_miller(int n) {
|
|
||||||
bool ok = true;
|
|
||||||
for (int i = 1; i <= 5 && ok; i++) {
|
|
||||||
int a = Rand() + 1;
|
|
||||||
int result = log_power(a, n - 1, n);
|
|
||||||
ok &= (result == 1);
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
int generate_prime() {
|
|
||||||
int generated = Rand();
|
|
||||||
while (!rabin_miller(generated))
|
|
||||||
generated = Rand();
|
|
||||||
return generated;
|
|
||||||
}
|
|
||||||
int gcd(int a, int b) {
|
|
||||||
while (b) {
|
|
||||||
int r = a % b;
|
|
||||||
a = b;
|
|
||||||
b = r;
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
int generate_coprime(int n) {
|
|
||||||
int generated = Rand();
|
|
||||||
while (gcd(n, generated) != 1)
|
|
||||||
generated = Rand();
|
|
||||||
return generated;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<int, int> euclid_extended(int a, int b) {
|
|
||||||
if (!b)
|
|
||||||
return { 1, 0 };
|
|
||||||
auto result = euclid_extended(b, a % b);
|
|
||||||
return { result.second, result.first - (a / b) * result.second };
|
|
||||||
}
|
|
||||||
|
|
||||||
int modular_inverse(int n, int mod) {
|
|
||||||
int inverse = euclid_extended(n, mod).first;
|
|
||||||
while (inverse < 0)
|
|
||||||
inverse += mod;
|
|
||||||
return inverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
RSA* GenKey() {
|
|
||||||
int p, q;
|
|
||||||
p = generate_prime();
|
|
||||||
q = generate_prime();
|
|
||||||
int n = p * q;
|
|
||||||
int phi = (p - 1) * (q - 1);
|
|
||||||
int e = generate_coprime(phi);
|
|
||||||
int d = modular_inverse(e, phi);
|
|
||||||
return new RSA { n, e, d };
|
|
||||||
}
|
|
||||||
|
|
||||||
int Enc(int value, int e, int n) {
|
|
||||||
return log_power(value, e, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Dec(int value, int d, int n) {
|
|
||||||
return log_power(value, d, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
#include <WS2tcpip.h>
|
||||||
int Handle(EXCEPTION_POINTERS* ep, char* Origin) {
|
int Handle(EXCEPTION_POINTERS* ep, char* Origin) {
|
||||||
//Assert(false);
|
Assert(false);
|
||||||
std::stringstream R;
|
std::stringstream R;
|
||||||
R << Sec("Code : ") << std::hex
|
R << ("Code : ") << std::hex
|
||||||
<< ep->ExceptionRecord->ExceptionCode
|
<< ep->ExceptionRecord->ExceptionCode
|
||||||
<< std::dec << Sec(" Origin : ") << Origin;
|
<< std::dec << (" Origin : ") << Origin;
|
||||||
except(R.str());
|
except(R.str());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -104,29 +25,3 @@ int Handle(EXCEPTION_POINTERS* ep, char* Origin) {
|
|||||||
// stub
|
// stub
|
||||||
int Handle(EXCEPTION_POINTERS*, char*) { return 1; }
|
int Handle(EXCEPTION_POINTERS*, char*) { return 1; }
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
std::string RSA_E(const std::string& Data, RSA* k) {
|
|
||||||
std::stringstream stream;
|
|
||||||
for (const char& c : Data) {
|
|
||||||
stream << std::hex << Enc(uint8_t(c), k->e, k->n) << "g";
|
|
||||||
}
|
|
||||||
return stream.str();
|
|
||||||
}
|
|
||||||
std::string RSA_E(const std::string& Data, int e, int n) {
|
|
||||||
std::stringstream stream;
|
|
||||||
for (const char& c : Data) {
|
|
||||||
stream << std::hex << Enc(uint8_t(c), e, n) << "g";
|
|
||||||
}
|
|
||||||
return stream.str();
|
|
||||||
}
|
|
||||||
std::string RSA_D(const std::string& Data, RSA* k) {
|
|
||||||
std::stringstream ss(Data);
|
|
||||||
std::string token, ret;
|
|
||||||
while (std::getline(ss, token, 'g')) {
|
|
||||||
if (token.find_first_not_of(Sec("0123456789abcdef")) != std::string::npos)
|
|
||||||
return "";
|
|
||||||
int c = std::stoi(token, nullptr, 16);
|
|
||||||
ret += char(Dec(c, k->d, k->n));
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/28/2020
|
/// Created by Anonymous275 on 7/28/2020
|
||||||
///
|
///
|
||||||
@@ -91,13 +95,13 @@ void LoadConfig(std::ifstream& IFS) {
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
if (index - 1 < 11) {
|
if (index - 1 < 11) {
|
||||||
error(Sec("Outdated/Incorrect config please remove it server will close in 5 secs"));
|
error(("Outdated/Incorrect config please remove it server will close in 5 secs"));
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||||
_Exit(0);
|
_Exit(0);
|
||||||
}
|
}
|
||||||
IFS.close();
|
IFS.close();
|
||||||
IFS.open(Sec("Server.cfg"));
|
IFS.open(("Server.cfg"));
|
||||||
info(Sec("Config found updating values"));
|
info(("Config found updating values"));
|
||||||
index = 1;
|
index = 1;
|
||||||
while (getline(IFS, line)) {
|
while (getline(IFS, line)) {
|
||||||
if (line.rfind('#', 0) != 0 && line.rfind(' ', 0) != 0) { //Checks if it starts as Comment
|
if (line.rfind('#', 0) != 0 && line.rfind(' ', 0) != 0) { //Checks if it starts as Comment
|
||||||
@@ -109,8 +113,8 @@ void LoadConfig(std::ifstream& IFS) {
|
|||||||
}
|
}
|
||||||
void GenerateConfig() {
|
void GenerateConfig() {
|
||||||
std::ofstream FileStream;
|
std::ofstream FileStream;
|
||||||
FileStream.open(Sec("Server.cfg"));
|
FileStream.open(("Server.cfg"));
|
||||||
FileStream << Sec("# This is the BeamMP Server Configuration File v0.60\n"
|
FileStream << ("# This is the BeamMP Server Configuration File v0.60\n"
|
||||||
"Debug = false # true or false to enable debug console output\n"
|
"Debug = false # true or false to enable debug console output\n"
|
||||||
"Private = true # Private?\n"
|
"Private = true # Private?\n"
|
||||||
"Port = 30814 # Port to run the server on UDP and TCP\n"
|
"Port = 30814 # Port to run the server on UDP and TCP\n"
|
||||||
@@ -124,27 +128,29 @@ void GenerateConfig() {
|
|||||||
FileStream.close();
|
FileStream.close();
|
||||||
}
|
}
|
||||||
void Default() {
|
void Default() {
|
||||||
info(Sec("Config not found generating default"));
|
info(("Config not found generating default"));
|
||||||
GenerateConfig();
|
GenerateConfig();
|
||||||
error(Sec("You are required to input the AuthKey"));
|
error(("You are required to input the AuthKey"));
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||||
_Exit(0);
|
_Exit(0);
|
||||||
}
|
}
|
||||||
void DebugData() {
|
void DebugData() {
|
||||||
debug(std::string(Sec("Debug : ")) + (Debug ? "true" : "false"));
|
debug(std::string("Debug : ") + (Debug ? "true" : "false"));
|
||||||
debug(std::string(Sec("Private : ")) + (Private ? "true" : "false"));
|
debug(std::string("Private : ") + (Private ? "true" : "false"));
|
||||||
debug(Sec("Port : ") + std::to_string(Port));
|
debug("Port : " + std::to_string(Port));
|
||||||
debug(Sec("Max Cars : ") + std::to_string(MaxCars));
|
debug("Max Cars : " + std::to_string(MaxCars));
|
||||||
debug(Sec("MaxPlayers : ") + std::to_string(MaxPlayers));
|
debug("MaxPlayers : " + std::to_string(MaxPlayers));
|
||||||
debug(Sec("MapName : ") + MapName);
|
debug("MapName : " + MapName);
|
||||||
debug(Sec("ServerName : ") + ServerName);
|
debug("ServerName : " + ServerName);
|
||||||
debug(Sec("ServerDesc : ") + ServerDesc);
|
debug("ServerDesc : " + ServerDesc);
|
||||||
debug(Sec("File : ") + Resource);
|
debug("File : " + Resource);
|
||||||
debug(Sec("Key length: ") + std::to_string(Key.length()));
|
debug("Key length: " + std::to_string(Key.length()));
|
||||||
}
|
}
|
||||||
void InitConfig() {
|
void InitConfig() {
|
||||||
|
////TODO: Move to json after update 4
|
||||||
|
|
||||||
std::ifstream IFS;
|
std::ifstream IFS;
|
||||||
IFS.open(Sec("Server.cfg"));
|
IFS.open(("Server.cfg"));
|
||||||
if (IFS.good())
|
if (IFS.good())
|
||||||
LoadConfig(IFS);
|
LoadConfig(IFS);
|
||||||
else
|
else
|
||||||
@@ -152,7 +158,7 @@ void InitConfig() {
|
|||||||
if (IFS.is_open())
|
if (IFS.is_open())
|
||||||
IFS.close();
|
IFS.close();
|
||||||
if (Key.empty()) {
|
if (Key.empty()) {
|
||||||
error(Sec("No AuthKey was found"));
|
error(("No AuthKey was found"));
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||||
_Exit(0);
|
_Exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/28/2020
|
/// Created by Anonymous275 on 7/28/2020
|
||||||
///
|
///
|
||||||
#include "Client.hpp"
|
#include "Client.hpp"
|
||||||
#include "Curl/Http.h"
|
#include "Curl/Http.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Security/Enc.h"
|
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <future>
|
#include <future>
|
||||||
@@ -34,19 +37,18 @@ std::string GenerateCall() {
|
|||||||
return Ret.str();
|
return Ret.str();
|
||||||
}
|
}
|
||||||
std::string RunPromise(const std::string& IP, const std::string& R) {
|
std::string RunPromise(const std::string& IP, const std::string& R) {
|
||||||
std::packaged_task<std::string()> task([&]() { return PostHTTP(IP, R); });
|
std::packaged_task<std::string()> task([&] { return PostHTTP(IP, R, false); });
|
||||||
std::future<std::string> f1 = task.get_future();
|
std::future<std::string> f1 = task.get_future();
|
||||||
std::thread t(std::move(task));
|
std::thread t(std::move(task));
|
||||||
t.detach();
|
t.detach();
|
||||||
auto status = f1.wait_for(std::chrono::seconds(10));
|
auto status = f1.wait_for(std::chrono::seconds(15));
|
||||||
if (status != std::future_status::timeout)
|
if (status != std::future_status::timeout)
|
||||||
return f1.get();
|
return f1.get();
|
||||||
error(Sec("Backend system Timeout please try again later"));
|
error("Backend system Timeout please try again later");
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
return "";
|
||||||
_Exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heartbeat() {
|
[[noreturn]] void Heartbeat() {
|
||||||
DebugPrintTID();
|
DebugPrintTID();
|
||||||
std::string R, T;
|
std::string R, T;
|
||||||
bool isAuth = false;
|
bool isAuth = false;
|
||||||
@@ -54,29 +56,26 @@ void Heartbeat() {
|
|||||||
R = GenerateCall();
|
R = GenerateCall();
|
||||||
if (!CustomIP.empty())
|
if (!CustomIP.empty())
|
||||||
R += "&ip=" + CustomIP;
|
R += "&ip=" + CustomIP;
|
||||||
std::string link = Sec("https://beammp.com/heartbeatv2");
|
std::string link = "https://beammp.com/heartbeatv2";
|
||||||
T = RunPromise(link, R);
|
T = RunPromise(link, R);
|
||||||
if (T.find_first_not_of(Sec("20")) != std::string::npos) {
|
|
||||||
|
if (T.substr(0, 2) != "20") {
|
||||||
//Backend system refused server startup!
|
//Backend system refused server startup!
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||||
std::string Backup = Sec("https://backup1.beammp.com/heartbeatv2");
|
std::string Backup = "https://backup1.beammp.com/heartbeatv2";
|
||||||
T = RunPromise(Backup, R);
|
T = RunPromise(Backup, R);
|
||||||
if (T.find_first_not_of(Sec("20")) != std::string::npos) {
|
if (T.substr(0, 2) != "20") {
|
||||||
error(Sec("Backend system refused server! Check your AuthKey"));
|
warn("Backend system refused server! Server might not show in the public list");
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
|
||||||
_Exit(-1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Server Authenticated
|
//Server Authenticated
|
||||||
if (T.length() == 4)
|
|
||||||
info(Sec("Server authenticated"));
|
|
||||||
R.clear();
|
|
||||||
T.clear();
|
|
||||||
if (!isAuth) {
|
if (!isAuth) {
|
||||||
WebsocketInit();
|
WebsocketInit();
|
||||||
|
if (T.length() == 4)info(("Authenticated!"));
|
||||||
|
else info(("Resumed authenticated session!"));
|
||||||
isAuth = true;
|
isAuth = true;
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
//std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void HBInit() {
|
void HBInit() {
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/28/2020
|
/// Created by Anonymous275 on 7/28/2020
|
||||||
///
|
///
|
||||||
@@ -15,22 +19,21 @@ std::string FileList;
|
|||||||
int ModsLoaded = 0;
|
int ModsLoaded = 0;
|
||||||
|
|
||||||
void InitRes() {
|
void InitRes() {
|
||||||
std::string Path = Resource + Sec("/Client");
|
std::string Path = Resource + "/Client";
|
||||||
if (!fs::exists(Path))
|
if (!fs::exists(Path))
|
||||||
fs::create_directory(Path);
|
fs::create_directory(Path);
|
||||||
for (const auto& entry : fs::directory_iterator(Path)) {
|
for (const auto& entry : fs::directory_iterator(Path)) {
|
||||||
auto pos = entry.path().string().find(Sec(".zip"));
|
auto pos = entry.path().string().find(".zip");
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
if (entry.path().string().length() - pos == 4) {
|
if (entry.path().string().length() - pos == 4) {
|
||||||
FileList += entry.path().string() + ";";
|
FileList += entry.path().string() + ";";
|
||||||
FileSizes += std::to_string(fs::file_size(entry.path())) + ";";
|
FileSizes += std::to_string(uint64_t(fs::file_size(entry.path()))) + ";";
|
||||||
MaxModSize += fs::file_size(entry.path());
|
MaxModSize += uint64_t(fs::file_size(entry.path()));
|
||||||
ModsLoaded++;
|
ModsLoaded++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::replace(FileList.begin(), FileList.end(), '\\', '/');
|
std::replace(FileList.begin(), FileList.end(), '\\', '/');
|
||||||
if (ModsLoaded) {
|
if (ModsLoaded)
|
||||||
info(Sec("Loaded ") + std::to_string(ModsLoaded) + Sec(" Mods"));
|
info("Loaded " + std::to_string(ModsLoaded) + " Mods");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/28/2020
|
/// Created by Anonymous275 on 7/28/2020
|
||||||
///
|
///
|
||||||
@@ -9,24 +13,22 @@
|
|||||||
|
|
||||||
std::string CustomIP;
|
std::string CustomIP;
|
||||||
std::string GetSVer() {
|
std::string GetSVer() {
|
||||||
static std::string r = Sec("1.0");
|
return "1.20";
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
std::string GetCVer() {
|
std::string GetCVer() {
|
||||||
static std::string r = Sec("1.70");
|
return "1.80";
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
void Args(int argc, char* argv[]) {
|
void Args(int argc, char* argv[]) {
|
||||||
info(Sec("BeamMP Server Running version ") + GetSVer());
|
info("BeamMP Server Running version " + GetSVer());
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
CustomIP = argv[1];
|
CustomIP = argv[1];
|
||||||
size_t n = std::count(CustomIP.begin(), CustomIP.end(), '.');
|
size_t n = std::count(CustomIP.begin(), CustomIP.end(), '.');
|
||||||
auto p = CustomIP.find_first_not_of(Sec(".0123456789"));
|
auto p = CustomIP.find_first_not_of((".0123456789"));
|
||||||
if (p != std::string::npos || n != 3 || CustomIP.substr(0, 3) == Sec("127")) {
|
if (p != std::string::npos || n != 3 || CustomIP.substr(0, 3) == ("127")) {
|
||||||
CustomIP.clear();
|
CustomIP.clear();
|
||||||
warn(Sec("IP Specified is invalid! Ignoring"));
|
warn("IP Specified is invalid! Ignoring");
|
||||||
} else
|
} else
|
||||||
info(Sec("Server started with custom IP"));
|
info("Server started with custom IP");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void InitServer(int argc, char* argv[]) {
|
void InitServer(int argc, char* argv[]) {
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 5/20/2020
|
/// Created by Anonymous275 on 5/20/2020
|
||||||
///
|
///
|
||||||
@@ -24,9 +28,9 @@ bool NewFile(const std::string& Path) {
|
|||||||
void RegisterFiles(const std::string& Path, bool HotSwap) {
|
void RegisterFiles(const std::string& Path, bool HotSwap) {
|
||||||
std::string Name = Path.substr(Path.find_last_of('\\') + 1);
|
std::string Name = Path.substr(Path.find_last_of('\\') + 1);
|
||||||
if (!HotSwap)
|
if (!HotSwap)
|
||||||
info(Sec("Loading plugin : ") + Name);
|
info(("Loading plugin : ") + Name);
|
||||||
for (const auto& entry : fs::directory_iterator(Path)) {
|
for (const auto& entry : fs::directory_iterator(Path)) {
|
||||||
auto pos = entry.path().string().find(Sec(".lua"));
|
auto pos = entry.path().string().find((".lua"));
|
||||||
if (pos != std::string::npos && entry.path().string().length() - pos == 4) {
|
if (pos != std::string::npos && entry.path().string().length() - pos == 4) {
|
||||||
if (!HotSwap || NewFile(entry.path().string())) {
|
if (!HotSwap || NewFile(entry.path().string())) {
|
||||||
auto FileName = entry.path().string();
|
auto FileName = entry.path().string();
|
||||||
@@ -35,7 +39,7 @@ void RegisterFiles(const std::string& Path, bool HotSwap) {
|
|||||||
PluginEngine.insert(std::move(ScriptToInsert));
|
PluginEngine.insert(std::move(ScriptToInsert));
|
||||||
Script.Init();
|
Script.Init();
|
||||||
if (HotSwap)
|
if (HotSwap)
|
||||||
info(Sec("[HOTSWAP] Added : ") + Script.GetFileName().substr(Script.GetFileName().find('\\')));
|
info(("[HOTSWAP] Added : ") + Script.GetFileName().substr(Script.GetFileName().find('\\')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,12 +61,12 @@ void FolderList(const std::string& Path, bool HotSwap) {
|
|||||||
if (stat(Script->GetFileName().c_str(), &Info) != 0) {
|
if (stat(Script->GetFileName().c_str(), &Info) != 0) {
|
||||||
Script->SetStopThread(true);
|
Script->SetStopThread(true);
|
||||||
PluginEngine.erase(Script);
|
PluginEngine.erase(Script);
|
||||||
info(Sec("[HOTSWAP] Removed : ") + Script->GetFileName().substr(Script->GetFileName().find('\\')));
|
info(("[HOTSWAP] Removed removed script due to delete"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (Script->GetLastWrite() != fs::last_write_time(Script->GetFileName())) {
|
if (Script->GetLastWrite() != fs::last_write_time(Script->GetFileName())) {
|
||||||
Script->SetStopThread(true);
|
Script->SetStopThread(true);
|
||||||
info(Sec("[HOTSWAP] Updated : ") + Script->GetFileName().substr(Script->GetFileName().find('\\')));
|
info(("[HOTSWAP] Updated Scripts due to edit"));
|
||||||
Script->SetLastWrite(fs::last_write_time(Script->GetFileName()));
|
Script->SetLastWrite(fs::last_write_time(Script->GetFileName()));
|
||||||
Script->Reload();
|
Script->Reload();
|
||||||
}
|
}
|
||||||
@@ -77,12 +81,12 @@ void InitLua() {
|
|||||||
if (!fs::exists(Resource)) {
|
if (!fs::exists(Resource)) {
|
||||||
fs::create_directory(Resource);
|
fs::create_directory(Resource);
|
||||||
}
|
}
|
||||||
std::string Path = Resource + Sec("/Server");
|
std::string Path = Resource + ("/Server");
|
||||||
if (!fs::exists(Path)) {
|
if (!fs::exists(Path)) {
|
||||||
fs::create_directory(Path);
|
fs::create_directory(Path);
|
||||||
}
|
}
|
||||||
FolderList(Path, false);
|
FolderList(Path, false);
|
||||||
std::thread t1(HotSwaps, Path);
|
std::thread t1(HotSwaps, Path);
|
||||||
t1.detach();
|
t1.detach();
|
||||||
info(Sec("Lua system online"));
|
info(("Lua system online"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 5/19/2020
|
/// Created by Anonymous275 on 5/19/2020
|
||||||
///
|
///
|
||||||
@@ -14,10 +18,10 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
std::unique_ptr<LuaArg> CreateArg(lua_State* L, int T, int S) {
|
std::shared_ptr<LuaArg> CreateArg(lua_State* L, int T, int S) {
|
||||||
if (S > T)
|
if (S > T)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
std::unique_ptr<LuaArg> temp(new LuaArg);
|
std::shared_ptr<LuaArg> temp(new LuaArg);
|
||||||
for (int C = S; C <= T; C++) {
|
for (int C = S; C <= T; C++) {
|
||||||
if (lua_isstring(L, C)) {
|
if (lua_isstring(L, C)) {
|
||||||
temp->args.emplace_back(std::string(lua_tostring(L, C)));
|
temp->args.emplace_back(std::string(lua_tostring(L, C)));
|
||||||
@@ -46,18 +50,18 @@ void SendError(lua_State* L, const std::string& msg) {
|
|||||||
auto MaybeS = GetScript(L);
|
auto MaybeS = GetScript(L);
|
||||||
std::string a;
|
std::string a;
|
||||||
if (!MaybeS.has_value()) {
|
if (!MaybeS.has_value()) {
|
||||||
a = Sec("_Console");
|
a = ("_Console");
|
||||||
} else {
|
} else {
|
||||||
Lua& S = MaybeS.value();
|
Lua& S = MaybeS.value();
|
||||||
a = fs::path(S.GetFileName()).filename().string();
|
a = fs::path(S.GetFileName()).filename().string();
|
||||||
}
|
}
|
||||||
warn(a + Sec(" | Incorrect Call of ") + msg);
|
warn(a + (" | Incorrect Call of ") + msg);
|
||||||
}
|
}
|
||||||
int Trigger(Lua* lua, const std::string& R, std::unique_ptr<LuaArg> arg) {
|
std::any Trigger(Lua* lua, const std::string& R, std::shared_ptr<LuaArg> arg) {
|
||||||
std::lock_guard<std::mutex> lockGuard(lua->Lock);
|
std::lock_guard<std::mutex> lockGuard(lua->Lock);
|
||||||
std::packaged_task<int(std::unique_ptr<LuaArg>)> task([lua, R](std::unique_ptr<LuaArg> arg) { return CallFunction(lua, R, std::move(arg)); });
|
std::packaged_task<std::any(std::shared_ptr<LuaArg>)> task([lua, R](std::shared_ptr<LuaArg> arg) { return CallFunction(lua, R, arg); });
|
||||||
std::future<int> f1 = task.get_future();
|
std::future<std::any> f1 = task.get_future();
|
||||||
std::thread t(std::move(task), std::move(arg));
|
std::thread t(std::move(task), arg);
|
||||||
t.detach();
|
t.detach();
|
||||||
auto status = f1.wait_for(std::chrono::seconds(5));
|
auto status = f1.wait_for(std::chrono::seconds(5));
|
||||||
if (status != std::future_status::timeout)
|
if (status != std::future_status::timeout)
|
||||||
@@ -65,11 +69,11 @@ int Trigger(Lua* lua, const std::string& R, std::unique_ptr<LuaArg> arg) {
|
|||||||
SendError(lua->GetState(), R + " took too long to respond");
|
SendError(lua->GetState(), R + " took too long to respond");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int FutureWait(Lua* lua, const std::string& R, std::unique_ptr<LuaArg> arg, bool Wait) {
|
std::any FutureWait(Lua* lua, const std::string& R, std::shared_ptr<LuaArg> arg, bool Wait) {
|
||||||
Assert(lua);
|
Assert(lua);
|
||||||
std::packaged_task<int(std::unique_ptr<LuaArg>)> task([lua, R](std::unique_ptr<LuaArg> arg) { return Trigger(lua, R, std::move(arg)); });
|
std::packaged_task<std::any(std::shared_ptr<LuaArg>)> task([lua, R](std::shared_ptr<LuaArg> arg) { return Trigger(lua, R, arg); });
|
||||||
std::future<int> f1 = task.get_future();
|
std::future<std::any> f1 = task.get_future();
|
||||||
std::thread t(std::move(task), std::move(arg));
|
std::thread t(std::move(task), arg);
|
||||||
t.detach();
|
t.detach();
|
||||||
int T = 0;
|
int T = 0;
|
||||||
if (Wait)
|
if (Wait)
|
||||||
@@ -79,24 +83,39 @@ int FutureWait(Lua* lua, const std::string& R, std::unique_ptr<LuaArg> arg, bool
|
|||||||
return f1.get();
|
return f1.get();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int TriggerLuaEvent(const std::string& Event, bool local, Lua* Caller, std::unique_ptr<LuaArg> arg, bool Wait) {
|
std::any TriggerLuaEvent(const std::string& Event, bool local, Lua* Caller, std::shared_ptr<LuaArg> arg, bool Wait) {
|
||||||
int R = 0;
|
std::any R;
|
||||||
|
std::string Type;
|
||||||
|
int Ret = 0;
|
||||||
for (auto& Script : PluginEngine) {
|
for (auto& Script : PluginEngine) {
|
||||||
if (Script->IsRegistered(Event)) {
|
if (Script->IsRegistered(Event)) {
|
||||||
if (local) {
|
if (local) {
|
||||||
if (Script->GetPluginName() == Caller->GetPluginName()) {
|
if (Script->GetPluginName() == Caller->GetPluginName()) {
|
||||||
R += FutureWait(Script.get(), Script->GetRegistered(Event), std::move(arg), Wait);
|
R = FutureWait(Script.get(), Script->GetRegistered(Event), arg, Wait);
|
||||||
}
|
Type = R.type().name();
|
||||||
} else
|
if (Type.find("int") != std::string::npos) {
|
||||||
R += FutureWait(Script.get(), Script->GetRegistered(Event), std::move(arg), Wait);
|
if (std::any_cast<int>(R))
|
||||||
}
|
Ret++;
|
||||||
}
|
} else if (Event == "onPlayerAuth")
|
||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
R = FutureWait(Script.get(), Script->GetRegistered(Event), arg, Wait);
|
||||||
|
Type = R.type().name();
|
||||||
|
if (Type.find("int") != std::string::npos) {
|
||||||
|
if (std::any_cast<int>(R))
|
||||||
|
Ret++;
|
||||||
|
} else if (Event == "onPlayerAuth")
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
bool ConsoleCheck(lua_State* L, int r) {
|
bool ConsoleCheck(lua_State* L, int r) {
|
||||||
if (r != LUA_OK) {
|
if (r != LUA_OK) {
|
||||||
std::string msg = lua_tostring(L, -1);
|
std::string msg = lua_tostring(L, -1);
|
||||||
warn(Sec("_Console | ") + msg);
|
warn(("_Console | ") + msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -125,7 +144,7 @@ int lua_RegisterEvent(lua_State* L) {
|
|||||||
if (Args == 2 && lua_isstring(L, 1) && lua_isstring(L, 2)) {
|
if (Args == 2 && lua_isstring(L, 1) && lua_isstring(L, 2)) {
|
||||||
Script.RegisterEvent(lua_tostring(L, 1), lua_tostring(L, 2));
|
Script.RegisterEvent(lua_tostring(L, 1), lua_tostring(L, 2));
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("RegisterEvent invalid argument count expected 2 got ") + std::to_string(Args));
|
SendError(L, ("RegisterEvent invalid argument count expected 2 got ") + std::to_string(Args));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_TriggerEventL(lua_State* L) {
|
int lua_TriggerEventL(lua_State* L) {
|
||||||
@@ -137,9 +156,9 @@ int lua_TriggerEventL(lua_State* L) {
|
|||||||
if (lua_isstring(L, 1)) {
|
if (lua_isstring(L, 1)) {
|
||||||
TriggerLuaEvent(lua_tostring(L, 1), true, &Script, CreateArg(L, Args, 2), false);
|
TriggerLuaEvent(lua_tostring(L, 1), true, &Script, CreateArg(L, Args, 2), false);
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("TriggerLocalEvent wrong argument [1] need string"));
|
SendError(L, ("TriggerLocalEvent wrong argument [1] need string"));
|
||||||
} else {
|
} else {
|
||||||
SendError(L, Sec("TriggerLocalEvent not enough arguments expected 1 got 0"));
|
SendError(L, ("TriggerLocalEvent not enough arguments expected 1 got 0"));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -153,9 +172,9 @@ int lua_TriggerEventG(lua_State* L) {
|
|||||||
if (lua_isstring(L, 1)) {
|
if (lua_isstring(L, 1)) {
|
||||||
TriggerLuaEvent(lua_tostring(L, 1), false, &Script, CreateArg(L, Args, 2), false);
|
TriggerLuaEvent(lua_tostring(L, 1), false, &Script, CreateArg(L, Args, 2), false);
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("TriggerGlobalEvent wrong argument [1] need string"));
|
SendError(L, ("TriggerGlobalEvent wrong argument [1] need string"));
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("TriggerGlobalEvent not enough arguments"));
|
SendError(L, ("TriggerGlobalEvent not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,13 +239,13 @@ int lua_CreateThread(lua_State* L) {
|
|||||||
std::thread t1(CallAsync, &Script, STR, U);
|
std::thread t1(CallAsync, &Script, STR, U);
|
||||||
t1.detach();
|
t1.detach();
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("CreateThread wrong argument [2] number must be between 1 and 500"));
|
SendError(L, ("CreateThread wrong argument [2] number must be between 1 and 500"));
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("CreateThread wrong argument [2] need number"));
|
SendError(L, ("CreateThread wrong argument [2] need number"));
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("CreateThread wrong argument [1] need string"));
|
SendError(L, ("CreateThread wrong argument [1] need string"));
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("CreateThread not enough arguments"));
|
SendError(L, ("CreateThread not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_Sleep(lua_State* L) {
|
int lua_Sleep(lua_State* L) {
|
||||||
@@ -234,7 +253,7 @@ int lua_Sleep(lua_State* L) {
|
|||||||
int t = int(lua_tonumber(L, 1));
|
int t = int(lua_tonumber(L, 1));
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(t));
|
std::this_thread::sleep_for(std::chrono::milliseconds(t));
|
||||||
} else {
|
} else {
|
||||||
SendError(L, Sec("Sleep not enough arguments"));
|
SendError(L, ("Sleep not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -256,7 +275,7 @@ int lua_isConnected(lua_State* L) {
|
|||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
SendError(L, Sec("isConnected not enough arguments"));
|
SendError(L, ("isConnected not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -270,7 +289,7 @@ int lua_GetPlayerName(lua_State* L) {
|
|||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
SendError(L, Sec("GetPlayerName not enough arguments"));
|
SendError(L, ("GetPlayerName not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -279,16 +298,16 @@ int lua_GetPlayerCount(lua_State* L) {
|
|||||||
lua_pushinteger(L, CI->Size());
|
lua_pushinteger(L, CI->Size());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int lua_GetDID(lua_State* L) {
|
int lua_GetGuest(lua_State* L) {
|
||||||
if (lua_isnumber(L, 1)) {
|
if (lua_isnumber(L, 1)) {
|
||||||
int ID = int(lua_tonumber(L, 1));
|
int ID = int(lua_tonumber(L, 1));
|
||||||
Client* c = GetClient(ID);
|
Client* c = GetClient(ID);
|
||||||
if (c != nullptr)
|
if (c != nullptr)
|
||||||
lua_pushstring(L, c->GetDID().c_str());
|
lua_pushboolean(L, c->isGuest);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
SendError(L, Sec("GetDID not enough arguments"));
|
SendError(L, "GetGuest not enough arguments");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -327,7 +346,7 @@ int lua_GetCars(lua_State* L) {
|
|||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
SendError(L, Sec("GetPlayerVehicles not enough arguments"));
|
SendError(L, ("GetPlayerVehicles not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -339,19 +358,16 @@ int lua_dropPlayer(lua_State* L) {
|
|||||||
Client* c = GetClient(ID);
|
Client* c = GetClient(ID);
|
||||||
if (c == nullptr)
|
if (c == nullptr)
|
||||||
return 0;
|
return 0;
|
||||||
if (c->GetRole() == Sec("MDEV"))
|
|
||||||
return 0;
|
|
||||||
std::string Reason;
|
std::string Reason;
|
||||||
if (Args > 1 && lua_isstring(L, 2)) {
|
if (Args > 1 && lua_isstring(L, 2)) {
|
||||||
Reason = std::string(Sec(" Reason : ")) + lua_tostring(L, 2);
|
Reason = std::string((" Reason : ")) + lua_tostring(L, 2);
|
||||||
}
|
}
|
||||||
Respond(c, "C:Server:You have been Kicked from the server! " + Reason, true);
|
Respond(c, "C:Server:You have been Kicked from the server! " + Reason, true);
|
||||||
c->SetStatus(-2);
|
c->SetStatus(-2);
|
||||||
info(Sec("Closing socket due to kick"));
|
info(("Closing socket due to kick"));
|
||||||
CloseSocketProper(c->GetTCPSock());
|
CloseSocketProper(c->GetTCPSock());
|
||||||
|
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("DropPlayer not enough arguments"));
|
SendError(L, ("DropPlayer not enough arguments"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_sendChat(lua_State* L) {
|
int lua_sendChat(lua_State* L) {
|
||||||
@@ -369,18 +385,18 @@ int lua_sendChat(lua_State* L) {
|
|||||||
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2));
|
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2));
|
||||||
Respond(c, Packet, true);
|
Respond(c, Packet, true);
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("SendChatMessage invalid argument [1] invalid ID"));
|
SendError(L, ("SendChatMessage invalid argument [1] invalid ID"));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("SendChatMessage invalid argument [2] expected string"));
|
SendError(L, ("SendChatMessage invalid argument [2] expected string"));
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("SendChatMessage invalid argument [1] expected number"));
|
SendError(L, ("SendChatMessage invalid argument [1] expected number"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_RemoveVehicle(lua_State* L) {
|
int lua_RemoveVehicle(lua_State* L) {
|
||||||
int Args = lua_gettop(L);
|
int Args = lua_gettop(L);
|
||||||
if (Args != 2) {
|
if (Args != 2) {
|
||||||
SendError(L, Sec("RemoveVehicle invalid argument count expected 2 got ") + std::to_string(Args));
|
SendError(L, ("RemoveVehicle invalid argument count expected 2 got ") + std::to_string(Args));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((lua_isinteger(L, 1) || lua_isnumber(L, 1)) && (lua_isinteger(L, 2) || lua_isnumber(L, 2))) {
|
if ((lua_isinteger(L, 1) || lua_isnumber(L, 1)) && (lua_isinteger(L, 2) || lua_isnumber(L, 2))) {
|
||||||
@@ -388,18 +404,16 @@ int lua_RemoveVehicle(lua_State* L) {
|
|||||||
int VID = int(lua_tointeger(L, 2));
|
int VID = int(lua_tointeger(L, 2));
|
||||||
Client* c = GetClient(PID);
|
Client* c = GetClient(PID);
|
||||||
if (c == nullptr) {
|
if (c == nullptr) {
|
||||||
SendError(L, Sec("RemoveVehicle invalid Player ID"));
|
SendError(L, ("RemoveVehicle invalid Player ID"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (c->GetRole() == "MDEV")
|
|
||||||
return 0;
|
|
||||||
if (!c->GetCarData(VID).empty()) {
|
if (!c->GetCarData(VID).empty()) {
|
||||||
std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID);
|
std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID);
|
||||||
SendToAll(nullptr, Destroy, true, true);
|
SendToAll(nullptr, Destroy, true, true);
|
||||||
c->DeleteCar(VID);
|
c->DeleteCar(VID);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("RemoveVehicle invalid argument expected number"));
|
SendError(L, ("RemoveVehicle invalid argument expected number"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_HWID(lua_State* L) {
|
int lua_HWID(lua_State* L) {
|
||||||
@@ -409,19 +423,19 @@ int lua_HWID(lua_State* L) {
|
|||||||
int lua_RemoteEvent(lua_State* L) {
|
int lua_RemoteEvent(lua_State* L) {
|
||||||
int Args = lua_gettop(L);
|
int Args = lua_gettop(L);
|
||||||
if (Args != 3) {
|
if (Args != 3) {
|
||||||
SendError(L, Sec("TriggerClientEvent invalid argument count expected 3 got ") + std::to_string(Args));
|
SendError(L, ("TriggerClientEvent invalid argument count expected 3 got ") + std::to_string(Args));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!lua_isnumber(L, 1)) {
|
if (!lua_isnumber(L, 1)) {
|
||||||
SendError(L, Sec("TriggerClientEvent invalid argument [1] expected number"));
|
SendError(L, ("TriggerClientEvent invalid argument [1] expected number"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!lua_isstring(L, 2)) {
|
if (!lua_isstring(L, 2)) {
|
||||||
SendError(L, Sec("TriggerClientEvent invalid argument [2] expected string"));
|
SendError(L, ("TriggerClientEvent invalid argument [2] expected string"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!lua_isstring(L, 3)) {
|
if (!lua_isstring(L, 3)) {
|
||||||
SendError(L, Sec("TriggerClientEvent invalid argument [3] expected string"));
|
SendError(L, ("TriggerClientEvent invalid argument [3] expected string"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int ID = int(lua_tointeger(L, 1));
|
int ID = int(lua_tointeger(L, 1));
|
||||||
@@ -431,30 +445,35 @@ int lua_RemoteEvent(lua_State* L) {
|
|||||||
else {
|
else {
|
||||||
Client* c = GetClient(ID);
|
Client* c = GetClient(ID);
|
||||||
if (c == nullptr) {
|
if (c == nullptr) {
|
||||||
SendError(L, Sec("TriggerClientEvent invalid Player ID"));
|
SendError(L, ("TriggerClientEvent invalid Player ID"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Respond(c, Packet, true);
|
Respond(c, Packet, true);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lua_ServerExit(lua_State*) {
|
int lua_ServerExit(lua_State* L) {
|
||||||
|
if (lua_gettop(L) > 0) {
|
||||||
|
if (lua_isnumber(L, 1)) {
|
||||||
|
_Exit(int(lua_tointeger(L, 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
_Exit(0);
|
_Exit(0);
|
||||||
}
|
}
|
||||||
int lua_Set(lua_State* L) {
|
int lua_Set(lua_State* L) {
|
||||||
int Args = lua_gettop(L);
|
int Args = lua_gettop(L);
|
||||||
if (Args != 2) {
|
if (Args != 2) {
|
||||||
SendError(L, Sec("set invalid argument count expected 2 got ") + std::to_string(Args));
|
SendError(L, ("set invalid argument count expected 2 got ") + std::to_string(Args));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!lua_isnumber(L, 1)) {
|
if (!lua_isnumber(L, 1)) {
|
||||||
SendError(L, Sec("set invalid argument [1] expected number"));
|
SendError(L, ("set invalid argument [1] expected number"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
auto MaybeSrc = GetScript(L);
|
auto MaybeSrc = GetScript(L);
|
||||||
std::string Name;
|
std::string Name;
|
||||||
if (!MaybeSrc.has_value()) {
|
if (!MaybeSrc.has_value()) {
|
||||||
Name = Sec("_Console");
|
Name = ("_Console");
|
||||||
} else {
|
} else {
|
||||||
Name = MaybeSrc.value().get().GetPluginName();
|
Name = MaybeSrc.value().get().GetPluginName();
|
||||||
}
|
}
|
||||||
@@ -463,54 +482,54 @@ int lua_Set(lua_State* L) {
|
|||||||
case 0: //debug
|
case 0: //debug
|
||||||
if (lua_isboolean(L, 2)) {
|
if (lua_isboolean(L, 2)) {
|
||||||
Debug = lua_toboolean(L, 2);
|
Debug = lua_toboolean(L, 2);
|
||||||
info(Name + Sec(" | Debug -> ") + (Debug ? "true" : "false"));
|
info(Name + (" | Debug -> ") + (Debug ? "true" : "false"));
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("set invalid argument [2] expected boolean for ID : 0"));
|
SendError(L, ("set invalid argument [2] expected boolean for ID : 0"));
|
||||||
break;
|
break;
|
||||||
case 1: //private
|
case 1: //private
|
||||||
if (lua_isboolean(L, 2)) {
|
if (lua_isboolean(L, 2)) {
|
||||||
Private = lua_toboolean(L, 2);
|
Private = lua_toboolean(L, 2);
|
||||||
info(Name + Sec(" | Private -> ") + (Private ? "true" : "false"));
|
info(Name + (" | Private -> ") + (Private ? "true" : "false"));
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("set invalid argument [2] expected boolean for ID : 1"));
|
SendError(L, ("set invalid argument [2] expected boolean for ID : 1"));
|
||||||
break;
|
break;
|
||||||
case 2: //max cars
|
case 2: //max cars
|
||||||
if (lua_isnumber(L, 2)) {
|
if (lua_isnumber(L, 2)) {
|
||||||
MaxCars = int(lua_tointeger(L, 2));
|
MaxCars = int(lua_tointeger(L, 2));
|
||||||
info(Name + Sec(" | MaxCars -> ") + std::to_string(MaxCars));
|
info(Name + (" | MaxCars -> ") + std::to_string(MaxCars));
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("set invalid argument [2] expected number for ID : 2"));
|
SendError(L, ("set invalid argument [2] expected number for ID : 2"));
|
||||||
break;
|
break;
|
||||||
case 3: //max players
|
case 3: //max players
|
||||||
if (lua_isnumber(L, 2)) {
|
if (lua_isnumber(L, 2)) {
|
||||||
MaxPlayers = int(lua_tointeger(L, 2));
|
MaxPlayers = int(lua_tointeger(L, 2));
|
||||||
info(Name + Sec(" | MaxPlayers -> ") + std::to_string(MaxPlayers));
|
info(Name + (" | MaxPlayers -> ") + std::to_string(MaxPlayers));
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("set invalid argument [2] expected number for ID : 3"));
|
SendError(L, ("set invalid argument [2] expected number for ID : 3"));
|
||||||
break;
|
break;
|
||||||
case 4: //Map
|
case 4: //Map
|
||||||
if (lua_isstring(L, 2)) {
|
if (lua_isstring(L, 2)) {
|
||||||
MapName = lua_tostring(L, 2);
|
MapName = lua_tostring(L, 2);
|
||||||
info(Name + Sec(" | MapName -> ") + MapName);
|
info(Name + (" | MapName -> ") + MapName);
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("set invalid argument [2] expected string for ID : 4"));
|
SendError(L, ("set invalid argument [2] expected string for ID : 4"));
|
||||||
break;
|
break;
|
||||||
case 5: //Name
|
case 5: //Name
|
||||||
if (lua_isstring(L, 2)) {
|
if (lua_isstring(L, 2)) {
|
||||||
ServerName = lua_tostring(L, 2);
|
ServerName = lua_tostring(L, 2);
|
||||||
info(Name + Sec(" | ServerName -> ") + ServerName);
|
info(Name + (" | ServerName -> ") + ServerName);
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("set invalid argument [2] expected string for ID : 5"));
|
SendError(L, ("set invalid argument [2] expected string for ID : 5"));
|
||||||
break;
|
break;
|
||||||
case 6: //Desc
|
case 6: //Desc
|
||||||
if (lua_isstring(L, 2)) {
|
if (lua_isstring(L, 2)) {
|
||||||
ServerDesc = lua_tostring(L, 2);
|
ServerDesc = lua_tostring(L, 2);
|
||||||
info(Name + Sec(" | ServerDesc -> ") + ServerDesc);
|
info(Name + (" | ServerDesc -> ") + ServerDesc);
|
||||||
} else
|
} else
|
||||||
SendError(L, Sec("set invalid argument [2] expected string for ID : 6"));
|
SendError(L, ("set invalid argument [2] expected string for ID : 6"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
warn(Sec("Invalid config ID : ") + std::to_string(C));
|
warn(("Invalid config ID : ") + std::to_string(C));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,9 +541,9 @@ int lua_Print(lua_State* L) {
|
|||||||
for (int i = 1; i <= Arg; i++) {
|
for (int i = 1; i <= Arg; i++) {
|
||||||
auto str = lua_tostring(L, i);
|
auto str = lua_tostring(L, i);
|
||||||
if (str != nullptr) {
|
if (str != nullptr) {
|
||||||
ConsoleOut(str + std::string(Sec("\n")));
|
ConsoleOut(str + std::string(("\n")));
|
||||||
} else {
|
} else {
|
||||||
ConsoleOut(Sec("nil\n"));
|
ConsoleOut(("nil\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -556,14 +575,14 @@ void Lua::Execute(const std::string& Command) {
|
|||||||
}
|
}
|
||||||
void Lua::Reload() {
|
void Lua::Reload() {
|
||||||
if (CheckLua(luaState, luaL_dofile(luaState, _FileName.c_str()))) {
|
if (CheckLua(luaState, luaL_dofile(luaState, _FileName.c_str()))) {
|
||||||
CallFunction(this, Sec("onInit"), nullptr);
|
CallFunction(this, ("onInit"), nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string Lua::GetOrigin() {
|
std::string Lua::GetOrigin() {
|
||||||
return fs::path(GetFileName()).filename().string();
|
return fs::path(GetFileName()).filename().string();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CallFunction(Lua* lua, const std::string& FuncName, std::unique_ptr<LuaArg> Arg) {
|
std::any CallFunction(Lua* lua, const std::string& FuncName, std::shared_ptr<LuaArg> Arg) {
|
||||||
lua_State* luaState = lua->GetState();
|
lua_State* luaState = lua->GetState();
|
||||||
lua_getglobal(luaState, FuncName.c_str());
|
lua_getglobal(luaState, FuncName.c_str());
|
||||||
if (lua_isfunction(luaState, -1)) {
|
if (lua_isfunction(luaState, -1)) {
|
||||||
@@ -572,11 +591,12 @@ int CallFunction(Lua* lua, const std::string& FuncName, std::unique_ptr<LuaArg>
|
|||||||
Size = int(Arg->args.size());
|
Size = int(Arg->args.size());
|
||||||
Arg->PushArgs(luaState);
|
Arg->PushArgs(luaState);
|
||||||
}
|
}
|
||||||
std::string Origin = lua->GetOrigin();
|
|
||||||
int R = lua_pcall(luaState, Size, 1, 0);
|
int R = lua_pcall(luaState, Size, 1, 0);
|
||||||
if (CheckLua(luaState, R)) {
|
if (CheckLua(luaState, R)) {
|
||||||
if (lua_isnumber(luaState, -1)) {
|
if (lua_isnumber(luaState, -1)) {
|
||||||
return int(lua_tointeger(luaState, -1));
|
return int(lua_tointeger(luaState, -1));
|
||||||
|
} else if (lua_isstring(luaState, -1)) {
|
||||||
|
return std::string(lua_tostring(luaState, -1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +609,22 @@ void Lua::SetPluginName(const std::string& Name) {
|
|||||||
void Lua::SetFileName(const std::string& Name) {
|
void Lua::SetFileName(const std::string& Name) {
|
||||||
_FileName = Name;
|
_FileName = Name;
|
||||||
}
|
}
|
||||||
|
int lua_TempFix(lua_State* L) {
|
||||||
|
if (lua_isnumber(L, 1)) {
|
||||||
|
int ID = int(lua_tonumber(L, 1));
|
||||||
|
Client* c = GetClient(ID);
|
||||||
|
if (c == nullptr)
|
||||||
|
return 0;
|
||||||
|
std::string Ret;
|
||||||
|
if (c->isGuest) {
|
||||||
|
Ret = "Guest-" + c->GetName();
|
||||||
|
} else
|
||||||
|
Ret = c->GetName();
|
||||||
|
lua_pushstring(L, Ret.c_str());
|
||||||
|
} else
|
||||||
|
SendError(L, "GetDID not enough arguments");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
void Lua::Init() {
|
void Lua::Init() {
|
||||||
Assert(luaState);
|
Assert(luaState);
|
||||||
luaL_openlibs(luaState);
|
luaL_openlibs(luaState);
|
||||||
@@ -600,11 +636,12 @@ void Lua::Init() {
|
|||||||
lua_register(luaState, "RegisterEvent", lua_RegisterEvent);
|
lua_register(luaState, "RegisterEvent", lua_RegisterEvent);
|
||||||
lua_register(luaState, "GetPlayerName", lua_GetPlayerName);
|
lua_register(luaState, "GetPlayerName", lua_GetPlayerName);
|
||||||
lua_register(luaState, "RemoveVehicle", lua_RemoveVehicle);
|
lua_register(luaState, "RemoveVehicle", lua_RemoveVehicle);
|
||||||
lua_register(luaState, "GetPlayerDiscordID", lua_GetDID);
|
lua_register(luaState, "GetPlayerDiscordID", lua_TempFix);
|
||||||
lua_register(luaState, "GetPlayerVehicles", lua_GetCars);
|
|
||||||
lua_register(luaState, "CreateThread", lua_CreateThread);
|
lua_register(luaState, "CreateThread", lua_CreateThread);
|
||||||
|
lua_register(luaState, "GetPlayerVehicles", lua_GetCars);
|
||||||
lua_register(luaState, "SendChatMessage", lua_sendChat);
|
lua_register(luaState, "SendChatMessage", lua_sendChat);
|
||||||
lua_register(luaState, "GetPlayers", lua_GetAllPlayers);
|
lua_register(luaState, "GetPlayers", lua_GetAllPlayers);
|
||||||
|
lua_register(luaState, "GetPlayerGuest", lua_GetGuest);
|
||||||
lua_register(luaState, "StopThread", lua_StopThread);
|
lua_register(luaState, "StopThread", lua_StopThread);
|
||||||
lua_register(luaState, "DropPlayer", lua_dropPlayer);
|
lua_register(luaState, "DropPlayer", lua_dropPlayer);
|
||||||
lua_register(luaState, "GetPlayerHWID", lua_HWID);
|
lua_register(luaState, "GetPlayerHWID", lua_HWID);
|
||||||
|
|||||||
@@ -1,233 +1,143 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/31/2020
|
/// Created by Anonymous275 on 7/31/2020
|
||||||
///
|
///
|
||||||
|
|
||||||
#include "Curl/Http.h"
|
#include "Curl/Http.h"
|
||||||
|
#include "Json.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Network.h"
|
#include "Network.h"
|
||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "UnixCompat.h"
|
#include "UnixCompat.h"
|
||||||
#include <algorithm>
|
#include <Lua/LuaSystem.hpp>
|
||||||
#include <atomic>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
bool Send(SOCKET TCPSock, std::string Data) {
|
std::string GetClientInfo(const std::string& PK) {
|
||||||
#ifdef WIN32
|
if (!PK.empty()) {
|
||||||
int BytesSent;
|
return PostHTTP("https://auth.beammp.com/pkToUser", R"({"key":")" + PK + "\"}", true);
|
||||||
int len = static_cast<int>(Data.size());
|
;
|
||||||
#else
|
|
||||||
int64_t BytesSent;
|
|
||||||
size_t len = Data.size();
|
|
||||||
#endif // WIN32
|
|
||||||
BytesSent = send(TCPSock, Data.c_str(), len, 0);
|
|
||||||
Data.clear();
|
|
||||||
if (BytesSent <= 0) {
|
|
||||||
#ifndef WIN32
|
|
||||||
error(__func__ + std::string(" ") + strerror(errno));
|
|
||||||
#else
|
|
||||||
error(__func__ + std::string(" ") + std::to_string(WSAGetLastError()));
|
|
||||||
#endif // WIN32
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
std::string Rcv(SOCKET TCPSock) {
|
|
||||||
uint32_t RealSize;
|
|
||||||
#ifdef WIN32
|
|
||||||
int64_t BytesRcv = recv(TCPSock, reinterpret_cast<char*>(&RealSize), sizeof(RealSize), 0);
|
|
||||||
#else
|
|
||||||
int64_t BytesRcv = recv(TCPSock, reinterpret_cast<void*>(&RealSize), sizeof(RealSize), 0);
|
|
||||||
#endif
|
|
||||||
if (BytesRcv != sizeof(RealSize)) {
|
|
||||||
error(std::string(Sec("invalid packet: expected 4, got ")) + std::to_string(BytesRcv));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
// RealSize is big-endian, so we convert it to host endianness
|
|
||||||
RealSize = ntohl(RealSize);
|
|
||||||
debug(std::string("got ") + std::to_string(RealSize) + " as size");
|
|
||||||
if (RealSize > 7000) {
|
|
||||||
error(Sec("Larger than allowed TCP packet received"));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
char buf[7000];
|
|
||||||
std::fill_n(buf, 7000, 0);
|
|
||||||
BytesRcv = recv(TCPSock, buf, RealSize, 0);
|
|
||||||
if (BytesRcv != RealSize) {
|
|
||||||
debug("expected " + std::to_string(RealSize) + " bytes, got " + std::to_string(BytesRcv) + " instead");
|
|
||||||
}
|
|
||||||
if (BytesRcv <= 0)
|
|
||||||
return "";
|
|
||||||
return std::string(buf);
|
|
||||||
}
|
|
||||||
std::string GetRole(const std::string& DID) {
|
|
||||||
if (!DID.empty()) {
|
|
||||||
std::string a = HttpRequest(Sec("https://beammp.com/entitlement?did=") + DID, 443);
|
|
||||||
std::string b = HttpRequest(Sec("https://backup1.beammp.com/entitlement?did=") + DID, 443);
|
|
||||||
if (!a.empty() || !b.empty()) {
|
|
||||||
if (a != b)
|
|
||||||
a = b;
|
|
||||||
auto pos = a.find('"');
|
|
||||||
if (pos != std::string::npos) {
|
|
||||||
return a.substr(pos + 1, a.find('"', pos + 1) - 2);
|
|
||||||
} else if (a == "[]")
|
|
||||||
return Sec("Member");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
void Check(SOCKET TCPSock, std::shared_ptr<std::atomic_bool> ok) {
|
|
||||||
DebugPrintTID();
|
Client* CreateClient(SOCKET TCPSock) {
|
||||||
size_t accum = 0;
|
|
||||||
while (!*ok) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
||||||
accum += 100;
|
|
||||||
if (accum >= 5000) {
|
|
||||||
error(Sec("Identification timed out (Check accum)"));
|
|
||||||
CloseSocketProper(TCPSock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int Max() {
|
|
||||||
int M = MaxPlayers;
|
|
||||||
for (auto& c : CI->Clients) {
|
|
||||||
if (c != nullptr) {
|
|
||||||
if (c->GetRole() == Sec("MDEV"))
|
|
||||||
M++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return M;
|
|
||||||
}
|
|
||||||
void CreateClient(SOCKET TCPSock, const std::string& Name, const std::string& DID, const std::string& Role) {
|
|
||||||
auto* c = new Client;
|
auto* c = new Client;
|
||||||
c->SetTCPSock(TCPSock);
|
c->SetTCPSock(TCPSock);
|
||||||
c->SetName(Name);
|
return c;
|
||||||
c->SetRole(Role);
|
|
||||||
c->SetDID(DID);
|
|
||||||
Client& Client = *c;
|
|
||||||
CI->AddClient(std::move(c));
|
|
||||||
InitClient(&Client);
|
|
||||||
}
|
|
||||||
std::pair<int, int> Parse(const std::string& msg) {
|
|
||||||
std::stringstream ss(msg);
|
|
||||||
std::string t;
|
|
||||||
std::pair<int, int> a = { 0, 0 }; //N then E
|
|
||||||
while (std::getline(ss, t, 'g')) {
|
|
||||||
if (t.find_first_not_of(Sec("0123456789abcdef")) != std::string::npos)
|
|
||||||
return a;
|
|
||||||
if (a.first == 0) {
|
|
||||||
a.first = std::stoi(t, nullptr, 16);
|
|
||||||
} else if (a.second == 0) {
|
|
||||||
a.second = std::stoi(t, nullptr, 16);
|
|
||||||
} else
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
return { 0, 0 };
|
|
||||||
}
|
|
||||||
std::string GenerateM(RSA* key) {
|
|
||||||
std::stringstream stream;
|
|
||||||
stream << std::hex << key->n << "g" << key->e << "g" << RSA_E(Sec("IDC"), key);
|
|
||||||
return stream.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Identification(SOCKET TCPSock, RSA* Skey) {
|
void ClientKick(Client* c, const std::string& R) {
|
||||||
|
info("Client kicked: " + R);
|
||||||
|
TCPSend(c, "E" + R);
|
||||||
|
CloseSocketProper(c->GetTCPSock());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Authentication(SOCKET TCPSock) {
|
||||||
DebugPrintTID();
|
DebugPrintTID();
|
||||||
Assert(Skey);
|
auto* c = CreateClient(TCPSock);
|
||||||
std::shared_ptr<std::atomic_bool> ok = std::make_shared<std::atomic_bool>(false);
|
|
||||||
std::thread Timeout(Check, TCPSock, ok);
|
|
||||||
Timeout.detach();
|
|
||||||
std::string Name, DID, Role;
|
|
||||||
if (!Send(TCPSock, GenerateM(Skey))) {
|
|
||||||
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
|
||||||
CloseSocketProper(TCPSock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::string msg = Rcv(TCPSock);
|
|
||||||
auto Keys = Parse(msg);
|
|
||||||
if (!Send(TCPSock, RSA_E("HC", Keys.second, Keys.first))) {
|
|
||||||
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
|
||||||
CloseSocketProper(TCPSock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Res = Rcv(TCPSock);
|
info("Identifying new client...");
|
||||||
std::string Ver = Rcv(TCPSock);
|
std::string Rc = TCPRcv(c);
|
||||||
*ok = true;
|
|
||||||
Ver = RSA_D(Ver, Skey);
|
if (Rc.size() > 3 && Rc.substr(0, 2) == "VC") {
|
||||||
if (Ver.size() > 3 && Ver.substr(0, 2) == Sec("VC")) {
|
Rc = Rc.substr(2);
|
||||||
Ver = Ver.substr(2);
|
if (Rc.length() > 4 || Rc != GetCVer()) {
|
||||||
if (Ver.length() > 4 || Ver != GetCVer()) {
|
ClientKick(c, "Outdated Version!");
|
||||||
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
|
||||||
CloseSocketProper(TCPSock);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
ClientKick(c, "Invalid version header!");
|
||||||
CloseSocketProper(TCPSock);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Res = RSA_D(Res, Skey);
|
TCPSend(c, "S");
|
||||||
if (Res.size() < 3 || Res.substr(0, 2) != Sec("NR")) {
|
|
||||||
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
Rc = TCPRcv(c);
|
||||||
CloseSocketProper(TCPSock);
|
|
||||||
|
if (Rc.size() > 50) {
|
||||||
|
ClientKick(c, "Invalid Key!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Res.find(':') == std::string::npos) {
|
|
||||||
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
Rc = GetClientInfo(Rc);
|
||||||
CloseSocketProper(TCPSock);
|
json::Document d;
|
||||||
|
d.Parse(Rc.c_str());
|
||||||
|
if (Rc == "-1" || d.HasParseError()) {
|
||||||
|
ClientKick(c, "Invalid key! Please restart your game.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Name = Res.substr(2, Res.find(':') - 2);
|
|
||||||
DID = Res.substr(Res.find(':') + 1);
|
if (d["username"].IsString() && d["roles"].IsString() && d["guest"].IsBool()) {
|
||||||
Role = GetRole(DID);
|
c->SetName(d["username"].GetString());
|
||||||
if (Role.empty() || Role.find(Sec("Error")) != std::string::npos) {
|
c->SetRoles(d["roles"].GetString());
|
||||||
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
c->isGuest = d["guest"].GetBool();
|
||||||
CloseSocketProper(TCPSock);
|
} else {
|
||||||
|
ClientKick(c, "Invalid authentication data!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// DebugPrintTIDInternal(std::string("Client(") + Name + ")");
|
|
||||||
debug(Sec("Name -> ") + Name + Sec(", Role -> ") + Role + Sec(", ID -> ") + DID);
|
debug("Name -> " + c->GetName() + ", Guest -> " + std::to_string(c->isGuest) + ", Roles -> " + c->GetRoles());
|
||||||
for (auto& c : CI->Clients) {
|
for (auto& Cl : CI->Clients) {
|
||||||
if (c != nullptr) {
|
if (Cl != nullptr) {
|
||||||
if (c->GetDID() == DID) {
|
if (Cl->GetName() == c->GetName() && Cl->isGuest == c->isGuest) {
|
||||||
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
info("Old client (" + Cl->GetName() + ") kicked: Reconnecting");
|
||||||
CloseSocketProper(c->GetTCPSock());
|
CloseSocketProper(Cl->GetTCPSock());
|
||||||
c->SetStatus(-2);
|
Cl->SetStatus(-2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Role == Sec("MDEV") || CI->Size() < Max()) {
|
|
||||||
debug("Identification success");
|
|
||||||
CreateClient(TCPSock, Name, DID, Role);
|
|
||||||
} else {
|
|
||||||
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
|
||||||
CloseSocketProper(TCPSock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Identify(SOCKET TCPSock) {
|
|
||||||
RSA* Skey = GenKey();
|
|
||||||
// this disgusting ifdef stuff is needed because for some
|
|
||||||
// reason MSVC defines __try and __except and libg++ defines
|
|
||||||
// __try and __catch so its all a big mess if we leave this in or undefine
|
|
||||||
// the macros
|
|
||||||
/*#ifdef WIN32
|
|
||||||
__try{
|
|
||||||
#endif // WIN32*/
|
|
||||||
Identification(TCPSock, Skey);
|
|
||||||
/*#ifdef WIN32
|
|
||||||
}__except(1){
|
|
||||||
if(TCPSock != -1){
|
|
||||||
error("died on " + std::string(__func__) + ":" + std::to_string(__LINE__));
|
|
||||||
CloseSocketProper(TCPSock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // WIN32*/
|
|
||||||
|
|
||||||
delete Skey;
|
auto arg = std::make_unique<LuaArg>(LuaArg { { c->GetName(), c->GetRoles(), c->isGuest } });
|
||||||
|
std::any Res = TriggerLuaEvent("onPlayerAuth", false, nullptr, std::move(arg), true);
|
||||||
|
std::string Type = Res.type().name();
|
||||||
|
if (Type.find("int") != std::string::npos && std::any_cast<int>(Res)) {
|
||||||
|
ClientKick(c, "you are not allowed on the server!");
|
||||||
|
return;
|
||||||
|
} else if (Type.find("string") != std::string::npos) {
|
||||||
|
ClientKick(c, std::any_cast<std::string>(Res));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (CI->Size() < MaxPlayers) {
|
||||||
|
info("Identification success");
|
||||||
|
Client& Client = *c;
|
||||||
|
CI->AddClient(std::move(c));
|
||||||
|
TCPClient(&Client);
|
||||||
|
} else
|
||||||
|
ClientKick(c, "Server full!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleDownload(SOCKET TCPSock) {
|
||||||
|
char D;
|
||||||
|
if (recv(TCPSock, &D, 1, 0) != 1) {
|
||||||
|
CloseSocketProper(TCPSock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto ID = uint8_t(D);
|
||||||
|
for (auto& c : CI->Clients) {
|
||||||
|
if (c->GetID() == ID) {
|
||||||
|
c->SetDownSock(TCPSock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Identify(SOCKET TCPSock) {
|
||||||
|
char Code;
|
||||||
|
if (recv(TCPSock, &Code, 1, 0) != 1) {
|
||||||
|
CloseSocketProper(TCPSock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Code == 'C') {
|
||||||
|
Authentication(TCPSock);
|
||||||
|
} else if (Code == 'D') {
|
||||||
|
HandleDownload(TCPSock);
|
||||||
|
} else
|
||||||
|
CloseSocketProper(TCPSock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCPServerMain() {
|
void TCPServerMain() {
|
||||||
@@ -235,7 +145,7 @@ void TCPServerMain() {
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
if (WSAStartup(514, &wsaData)) {
|
if (WSAStartup(514, &wsaData)) {
|
||||||
error(Sec("Can't start Winsock!"));
|
error("Can't start Winsock!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SOCKET client, Listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
SOCKET client, Listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
@@ -244,30 +154,30 @@ void TCPServerMain() {
|
|||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons(Port);
|
addr.sin_port = htons(Port);
|
||||||
if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||||
error(Sec("Can't bind socket! ") + std::to_string(WSAGetLastError()));
|
error("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);
|
||||||
}
|
}
|
||||||
if (Listener == -1) {
|
if (Listener == -1) {
|
||||||
error(Sec("Invalid listening socket"));
|
error("Invalid listening socket");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (listen(Listener, SOMAXCONN)) {
|
if (listen(Listener, SOMAXCONN)) {
|
||||||
error(Sec("listener failed ") + std::to_string(GetLastError()));
|
error("listener failed " + std::to_string(GetLastError()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info(Sec("Vehicle event network online"));
|
info("Vehicle event network online");
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
client = accept(Listener, nullptr, nullptr);
|
client = accept(Listener, nullptr, nullptr);
|
||||||
if (client == -1) {
|
if (client == -1) {
|
||||||
warn(Sec("Got an invalid client socket on connect! Skipping..."));
|
warn("Got an invalid client socket on connect! Skipping...");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::thread ID(Identify, client);
|
std::thread ID(Identify, client);
|
||||||
ID.detach();
|
ID.detach();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
error(Sec("fatal: ") + std::string(e.what()));
|
error("fatal: " + std::string(e.what()));
|
||||||
}
|
}
|
||||||
} while (client);
|
} while (client);
|
||||||
|
|
||||||
@@ -285,30 +195,30 @@ void TCPServerMain() {
|
|||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons(uint16_t(Port));
|
addr.sin_port = htons(uint16_t(Port));
|
||||||
if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) != 0) {
|
if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) != 0) {
|
||||||
error(Sec("Can't bind socket! ") + std::string(strerror(errno)));
|
error(("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);
|
||||||
}
|
}
|
||||||
if (Listener == -1) {
|
if (Listener == -1) {
|
||||||
error(Sec("Invalid listening socket"));
|
error(("Invalid listening socket"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (listen(Listener, SOMAXCONN)) {
|
if (listen(Listener, SOMAXCONN)) {
|
||||||
error(Sec("listener failed ") + std::string(strerror(errno)));
|
error(("listener failed ") + std::string(strerror(errno)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info(Sec("Vehicle event network online"));
|
info(("Vehicle event network online"));
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
client = accept(Listener, nullptr, nullptr);
|
client = accept(Listener, nullptr, nullptr);
|
||||||
if (client == -1) {
|
if (client == -1) {
|
||||||
warn(Sec("Got an invalid client socket on connect! Skipping..."));
|
warn(("Got an invalid client socket on connect! Skipping..."));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::thread ID(Identify, client);
|
std::thread ID(Identify, client);
|
||||||
ID.detach();
|
ID.detach();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
error(Sec("fatal: ") + std::string(e.what()));
|
error(("fatal: ") + std::string(e.what()));
|
||||||
}
|
}
|
||||||
} while (client);
|
} while (client);
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +1,14 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 5/8/2020
|
/// Created by Anonymous275 on 5/8/2020
|
||||||
///
|
///
|
||||||
#include "Client.hpp"
|
#include "Client.hpp"
|
||||||
|
|
||||||
std::string Client::GetName() {
|
#include <memory>
|
||||||
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) {
|
void Client::DeleteCar(int ident) {
|
||||||
for (auto& v : VehicleData) {
|
for (auto& v : VehicleData) {
|
||||||
if (v != nullptr && v->ID == ident) {
|
if (v != nullptr && v->ID == ident) {
|
||||||
@@ -71,17 +35,13 @@ int Client::GetOpenCarID() {
|
|||||||
return OpenID;
|
return OpenID;
|
||||||
}
|
}
|
||||||
void Client::AddNewCar(int ident, const std::string& Data) {
|
void Client::AddNewCar(int ident, const std::string& Data) {
|
||||||
VehicleData.insert(std::unique_ptr<VData>(new VData { ident, Data }));
|
VehicleData.insert(std::make_unique<VData>(VData { ident, Data }));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<std::unique_ptr<VData>>& Client::GetAllCars() {
|
std::set<std::unique_ptr<VData>>& Client::GetAllCars() {
|
||||||
return VehicleData;
|
return VehicleData;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::set<std::unique_ptr<VData>>& Client::GetAllCars() const {
|
|
||||||
return VehicleData;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Client::GetCarData(int ident) {
|
std::string Client::GetCarData(int ident) {
|
||||||
for (auto& v : VehicleData) {
|
for (auto& v : VehicleData) {
|
||||||
if (v != nullptr && v->ID == ident) {
|
if (v != nullptr && v->ID == ident) {
|
||||||
@@ -91,6 +51,7 @@ std::string Client::GetCarData(int ident) {
|
|||||||
DeleteCar(ident);
|
DeleteCar(ident);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SetCarData(int ident, const std::string& Data) {
|
void Client::SetCarData(int ident, const std::string& Data) {
|
||||||
for (auto& v : VehicleData) {
|
for (auto& v : VehicleData) {
|
||||||
if (v != nullptr && v->ID == ident) {
|
if (v != nullptr && v->ID == ident) {
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 8/1/2020
|
/// Created by Anonymous275 on 8/1/2020
|
||||||
///
|
///
|
||||||
|
|
||||||
#include "Client.hpp"
|
#include "Client.hpp"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Lua/LuaSystem.hpp"
|
#include "Lua/LuaSystem.hpp"
|
||||||
@@ -8,27 +13,37 @@
|
|||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "UnixCompat.h"
|
#include "UnixCompat.h"
|
||||||
#include <memory>
|
#undef GetObject //to fix microsoft bs
|
||||||
#include <sstream>
|
#include "Json.h"
|
||||||
|
|
||||||
int FC(const std::string& s, const std::string& p, int n) {
|
|
||||||
auto i = s.find(p);
|
|
||||||
int j;
|
|
||||||
for (j = 1; j < n && i != std::string::npos; ++j) {
|
|
||||||
i = s.find(p, i + 1);
|
|
||||||
}
|
|
||||||
if (j == n)
|
|
||||||
return int(i);
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
void Apply(Client* c, int VID, const std::string& pckt) {
|
void Apply(Client* c, int VID, const std::string& pckt) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
std::string Packet = pckt;
|
std::string Packet = pckt.substr(pckt.find('{')), VD = c->GetCarData(VID);
|
||||||
std::string VD = c->GetCarData(VID);
|
std::string Header = VD.substr(0, VD.find('{'));
|
||||||
Packet = Packet.substr(FC(Packet, ",", 2) + 1);
|
VD = VD.substr(VD.find('{'));
|
||||||
Packet = VD.substr(0, FC(VD, ",", 2) + 1) + Packet.substr(0, Packet.find_last_of('"') + 1) + VD.substr(FC(VD, ",\"", 7));
|
rapidjson::Document Veh, Pack;
|
||||||
c->SetCarData(VID, Packet);
|
Veh.Parse(VD.c_str());
|
||||||
|
if (Veh.HasParseError()) {
|
||||||
|
error("Could not get vehicle config!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Pack.Parse(Packet.c_str());
|
||||||
|
if (Pack.HasParseError() || Pack.IsNull()) {
|
||||||
|
error("Could not get active vehicle config!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& M : Pack.GetObject()) {
|
||||||
|
if (Veh[M.name].IsNull()) {
|
||||||
|
Veh.AddMember(M.name, M.value, Veh.GetAllocator());
|
||||||
|
} else {
|
||||||
|
Veh[M.name] = Pack[M.name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rapidjson::StringBuffer Buffer;
|
||||||
|
rapidjson::Writer<rapidjson::StringBuffer> writer(Buffer);
|
||||||
|
Veh.Accept(writer);
|
||||||
|
c->SetCarData(VID, Header + Buffer.GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehicleParser(Client* c, const std::string& Pckt) {
|
void VehicleParser(Client* c, const std::string& Pckt) {
|
||||||
@@ -43,17 +58,18 @@ void VehicleParser(Client* c, const std::string& Pckt) {
|
|||||||
switch (Code) { //Spawned Destroyed Switched/Moved NotFound Reset
|
switch (Code) { //Spawned Destroyed Switched/Moved NotFound Reset
|
||||||
case 's':
|
case 's':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string(Sec("got 'Os' packet: '")) + Packet + Sec("' (") + std::to_string(Packet.size()) + Sec(")"));
|
debug(std::string(("got 'Os' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
#endif
|
#endif
|
||||||
if (Data.at(0) == '0') {
|
if (Data.at(0) == '0') {
|
||||||
int CarID = c->GetOpenCarID();
|
int CarID = c->GetOpenCarID();
|
||||||
debug(c->GetName() + Sec(" created a car with ID ") + std::to_string(CarID));
|
debug(c->GetName() + (" created a car with ID ") + std::to_string(CarID));
|
||||||
Packet = "Os:" + c->GetRole() + ":" + c->GetName() + ":" + std::to_string(c->GetID()) + "-" + std::to_string(CarID) + Packet.substr(4);
|
Packet = "Os:" + c->GetRoles() + ":" + c->GetName() + ":" + std::to_string(c->GetID()) + "-" + std::to_string(CarID) + Packet.substr(4);
|
||||||
if (c->GetCarCount() >= MaxCars || TriggerLuaEvent(Sec("onVehicleSpawn"), false, nullptr, std::make_unique<LuaArg>(LuaArg { { c->GetID(), CarID, Packet.substr(3) } }), true)) {
|
auto Res = TriggerLuaEvent(("onVehicleSpawn"), false, nullptr, std::make_unique<LuaArg>(LuaArg { { c->GetID(), CarID, Packet.substr(3) } }), true);
|
||||||
|
if (c->GetCarCount() >= MaxCars || std::any_cast<int>(Res)) {
|
||||||
Respond(c, Packet, true);
|
Respond(c, Packet, true);
|
||||||
std::string Destroy = "Od:" + std::to_string(c->GetID()) + "-" + std::to_string(CarID);
|
std::string Destroy = "Od:" + std::to_string(c->GetID()) + "-" + std::to_string(CarID);
|
||||||
Respond(c, Destroy, true);
|
Respond(c, Destroy, true);
|
||||||
debug(c->GetName() + Sec(" (force : car limit/lua) removed ID ") + std::to_string(CarID));
|
debug(c->GetName() + (" (force : car limit/lua) removed ID ") + std::to_string(CarID));
|
||||||
} else {
|
} else {
|
||||||
c->AddNewCar(CarID, Packet);
|
c->AddNewCar(CarID, Packet);
|
||||||
SendToAll(nullptr, Packet, true, true);
|
SendToAll(nullptr, Packet, true, true);
|
||||||
@@ -62,7 +78,7 @@ void VehicleParser(Client* c, const std::string& Pckt) {
|
|||||||
return;
|
return;
|
||||||
case 'c':
|
case 'c':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string(Sec("got 'Oc' packet: '")) + Packet + Sec("' (") + std::to_string(Packet.size()) + Sec(")"));
|
debug(std::string(("got 'Oc' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
#endif
|
#endif
|
||||||
pid = Data.substr(0, Data.find('-'));
|
pid = Data.substr(0, Data.find('-'));
|
||||||
vid = Data.substr(Data.find('-') + 1, Data.find(':', 1) - Data.find('-') - 1);
|
vid = Data.substr(Data.find('-') + 1, Data.find(':', 1) - Data.find('-') - 1);
|
||||||
@@ -71,9 +87,10 @@ void VehicleParser(Client* c, const std::string& Pckt) {
|
|||||||
VID = stoi(vid);
|
VID = stoi(vid);
|
||||||
}
|
}
|
||||||
if (PID != -1 && VID != -1 && PID == c->GetID()) {
|
if (PID != -1 && VID != -1 && PID == c->GetID()) {
|
||||||
if (!TriggerLuaEvent(Sec("onVehicleEdited"), false, nullptr,
|
auto Res = TriggerLuaEvent(("onVehicleEdited"), false, nullptr,
|
||||||
std::unique_ptr<LuaArg>(new LuaArg { { c->GetID(), VID, Packet.substr(3) } }),
|
std::make_unique<LuaArg>(LuaArg { { c->GetID(), VID, Packet.substr(3) } }),
|
||||||
true)) {
|
true);
|
||||||
|
if (!std::any_cast<int>(Res)) {
|
||||||
SendToAll(c, Packet, false, true);
|
SendToAll(c, Packet, false, true);
|
||||||
Apply(c, VID, Packet);
|
Apply(c, VID, Packet);
|
||||||
} else {
|
} else {
|
||||||
@@ -85,7 +102,7 @@ void VehicleParser(Client* c, const std::string& Pckt) {
|
|||||||
return;
|
return;
|
||||||
case 'd':
|
case 'd':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string(Sec("got 'Od' packet: '")) + Packet + Sec("' (") + std::to_string(Packet.size()) + Sec(")"));
|
debug(std::string(("got 'Od' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
#endif
|
#endif
|
||||||
pid = Data.substr(0, Data.find('-'));
|
pid = Data.substr(0, Data.find('-'));
|
||||||
vid = Data.substr(Data.find('-') + 1);
|
vid = Data.substr(Data.find('-') + 1);
|
||||||
@@ -95,21 +112,27 @@ void VehicleParser(Client* c, const std::string& Pckt) {
|
|||||||
}
|
}
|
||||||
if (PID != -1 && VID != -1 && PID == c->GetID()) {
|
if (PID != -1 && VID != -1 && PID == c->GetID()) {
|
||||||
SendToAll(nullptr, Packet, true, true);
|
SendToAll(nullptr, Packet, true, true);
|
||||||
TriggerLuaEvent(Sec("onVehicleDeleted"), false, nullptr,
|
TriggerLuaEvent(("onVehicleDeleted"), false, nullptr,
|
||||||
std::unique_ptr<LuaArg>(new LuaArg { { c->GetID(), VID } }), false);
|
std::make_unique<LuaArg>(LuaArg { { c->GetID(), VID } }), false);
|
||||||
c->DeleteCar(VID);
|
c->DeleteCar(VID);
|
||||||
debug(c->GetName() + Sec(" deleted car with ID ") + std::to_string(VID));
|
debug(c->GetName() + (" deleted car with ID ") + std::to_string(VID));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 'r':
|
case 'r':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string(Sec("got 'Or' packet: '")) + Packet + Sec("' (") + std::to_string(Packet.size()) + Sec(")"));
|
debug(std::string(("got 'Or' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
|
#endif
|
||||||
|
SendToAll(c, Packet, false, true);
|
||||||
|
return;
|
||||||
|
case 't':
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug(std::string(("got 'Ot' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
#endif
|
#endif
|
||||||
SendToAll(c, Packet, false, true);
|
SendToAll(c, Packet, false, true);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
warn(std::string(Sec("possibly not implemented: '") + Packet + Sec("' (") + std::to_string(Packet.size()) + Sec(")")));
|
warn(std::string(("possibly not implemented: '") + Packet + ("' (") + std::to_string(Packet.size()) + (")")));
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -120,15 +143,16 @@ void SyncClient(Client* c) {
|
|||||||
return;
|
return;
|
||||||
c->isSynced = true;
|
c->isSynced = true;
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
Respond(c, Sec("Sn") + c->GetName(), true);
|
Respond(c, ("Sn") + c->GetName(), true);
|
||||||
SendToAll(c, Sec("JWelcome ") + c->GetName() + "!", false, true);
|
SendToAll(c, ("JWelcome ") + c->GetName() + "!", false, true);
|
||||||
TriggerLuaEvent(Sec("onPlayerJoin"), false, nullptr, std::unique_ptr<LuaArg>(new LuaArg { { c->GetID() } }), false);
|
TriggerLuaEvent(("onPlayerJoin"), false, nullptr, std::make_unique<LuaArg>(LuaArg { { c->GetID() } }), false);
|
||||||
for (auto& client : CI->Clients) {
|
for (auto& client : CI->Clients) {
|
||||||
if (client != nullptr) {
|
if (client != nullptr) {
|
||||||
if (client.get() != c) {
|
if (client.get() != c) {
|
||||||
for (auto& v : client->GetAllCars()) {
|
for (auto& v : client->GetAllCars()) {
|
||||||
if (v != nullptr) {
|
if (v != nullptr) {
|
||||||
if(c->GetStatus() < 0)return;
|
if (c->GetStatus() < 0)
|
||||||
|
return;
|
||||||
Respond(c, v->Data, true);
|
Respond(c, v->Data, true);
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||||
}
|
}
|
||||||
@@ -136,14 +160,14 @@ void SyncClient(Client* c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info(c->GetName() + Sec(" is now synced!"));
|
info(c->GetName() + (" is now synced!"));
|
||||||
}
|
}
|
||||||
void ParseVeh(Client* c, const std::string& Packet) {
|
void ParseVeh(Client* c, const std::string& Packet) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
__try {
|
__try {
|
||||||
VehicleParser(c, Packet);
|
VehicleParser(c, Packet);
|
||||||
} __except (Handle(GetExceptionInformation(), Sec("Vehicle Handler"))) { }
|
} __except (Handle(GetExceptionInformation(), ("Vehicle Handler"))) { }
|
||||||
#else // unix
|
#else // unix
|
||||||
VehicleParser(c, Packet);
|
VehicleParser(c, Packet);
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
@@ -160,7 +184,7 @@ void HandleEvent(Client* c, const std::string& Data) {
|
|||||||
Name = t;
|
Name = t;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
TriggerLuaEvent(Name, false, nullptr, std::unique_ptr<LuaArg>(new LuaArg { { c->GetID(), t } }), false);
|
TriggerLuaEvent(Name, false, nullptr, std::make_unique<LuaArg>(LuaArg { { c->GetID(), t } }), false);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -171,12 +195,11 @@ void HandleEvent(Client* c, const std::string& Data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalParser(Client* c, const std::string& Pack) {
|
void GlobalParser(Client* c, const std::string& Packet) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
if (Pack.empty() || c == nullptr)
|
if (Packet.empty() || c == nullptr)
|
||||||
return;
|
return;
|
||||||
std::string Packet = Pack.substr(0, strlen(Pack.c_str()));
|
std::any Res;
|
||||||
std::string pct;
|
|
||||||
char Code = Packet.at(0);
|
char Code = Packet.at(0);
|
||||||
|
|
||||||
//V to Z
|
//V to Z
|
||||||
@@ -186,45 +209,42 @@ void GlobalParser(Client* c, const std::string& Pack) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (Code) {
|
switch (Code) {
|
||||||
case 'P': // initial connection
|
case 'H': // initial connection
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string(Sec("got 'P' packet: '")) + Pack + Sec("' (") + std::to_string(Packet.size()) + Sec(")"));
|
debug(std::string("got 'H' packet: '") + Packet + "' (" + std::to_string(Packet.size()) + ")");
|
||||||
#endif
|
#endif
|
||||||
Respond(c, Sec("P") + std::to_string(c->GetID()), true);
|
|
||||||
SyncClient(c);
|
SyncClient(c);
|
||||||
return;
|
return;
|
||||||
case 'p':
|
case 'p':
|
||||||
Respond(c, Sec("p"), false);
|
Respond(c, ("p"), false);
|
||||||
UpdatePlayers();
|
UpdatePlayers();
|
||||||
return;
|
return;
|
||||||
case 'O':
|
case 'O':
|
||||||
if (Packet.length() > 1000) {
|
if (Packet.length() > 1000) {
|
||||||
debug(Sec("Received data from: ") + c->GetName() + Sec(" Size: ") + std::to_string(Packet.length()));
|
debug(("Received data from: ") + c->GetName() + (" Size: ") + std::to_string(Packet.length()));
|
||||||
}
|
}
|
||||||
ParseVeh(c, Packet);
|
ParseVeh(c, Packet);
|
||||||
return;
|
return;
|
||||||
case 'J':
|
case 'J':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string(Sec("got 'J' packet: '")) + Pack + Sec("' (") + std::to_string(Packet.size()) + Sec(")"));
|
debug(std::string(("got 'J' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
#endif
|
#endif
|
||||||
SendToAll(c, Packet, false, true);
|
SendToAll(c, Packet, false, true);
|
||||||
return;
|
return;
|
||||||
case 'C':
|
case 'C':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string(Sec("got 'C' packet: '")) + Pack + Sec("' (") + std::to_string(Packet.size()) + Sec(")"));
|
debug(std::string(("got 'C' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
#endif
|
#endif
|
||||||
if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos)
|
if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos)
|
||||||
break;
|
break;
|
||||||
if (TriggerLuaEvent(Sec("onChatMessage"), false, nullptr,
|
Res = TriggerLuaEvent("onChatMessage", false, nullptr, std::make_unique<LuaArg>(LuaArg { { c->GetID(), c->GetName(), Packet.substr(Packet.find(':', 3) + 1) } }), true);
|
||||||
std::unique_ptr<LuaArg>(new LuaArg {
|
if (std::any_cast<int>(Res))
|
||||||
{ c->GetID(), c->GetName(), Packet.substr(Packet.find(':', 3) + 1) } }),
|
|
||||||
true))
|
|
||||||
break;
|
break;
|
||||||
SendToAll(nullptr, Packet, true, true);
|
SendToAll(nullptr, Packet, true, true);
|
||||||
return;
|
return;
|
||||||
case 'E':
|
case 'E':
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug(std::string(Sec("got 'E' packet: '")) + Pack + Sec("' (") + std::to_string(Packet.size()) + Sec(")"));
|
debug(std::string(("got 'E' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
#endif
|
#endif
|
||||||
HandleEvent(c, Packet);
|
HandleEvent(c, Packet);
|
||||||
return;
|
return;
|
||||||
@@ -241,7 +261,7 @@ void GParser(Client* c, const std::string& Packet) {
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
__try {
|
__try {
|
||||||
GlobalParser(c, Packet);
|
GlobalParser(c, Packet);
|
||||||
} __except (Handle(GetExceptionInformation(), Sec("Global Handler"))) { }
|
} __except (Handle(GetExceptionInformation(), ("Global Handler"))) { }
|
||||||
#else
|
#else
|
||||||
GlobalParser(c, Packet);
|
GlobalParser(c, Packet);
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 4/9/2020
|
/// Created by Anonymous275 on 4/9/2020
|
||||||
///
|
///
|
||||||
@@ -5,15 +9,31 @@
|
|||||||
#include "CustomAssert.h"
|
#include "CustomAssert.h"
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
class CurlManager{
|
||||||
|
public:
|
||||||
|
CurlManager(){
|
||||||
|
curl = curl_easy_init();
|
||||||
|
}
|
||||||
|
~CurlManager(){
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
inline CURL* Get(){
|
||||||
|
return curl;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
CURL *curl;
|
||||||
|
};
|
||||||
|
|
||||||
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
|
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
|
||||||
((std::string*)userp)->append((char*)contents, size * nmemb);
|
((std::string*)userp)->append((char*)contents, size * nmemb);
|
||||||
return size * nmemb;
|
return size * nmemb;
|
||||||
}
|
}
|
||||||
std::string HttpRequest(const std::string& IP, int port) {
|
std::string HttpRequest(const std::string& IP, int port) {
|
||||||
CURL* curl;
|
static thread_local CurlManager M;
|
||||||
CURLcode res;
|
|
||||||
std::string readBuffer;
|
std::string readBuffer;
|
||||||
curl = curl_easy_init();
|
CURL* curl = M.Get();
|
||||||
|
CURLcode res;
|
||||||
Assert(curl);
|
Assert(curl);
|
||||||
if (curl) {
|
if (curl) {
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
|
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
|
||||||
@@ -21,30 +41,33 @@ std::string HttpRequest(const std::string& IP, int port) {
|
|||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||||
res = curl_easy_perform(curl);
|
res = curl_easy_perform(curl);
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
if (res != CURLE_OK)
|
if (res != CURLE_OK)
|
||||||
return "-1";
|
return "-1";
|
||||||
}
|
}
|
||||||
return readBuffer;
|
return readBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PostHTTP(const std::string& IP, const std::string& Fields) {
|
std::string PostHTTP(const std::string& IP, const std::string& Fields, bool json) {
|
||||||
CURL* curl;
|
auto header = curl_slist { (char*)"Content-Type: application/json" };
|
||||||
|
static thread_local CurlManager M;
|
||||||
|
static std::mutex Lock;
|
||||||
|
std::scoped_lock Guard(Lock);
|
||||||
|
CURL* curl = M.Get();
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
std::string readBuffer;
|
std::string readBuffer;
|
||||||
curl = curl_easy_init();
|
|
||||||
Assert(curl);
|
Assert(curl);
|
||||||
if (curl) {
|
if (curl) {
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
|
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
|
||||||
/*curl_easy_setopt(curl, CURLOPT_URL, "https://95.216.35.232/heartbeatv2");
|
if (json)
|
||||||
curl_easy_setopt(curl, CURLOPT_PORT, 3600);*/
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, Fields.size());
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, Fields.size());
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, Fields.c_str());
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, Fields.c_str());
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5);
|
||||||
res = curl_easy_perform(curl);
|
res = curl_easy_perform(curl);
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
if (res != CURLE_OK)
|
if (res != CURLE_OK)
|
||||||
return "-1";
|
return "-1";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 8/1/2020
|
/// Created by Anonymous275 on 8/1/2020
|
||||||
///
|
///
|
||||||
@@ -5,8 +9,10 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Lua/LuaSystem.hpp"
|
#include "Lua/LuaSystem.hpp"
|
||||||
#include "Network.h"
|
#include "Network.h"
|
||||||
#include "Security/Enc.h"
|
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
#include "UnixCompat.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
int OpenID() {
|
int OpenID() {
|
||||||
int ID = 0;
|
int ID = 0;
|
||||||
bool found;
|
bool found;
|
||||||
@@ -57,7 +63,7 @@ void SendToAll(Client* c, const std::string& Data, bool Self, bool Rel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void UpdatePlayers() {
|
void UpdatePlayers() {
|
||||||
std::string Packet = Sec("Ss") + std::to_string(CI->Size()) + "/" + std::to_string(MaxPlayers) + ":";
|
std::string Packet = ("Ss") + std::to_string(CI->Size()) + "/" + std::to_string(MaxPlayers) + ":";
|
||||||
for (auto& c : CI->Clients) {
|
for (auto& c : CI->Clients) {
|
||||||
if (c != nullptr)
|
if (c != nullptr)
|
||||||
Packet += c->GetName() + ",";
|
Packet += c->GetName() + ",";
|
||||||
@@ -66,11 +72,8 @@ void UpdatePlayers() {
|
|||||||
SendToAll(nullptr, Packet, true, true);
|
SendToAll(nullptr, Packet, true, true);
|
||||||
}
|
}
|
||||||
void OnDisconnect(Client* c, bool kicked) {
|
void OnDisconnect(Client* c, bool kicked) {
|
||||||
|
|
||||||
Assert(c);
|
Assert(c);
|
||||||
info(c->GetName() + Sec(" Connection Terminated"));
|
info(c->GetName() + (" Connection Terminated"));
|
||||||
if (c == nullptr)
|
|
||||||
return;
|
|
||||||
std::string Packet;
|
std::string Packet;
|
||||||
for (auto& v : c->GetAllCars()) {
|
for (auto& v : c->GetAllCars()) {
|
||||||
if (v != nullptr) {
|
if (v != nullptr) {
|
||||||
@@ -79,23 +82,28 @@ void OnDisconnect(Client* c, bool kicked) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (kicked)
|
if (kicked)
|
||||||
Packet = Sec("L") + c->GetName() + Sec(" was kicked!");
|
Packet = ("L") + c->GetName() + (" was kicked!");
|
||||||
Packet = Sec("L") + c->GetName() + Sec(" Left the server!");
|
else
|
||||||
|
Packet = ("L") + c->GetName() + (" left the server!");
|
||||||
SendToAll(c, Packet, false, true);
|
SendToAll(c, Packet, false, true);
|
||||||
Packet.clear();
|
Packet.clear();
|
||||||
TriggerLuaEvent(Sec("onPlayerDisconnect"), false, nullptr, std::unique_ptr<LuaArg>(new LuaArg { { c->GetID() } }), false);
|
TriggerLuaEvent(("onPlayerDisconnect"), false, nullptr, std::make_unique<LuaArg>(LuaArg { { c->GetID() } }), false);
|
||||||
CI->RemoveClient(c); ///Removes the Client from existence
|
if (c->GetTCPSock())
|
||||||
|
CloseSocketProper(c->GetTCPSock());
|
||||||
|
if (c->GetDownSock())
|
||||||
|
CloseSocketProper(c->GetDownSock());
|
||||||
|
CI->RemoveClient(c);
|
||||||
}
|
}
|
||||||
void OnConnect(Client* c) {
|
void OnConnect(Client* c) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
info(Sec("Client connected"));
|
info("Client connected");
|
||||||
c->SetID(OpenID());
|
c->SetID(OpenID());
|
||||||
info(Sec("Assigned ID ") + std::to_string(c->GetID()) + Sec(" to ") + c->GetName());
|
info("Assigned ID " + std::to_string(c->GetID()) + " to " + c->GetName());
|
||||||
TriggerLuaEvent(Sec("onPlayerConnecting"), false, nullptr, std::unique_ptr<LuaArg>(new LuaArg { { c->GetID() } }), false);
|
TriggerLuaEvent("onPlayerConnecting", false, nullptr, std::make_unique<LuaArg>(LuaArg { { c->GetID() } }), false);
|
||||||
SyncResources(c);
|
SyncResources(c);
|
||||||
if (c->GetStatus() < 0)
|
if (c->GetStatus() < 0)
|
||||||
return;
|
return;
|
||||||
Respond(c, "M" + MapName, true); //Send the Map on connect
|
Respond(c, "M" + MapName, true); //Send the Map on connect
|
||||||
info(c->GetName() + Sec(" : Connected"));
|
info(c->GetName() + " : Connected");
|
||||||
TriggerLuaEvent(Sec("onPlayerJoining"), false, nullptr, std::unique_ptr<LuaArg>(new LuaArg { { c->GetID() } }), false);
|
TriggerLuaEvent("onPlayerJoining", false, nullptr, std::make_unique<LuaArg>(LuaArg { { c->GetID() } }), false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 6/18/2020
|
/// Created by Anonymous275 on 6/18/2020
|
||||||
///
|
///
|
||||||
@@ -9,7 +13,7 @@
|
|||||||
std::string StatReport;
|
std::string StatReport;
|
||||||
int PPS = 0;
|
int PPS = 0;
|
||||||
void Monitor() {
|
void Monitor() {
|
||||||
int R, C = 0, V = 0;
|
int C = 0, V = 0;
|
||||||
if (CI->Clients.empty()) {
|
if (CI->Clients.empty()) {
|
||||||
StatReport = "-";
|
StatReport = "-";
|
||||||
return;
|
return;
|
||||||
@@ -23,7 +27,7 @@ void Monitor() {
|
|||||||
if (C == 0 || PPS == 0) {
|
if (C == 0 || PPS == 0) {
|
||||||
StatReport = "-";
|
StatReport = "-";
|
||||||
} else {
|
} else {
|
||||||
R = (PPS / C) / V;
|
int R = (PPS / C) / V;
|
||||||
StatReport = std::to_string(R);
|
StatReport = std::to_string(R);
|
||||||
}
|
}
|
||||||
PPS = 0;
|
PPS = 0;
|
||||||
|
|||||||
@@ -1,75 +1,110 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 8/1/2020
|
/// Created by Anonymous275 on 8/1/2020
|
||||||
///
|
///
|
||||||
|
|
||||||
#include "Client.hpp"
|
#include "Client.hpp"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "Network.h"
|
||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "UnixCompat.h"
|
#include "UnixCompat.h"
|
||||||
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#ifdef __linux
|
bool TCPSendRaw(SOCKET C, char* Data, int32_t Size) {
|
||||||
// we need this for `struct stat`
|
int64_t Sent = 0;
|
||||||
#include <sys/stat.h>
|
do {
|
||||||
#endif // __linux
|
int64_t Temp = send(C, &Data[Sent], int(Size - Sent), 0);
|
||||||
|
if (Temp < 1) {
|
||||||
|
info("Socket Closed! " + std::to_string(C));
|
||||||
|
CloseSocketProper(C);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Sent += Temp;
|
||||||
|
} while (Sent < Size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void STCPSend(Client* c, std::string Data) {
|
void SplitLoad(Client* c, int64_t Sent, int64_t Size, bool D, const std::string& Name) {
|
||||||
Assert(c);
|
|
||||||
if (c == nullptr)
|
|
||||||
return;
|
|
||||||
#ifdef WIN32
|
|
||||||
int BytesSent;
|
|
||||||
int len = static_cast<int>(Data.size());
|
|
||||||
#else
|
|
||||||
int64_t BytesSent;
|
|
||||||
size_t len = Data.size();
|
|
||||||
#endif // WIN32
|
|
||||||
BytesSent = send(c->GetTCPSock(), Data.c_str(), len, 0);
|
|
||||||
Data.clear();
|
|
||||||
if (BytesSent == 0) {
|
|
||||||
if (c->GetStatus() > -1)
|
|
||||||
c->SetStatus(-1);
|
|
||||||
} else if (BytesSent < 0) {
|
|
||||||
if (c->GetStatus() > -1)
|
|
||||||
c->SetStatus(-1);
|
|
||||||
info(Sec("Closing socket, BytesSent < 0"));
|
|
||||||
CloseSocketProper(c->GetTCPSock());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void SendFile(Client* c, const std::string& Name) {
|
|
||||||
Assert(c);
|
|
||||||
info(c->GetName() + Sec(" requesting : ") + Name.substr(Name.find_last_of('/')));
|
|
||||||
struct stat Info { };
|
|
||||||
if (stat(Name.c_str(), &Info) != 0) {
|
|
||||||
STCPSend(c, Sec("Cannot Open"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::ifstream f(Name.c_str(), std::ios::binary);
|
std::ifstream f(Name.c_str(), std::ios::binary);
|
||||||
f.seekg(0, std::ios_base::end);
|
int32_t Split = 0x7735940; //125MB
|
||||||
std::streampos fileSize = f.tellg();
|
char* Data;
|
||||||
size_t Size = size_t(fileSize);
|
if (Size > Split)
|
||||||
size_t Sent = 0;
|
Data = new char[Split];
|
||||||
size_t Diff;
|
else
|
||||||
int64_t Split = 64000;
|
Data = new char[Size];
|
||||||
|
SOCKET TCPSock;
|
||||||
|
if (D)
|
||||||
|
TCPSock = c->GetDownSock();
|
||||||
|
else
|
||||||
|
TCPSock = c->GetTCPSock();
|
||||||
|
info("Split load Socket " + std::to_string(TCPSock));
|
||||||
while (c->GetStatus() > -1 && Sent < Size) {
|
while (c->GetStatus() > -1 && Sent < Size) {
|
||||||
Diff = Size - Sent;
|
int64_t Diff = Size - Sent;
|
||||||
if (Diff > size_t(Split)) {
|
if (Diff > Split) {
|
||||||
std::string Data(size_t(Split), 0);
|
f.seekg(Sent, std::ios_base::beg);
|
||||||
f.seekg(int64_t(Sent), std::ios_base::beg);
|
f.read(Data, Split);
|
||||||
f.read(&Data[0], Split);
|
if (!TCPSendRaw(TCPSock, Data, Split)) {
|
||||||
STCPSend(c, Data);
|
if (c->GetStatus() > -1)
|
||||||
Sent += size_t(Split);
|
c->SetStatus(-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Sent += Split;
|
||||||
} else {
|
} else {
|
||||||
std::string Data(Diff, 0);
|
f.seekg(Sent, std::ios_base::beg);
|
||||||
f.seekg(int64_t(Sent), std::ios_base::beg);
|
f.read(Data, Diff);
|
||||||
f.read(&Data[0], int64_t(Diff));
|
if (!TCPSendRaw(TCPSock, Data, int32_t(Diff))) {
|
||||||
STCPSend(c, Data);
|
if (c->GetStatus() > -1)
|
||||||
|
c->SetStatus(-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
Sent += Diff;
|
Sent += Diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
delete[] Data;
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SendFile(Client* c, const std::string& Name) {
|
||||||
|
Assert(c);
|
||||||
|
info(c->GetName() + " requesting : " + Name.substr(Name.find_last_of('/')));
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(Name)) {
|
||||||
|
TCPSend(c, "CO");
|
||||||
|
warn("File " + Name + " could not be accessed!");
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
TCPSend(c, "AG");
|
||||||
|
|
||||||
|
///Wait for connections
|
||||||
|
int T = 0;
|
||||||
|
while (c->GetDownSock() < 1 && T < 50) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
T++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->GetDownSock() < 1) {
|
||||||
|
error("Client doesn't have a download socket!");
|
||||||
|
if (c->GetStatus() > -1)
|
||||||
|
c->SetStatus(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t Size = std::filesystem::file_size(Name), MSize = Size / 2;
|
||||||
|
|
||||||
|
std::thread Dt(SplitLoad, c, 0, MSize, false, Name);
|
||||||
|
Dt.detach();
|
||||||
|
|
||||||
|
SplitLoad(c, MSize, Size, true, Name);
|
||||||
|
|
||||||
|
if (Dt.joinable())
|
||||||
|
Dt.join();
|
||||||
|
}
|
||||||
|
|
||||||
void Parse(Client* c, const std::string& Packet) {
|
void Parse(Client* c, const std::string& Packet) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
if (c == nullptr || Packet.empty())
|
if (c == nullptr || Packet.empty())
|
||||||
@@ -83,11 +118,11 @@ void Parse(Client* c, const std::string& Packet) {
|
|||||||
return;
|
return;
|
||||||
case 'S':
|
case 'S':
|
||||||
if (SubCode == 'R') {
|
if (SubCode == 'R') {
|
||||||
debug(Sec("Sending Mod Info"));
|
debug("Sending Mod Info");
|
||||||
std::string ToSend = FileList + FileSizes;
|
std::string ToSend = FileList + FileSizes;
|
||||||
if (ToSend.empty())
|
if (ToSend.empty())
|
||||||
ToSend = "-";
|
ToSend = "-";
|
||||||
STCPSend(c, ToSend);
|
TCPSend(c, ToSend);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
@@ -95,45 +130,25 @@ void Parse(Client* c, const std::string& Packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool STCPRecv(Client* c) {
|
|
||||||
Assert(c);
|
|
||||||
if (c == nullptr)
|
|
||||||
return false;
|
|
||||||
#define len 200
|
|
||||||
char buf[len];
|
|
||||||
ZeroMemory(buf, len);
|
|
||||||
int64_t BytesRcv = recv(c->GetTCPSock(), buf, len, 0);
|
|
||||||
#undef len
|
|
||||||
if (BytesRcv == 0) {
|
|
||||||
if (c->GetStatus() > -1)
|
|
||||||
c->SetStatus(-1);
|
|
||||||
info(Sec("Closing socket in STCP receive, BytesRcv == 0"));
|
|
||||||
CloseSocketProper(c->GetTCPSock());
|
|
||||||
return false;
|
|
||||||
} else if (BytesRcv < 0) {
|
|
||||||
if (c->GetStatus() > -1)
|
|
||||||
c->SetStatus(-1);
|
|
||||||
info(Sec("Closing socket in STCP receive, BytesRcv < 0"));
|
|
||||||
CloseSocketProper(c->GetTCPSock());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (strcmp(buf, "Done") == 0)
|
|
||||||
return false;
|
|
||||||
std::string Ret(buf, size_t(BytesRcv));
|
|
||||||
Parse(c, Ret);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncResources(Client* c) {
|
void SyncResources(Client* c) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
if (c == nullptr)
|
if (c == nullptr)
|
||||||
return;
|
return;
|
||||||
|
#ifndef DEBUG
|
||||||
try {
|
try {
|
||||||
STCPSend(c, Sec("WS"));
|
#endif
|
||||||
while (c->GetStatus() > -1 && STCPRecv(c))
|
TCPSend(c, "P" + std::to_string(c->GetID()));
|
||||||
;
|
std::string Data;
|
||||||
|
while (c->GetStatus() > -1) {
|
||||||
|
Data = TCPRcv(c);
|
||||||
|
if (Data == "Done")
|
||||||
|
break;
|
||||||
|
Parse(c, Data);
|
||||||
|
}
|
||||||
|
#ifndef DEBUG
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
except(Sec("Exception! : ") + std::string(e.what()));
|
except("Exception! : " + std::string(e.what()));
|
||||||
c->SetStatus(-1);
|
c->SetStatus(-1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 8/1/2020
|
/// Created by Anonymous275 on 8/1/2020
|
||||||
///
|
///
|
||||||
@@ -8,14 +12,12 @@
|
|||||||
#include "UnixCompat.h"
|
#include "UnixCompat.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
void TCPSend(Client* c, const std::string& Data) {
|
bool TCPSend(Client* c, const std::string& Data) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
if (c == nullptr)
|
if (c == nullptr)
|
||||||
return;
|
return false;
|
||||||
// Size is BIG ENDIAN now, use only for header!
|
|
||||||
//auto Size = htonl(int32_t(Data.size()));
|
int32_t Size, Sent;
|
||||||
///TODO : BIG ENDIAN for other OS
|
|
||||||
int32_t Size, Sent, Temp;
|
|
||||||
std::string Send(4, 0);
|
std::string Send(4, 0);
|
||||||
Size = int32_t(Data.size());
|
Size = int32_t(Data.size());
|
||||||
memcpy(&Send[0], &Size, sizeof(Size));
|
memcpy(&Send[0], &Size, sizeof(Size));
|
||||||
@@ -23,71 +25,71 @@ void TCPSend(Client* c, const std::string& Data) {
|
|||||||
Sent = 0;
|
Sent = 0;
|
||||||
Size += 4;
|
Size += 4;
|
||||||
do {
|
do {
|
||||||
Temp = send(c->GetTCPSock(), &Send[Sent], Size - Sent, 0);
|
int32_t Temp = send(c->GetTCPSock(), &Send[Sent], Size - Sent, 0);
|
||||||
if (Temp == 0) {
|
if (Temp == 0) {
|
||||||
if (c->GetStatus() > -1)
|
if (c->GetStatus() > -1)
|
||||||
c->SetStatus(-1);
|
c->SetStatus(-1);
|
||||||
return;
|
return false;
|
||||||
} else if (Temp < 0) {
|
} else if (Temp < 0) {
|
||||||
if (c->GetStatus() > -1)
|
if (c->GetStatus() > -1)
|
||||||
c->SetStatus(-1);
|
c->SetStatus(-1);
|
||||||
// info(Sec("Closing socket, Temp < 0"));
|
|
||||||
CloseSocketProper(c->GetTCPSock());
|
CloseSocketProper(c->GetTCPSock());
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
Sent += Temp;
|
Sent += Temp;
|
||||||
} while (Sent < Size);
|
} while (Sent < Size);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckBytes(Client* c, int32_t BytesRcv) {
|
bool CheckBytes(Client* c, int32_t BytesRcv) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
if (BytesRcv == 0) {
|
if (BytesRcv == 0) {
|
||||||
debug(Sec("(TCP) Connection closing..."));
|
debug("(TCP) Connection closing...");
|
||||||
if (c->GetStatus() > -1)
|
if (c->GetStatus() > -1)
|
||||||
c->SetStatus(-1);
|
c->SetStatus(-1);
|
||||||
return false;
|
return false;
|
||||||
} else if (BytesRcv < 0) {
|
} else if (BytesRcv < 0) {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
debug(Sec("(TCP) recv failed with error: ") + std::to_string(WSAGetLastError()));
|
debug(("(TCP) recv failed with error: ") + std::to_string(WSAGetLastError()));
|
||||||
#else // unix
|
#else // unix
|
||||||
debug(Sec("(TCP) recv failed with error: ") + std::string(strerror(errno)));
|
debug(("(TCP) recv failed with error: ") + std::string(strerror(errno)));
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
if (c->GetStatus() > -1)
|
if (c->GetStatus() > -1)
|
||||||
c->SetStatus(-1);
|
c->SetStatus(-1);
|
||||||
info(Sec("Closing socket in CheckBytes, BytesRcv < 0"));
|
info(("Closing socket in CheckBytes, BytesRcv < 0"));
|
||||||
CloseSocketProper(c->GetTCPSock());
|
CloseSocketProper(c->GetTCPSock());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCPRcv(Client* c) {
|
std::string TCPRcv(Client* c) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
int32_t Header, BytesRcv = 0, Temp;
|
int32_t Header, BytesRcv = 0, Temp;
|
||||||
if (c == nullptr || c->GetStatus() < 0)
|
if (c == nullptr || c->GetStatus() < 0)
|
||||||
return;
|
return "";
|
||||||
|
|
||||||
std::vector<char> Data(sizeof(Header));
|
std::vector<char> Data(sizeof(Header));
|
||||||
do {
|
do {
|
||||||
Temp = recv(c->GetTCPSock(), &Data[BytesRcv], 4 - BytesRcv, 0);
|
Temp = recv(c->GetTCPSock(), &Data[BytesRcv], 4 - BytesRcv, 0);
|
||||||
if (!CheckBytes(c, Temp)) {
|
if (!CheckBytes(c, Temp)) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
error(std::string(__func__) + Sec(": failed on CheckBytes in while(BytesRcv < 4)"));
|
error(std::string(__func__) + (": failed on CheckBytes in while(BytesRcv < 4)"));
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
return;
|
return "";
|
||||||
}
|
}
|
||||||
BytesRcv += Temp;
|
BytesRcv += Temp;
|
||||||
} while (size_t(BytesRcv) < sizeof(Header));
|
} while (size_t(BytesRcv) < sizeof(Header));
|
||||||
memcpy(&Header, &Data[0], sizeof(Header));
|
memcpy(&Header, &Data[0], sizeof(Header));
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
//debug(std::string(__func__) + Sec(": expecting ") + std::to_string(Header) + Sec(" bytes."));
|
//debug(std::string(__func__) + (": expecting ") + std::to_string(Header) + (" bytes."));
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
if (!CheckBytes(c, BytesRcv)) {
|
if (!CheckBytes(c, BytesRcv)) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
error(std::string(__func__) + Sec(": failed on CheckBytes"));
|
error(std::string(__func__) + (": failed on CheckBytes"));
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
return;
|
return "";
|
||||||
}
|
}
|
||||||
Data.resize(Header);
|
Data.resize(Header);
|
||||||
BytesRcv = 0;
|
BytesRcv = 0;
|
||||||
@@ -95,18 +97,18 @@ void TCPRcv(Client* c) {
|
|||||||
Temp = recv(c->GetTCPSock(), &Data[BytesRcv], Header - BytesRcv, 0);
|
Temp = recv(c->GetTCPSock(), &Data[BytesRcv], Header - BytesRcv, 0);
|
||||||
if (!CheckBytes(c, Temp)) {
|
if (!CheckBytes(c, Temp)) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
error(std::string(__func__) + Sec(": failed on CheckBytes in while(BytesRcv < Header)"));
|
error(std::string(__func__) + (": failed on CheckBytes in while(BytesRcv < Header)"));
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
return;
|
return "";
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
//debug(std::string(__func__) + Sec(": Temp: ") + std::to_string(Temp) + Sec(", BytesRcv: ") + std::to_string(BytesRcv));
|
//debug(std::string(__func__) + (": Temp: ") + std::to_string(Temp) + (", BytesRcv: ") + std::to_string(BytesRcv));
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
BytesRcv += Temp;
|
BytesRcv += Temp;
|
||||||
} while (BytesRcv < Header);
|
} while (BytesRcv < Header);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
//debug(std::string(__func__) + Sec(": finished recv with Temp: ") + std::to_string(Temp) + Sec(", BytesRcv: ") + std::to_string(BytesRcv));
|
//debug(std::string(__func__) + (": finished recv with Temp: ") + std::to_string(Temp) + (", BytesRcv: ") + std::to_string(BytesRcv));
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
std::string Ret(Data.data(), Header);
|
std::string Ret(Data.data(), Header);
|
||||||
|
|
||||||
@@ -116,22 +118,20 @@ void TCPRcv(Client* c) {
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
//debug("Parsing from " + c->GetName() + " -> " +std::to_string(Ret.size()));
|
//debug("Parsing from " + c->GetName() + " -> " +std::to_string(Ret.size()));
|
||||||
#endif
|
#endif
|
||||||
GParser(c, Ret);
|
|
||||||
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCPClient(Client* c) {
|
void TCPClient(Client* c) {
|
||||||
DebugPrintTIDInternal(Sec("Client(") + c->GetName() + Sec(")"), true);
|
DebugPrintTIDInternal("Client(" + c->GetName() + ")", true);
|
||||||
Assert(c);
|
Assert(c);
|
||||||
if (c->GetTCPSock() == -1) {
|
if (c->GetTCPSock() == -1) {
|
||||||
CI->RemoveClient(c);
|
CI->RemoveClient(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OnConnect(c);
|
OnConnect(c);
|
||||||
while (c->GetStatus() > -1)
|
while (c->GetStatus() > -1) {
|
||||||
TCPRcv(c);
|
GParser(c, TCPRcv(c));
|
||||||
|
}
|
||||||
OnDisconnect(c, c->GetStatus() == -2);
|
OnDisconnect(c, c->GetStatus() == -2);
|
||||||
}
|
}
|
||||||
void InitClient(Client* c) {
|
|
||||||
std::thread NewClient(TCPClient, c);
|
|
||||||
NewClient.detach();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 5/8/2020
|
/// Created by Anonymous275 on 5/8/2020
|
||||||
///
|
///
|
||||||
///UDP
|
|
||||||
#include "Client.hpp"
|
#include "Client.hpp"
|
||||||
#include "Compressor.h"
|
#include "Compressor.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
@@ -9,28 +13,14 @@
|
|||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "UnixCompat.h"
|
#include "UnixCompat.h"
|
||||||
#include <array>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
int FC(const std::string& s, const std::string& p, int n);
|
#include <array>
|
||||||
struct PacketData {
|
|
||||||
int ID;
|
|
||||||
::Client* Client;
|
|
||||||
std::string Data;
|
|
||||||
int Tries;
|
|
||||||
};
|
|
||||||
struct SplitData {
|
|
||||||
int Total {};
|
|
||||||
int ID {};
|
|
||||||
std::set<std::pair<int, std::string>> Fragments;
|
|
||||||
};
|
|
||||||
|
|
||||||
SOCKET UDPSock;
|
SOCKET UDPSock;
|
||||||
std::set<PacketData*> DataAcks;
|
|
||||||
std::set<SplitData*> SplitPackets;
|
|
||||||
void UDPSend(Client* c, std::string Data) {
|
void UDPSend(Client* c, std::string Data) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
if (c == nullptr || !c->isConnected || c->GetStatus() < 0)
|
if (c == nullptr || !c->isConnected || c->GetStatus() < 0)
|
||||||
@@ -52,51 +42,27 @@ void UDPSend(Client* c, std::string Data) {
|
|||||||
sendOk = sendto(UDPSock, Data.c_str(), len, 0, (sockaddr*)&Addr, AddrSize);
|
sendOk = sendto(UDPSock, Data.c_str(), len, 0, (sockaddr*)&Addr, AddrSize);
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
if (sendOk == -1) {
|
if (sendOk == -1) {
|
||||||
debug(Sec("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError()));
|
debug(("(UDP) Send Failed Code : ") + std::to_string(WSAGetLastError()));
|
||||||
if (c->GetStatus() > -1)
|
if (c->GetStatus() > -1)
|
||||||
c->SetStatus(-1);
|
c->SetStatus(-1);
|
||||||
} else if (sendOk == 0) {
|
} else if (sendOk == 0) {
|
||||||
debug(Sec("(UDP) sendto returned 0"));
|
debug(("(UDP) sendto returned 0"));
|
||||||
if (c->GetStatus() > -1)
|
if (c->GetStatus() > -1)
|
||||||
c->SetStatus(-1);
|
c->SetStatus(-1);
|
||||||
}
|
}
|
||||||
#else // unix
|
#else // unix
|
||||||
if (sendOk == -1) {
|
if (sendOk == -1) {
|
||||||
debug(Sec("(UDP) Send Failed Code : ") + std::string(strerror(errno)));
|
debug(("(UDP) Send Failed Code : ") + std::string(strerror(errno)));
|
||||||
if (c->GetStatus() > -1)
|
if (c->GetStatus() > -1)
|
||||||
c->SetStatus(-1);
|
c->SetStatus(-1);
|
||||||
} else if (sendOk == 0) {
|
} else if (sendOk == 0) {
|
||||||
debug(Sec("(UDP) sendto returned 0"));
|
debug(("(UDP) sendto returned 0"));
|
||||||
if (c->GetStatus() > -1)
|
if (c->GetStatus() > -1)
|
||||||
c->SetStatus(-1);
|
c->SetStatus(-1);
|
||||||
}
|
}
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
void AckID(int ID) {
|
|
||||||
for (PacketData* p : DataAcks) {
|
|
||||||
if (p != nullptr && p->ID == ID) {
|
|
||||||
DataAcks.erase(p);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int PacktID() {
|
|
||||||
static int ID = -1;
|
|
||||||
if (ID > 999999)
|
|
||||||
ID = 0;
|
|
||||||
else
|
|
||||||
ID++;
|
|
||||||
return ID;
|
|
||||||
}
|
|
||||||
int SplitID() {
|
|
||||||
static int SID = -1;
|
|
||||||
if (SID > 999999)
|
|
||||||
SID = 0;
|
|
||||||
else
|
|
||||||
SID++;
|
|
||||||
return SID;
|
|
||||||
}
|
|
||||||
void SendLarge(Client* c, std::string Data) {
|
void SendLarge(Client* c, std::string Data) {
|
||||||
Assert(c);
|
Assert(c);
|
||||||
if (Data.length() > 400) {
|
if (Data.length() > 400) {
|
||||||
@@ -105,121 +71,22 @@ void SendLarge(Client* c, std::string Data) {
|
|||||||
}
|
}
|
||||||
TCPSend(c, Data);
|
TCPSend(c, Data);
|
||||||
}
|
}
|
||||||
struct HandledC {
|
|
||||||
size_t Pos = 0;
|
|
||||||
Client* c = nullptr;
|
|
||||||
std::array<int, 100> HandledIDs = { -1 };
|
|
||||||
};
|
|
||||||
std::set<HandledC*> HandledIDs;
|
|
||||||
void ResetIDs(HandledC* H) {
|
|
||||||
for (size_t C = 0; C < 100; C++) {
|
|
||||||
H->HandledIDs.at(C) = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HandledC* GetHandled(Client* c) {
|
|
||||||
Assert(c);
|
|
||||||
for (HandledC* h : HandledIDs) {
|
|
||||||
if (h->c == c) {
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new HandledC();
|
|
||||||
}
|
|
||||||
bool Handled(Client* c, int ID) {
|
|
||||||
Assert(c);
|
|
||||||
bool handle = false;
|
|
||||||
for (HandledC* h : HandledIDs) {
|
|
||||||
if (h->c == c) {
|
|
||||||
for (int id : h->HandledIDs) {
|
|
||||||
if (id == ID)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (h->Pos > 99)
|
|
||||||
h->Pos = 0;
|
|
||||||
h->HandledIDs.at(h->Pos) = ID;
|
|
||||||
h->Pos++;
|
|
||||||
handle = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (HandledC* h : HandledIDs) {
|
|
||||||
if (h->c == nullptr || !h->c->isConnected) {
|
|
||||||
HandledIDs.erase(h);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!handle) {
|
|
||||||
HandledC* h = GetHandled(c);
|
|
||||||
ResetIDs(h);
|
|
||||||
if (h->Pos > 99)
|
|
||||||
h->Pos = 0;
|
|
||||||
h->HandledIDs.at(h->Pos) = ID;
|
|
||||||
h->Pos++;
|
|
||||||
h->c = c;
|
|
||||||
HandledIDs.insert(h);
|
|
||||||
}
|
|
||||||
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);
|
std::array<char, 1024> Ret{};
|
||||||
std::string Ret(10240, 0);
|
int64_t Rcv = recvfrom(UDPSock, Ret.data(), Ret.size(), 0, (sockaddr*)&client, (socklen_t*)&clientLength);
|
||||||
int64_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(("(UDP) Error receiving from Client! Code : ") + std::to_string(WSAGetLastError()));
|
||||||
#else // unix
|
#else // unix
|
||||||
error(Sec("(UDP) Error receiving from Client! Code : ") + std::string(strerror(errno)));
|
error(("(UDP) Error receiving from Client! Code : ") + std::string(strerror(errno)));
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return Ret.substr(0, Rcv);
|
return std::string(Ret.begin(), Ret.begin() + Rcv);
|
||||||
}
|
}
|
||||||
|
|
||||||
SplitData* GetSplit(int SplitID) {
|
|
||||||
for (SplitData* a : SplitPackets) {
|
|
||||||
if (a->ID == SplitID)
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
auto* SP = new SplitData();
|
|
||||||
SplitPackets.insert(SP);
|
|
||||||
return SP;
|
|
||||||
}
|
|
||||||
void HandleChunk(Client* c, const std::string& Data) {
|
|
||||||
Assert(c);
|
|
||||||
int pos = FC(Data, "|", 5);
|
|
||||||
if (pos == -1)
|
|
||||||
return;
|
|
||||||
std::stringstream ss(Data.substr(0, size_t(pos++)));
|
|
||||||
std::string t;
|
|
||||||
int I = -1;
|
|
||||||
//Current Max ID SID
|
|
||||||
std::vector<int> Num(4, 0);
|
|
||||||
while (std::getline(ss, t, '|')) {
|
|
||||||
if (I >= 0)
|
|
||||||
Num.at(size_t(I)) = std::stoi(t);
|
|
||||||
I++;
|
|
||||||
}
|
|
||||||
std::string ack = "TRG:" + std::to_string(Num.at(2));
|
|
||||||
UDPSend(c, ack);
|
|
||||||
if (Handled(c, Num.at(2))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::string Packet = Data.substr(size_t(pos));
|
|
||||||
SplitData* SData = GetSplit(Num.at(3));
|
|
||||||
SData->Total = Num.at(1);
|
|
||||||
SData->ID = Num.at(3);
|
|
||||||
SData->Fragments.insert(std::make_pair(Num.at(0), Packet));
|
|
||||||
if (SData->Fragments.size() == size_t(SData->Total)) {
|
|
||||||
std::string ToHandle;
|
|
||||||
for (const std::pair<int, std::string>& a : SData->Fragments) {
|
|
||||||
ToHandle += a.second;
|
|
||||||
}
|
|
||||||
GParser(c, ToHandle);
|
|
||||||
SplitPackets.erase(SData);
|
|
||||||
delete SData;
|
|
||||||
SData = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void UDPParser(Client* c, std::string Packet) {
|
void UDPParser(Client* c, std::string Packet) {
|
||||||
if (Packet.find("Zp") != std::string::npos && Packet.size() > 500) {
|
if (Packet.find("Zp") != std::string::npos && Packet.size() > 500) {
|
||||||
abort();
|
abort();
|
||||||
@@ -228,56 +95,14 @@ 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:") {
|
|
||||||
std::string pkt = Packet.substr(4);
|
|
||||||
if (Packet.find_first_not_of("0123456789") == std::string::npos) {
|
|
||||||
AckID(stoi(Packet));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else if (Packet.substr(0, 3) == "BD:") {
|
|
||||||
auto pos = Packet.find(':', 4);
|
|
||||||
int ID = stoi(Packet.substr(3, pos - 3));
|
|
||||||
std::string pkt = "TRG:" + std::to_string(ID);
|
|
||||||
UDPSend(c, pkt);
|
|
||||||
if (!Handled(c, ID)) {
|
|
||||||
pkt = Packet.substr(pos + 1);
|
|
||||||
GParser(c, pkt);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else if (Packet.substr(0, 2) == "SC") {
|
|
||||||
HandleChunk(c, Packet);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GParser(c, Packet);
|
GParser(c, Packet);
|
||||||
}
|
}
|
||||||
void LOOP() {
|
|
||||||
DebugPrintTID();
|
|
||||||
while (UDPSock != -1) {
|
|
||||||
if (!DataAcks.empty()) {
|
|
||||||
for (PacketData* p : DataAcks) {
|
|
||||||
if (p != nullptr) {
|
|
||||||
if (p->Client == nullptr || p->Client->GetTCPSock() == -1) {
|
|
||||||
DataAcks.erase(p);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (p->Tries < 15) {
|
|
||||||
UDPSend(p->Client, p->Data);
|
|
||||||
p->Tries++;
|
|
||||||
} else {
|
|
||||||
DataAcks.erase(p);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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(("Can't start Winsock!"));
|
||||||
//return;
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,23 +115,19 @@ void LOOP() {
|
|||||||
|
|
||||||
// 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(("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);
|
||||||
//return;
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataAcks.clear();
|
info(("Vehicle data network online on port ") + std::to_string(Port) + (" with a Max of ") + std::to_string(MaxPlayers) + (" Clients"));
|
||||||
std::thread Ack(LOOP);
|
|
||||||
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"));
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
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)
|
if (Data.empty() || Pos == std::string::npos || Pos > 2)
|
||||||
continue;
|
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
|
||||||
@@ -320,7 +141,7 @@ void LOOP() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
error(Sec("fatal: ") + std::string(e.what()));
|
error(("fatal: ") + std::string(e.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*CloseSocketProper(UDPSock);
|
/*CloseSocketProper(UDPSock);
|
||||||
@@ -336,17 +157,13 @@ void LOOP() {
|
|||||||
|
|
||||||
// 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(("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);
|
||||||
//return;
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataAcks.clear();
|
info(("Vehicle data network online on port ") + std::to_string(Port) + (" with a Max of ") + std::to_string(MaxPlayers) + (" Clients"));
|
||||||
std::thread Ack(LOOP);
|
|
||||||
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"));
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
sockaddr_in client {};
|
sockaddr_in client {};
|
||||||
@@ -366,7 +183,7 @@ void LOOP() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
error(Sec("fatal: ") + std::string(e.what()));
|
error(("fatal: ") + std::string(e.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*CloseSocketProper(UDPSock); // TODO: Why not this? We did this in TCPServerMain?
|
/*CloseSocketProper(UDPSock); // TODO: Why not this? We did this in TCPServerMain?
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 11/6/2020
|
/// Created by Anonymous275 on 11/6/2020
|
||||||
///
|
///
|
||||||
@@ -5,11 +9,11 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Security/Enc.h"
|
#include "Security/Enc.h"
|
||||||
#include <boost/asio/connect.hpp>
|
#include <boost/asio/connect.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>*/
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/beast/websocket.hpp>
|
#include <boost/beast/websocket.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>*/
|
||||||
|
|
||||||
/*namespace beast = boost::beast;
|
/*namespace beast = boost::beast;
|
||||||
namespace http = beast::http;
|
namespace http = beast::http;
|
||||||
@@ -24,13 +28,13 @@ std::string GetRes(const beast::flat_buffer& buff) {
|
|||||||
void SyncData() {
|
void SyncData() {
|
||||||
/*DebugPrintTID();
|
/*DebugPrintTID();
|
||||||
try {
|
try {
|
||||||
std::string const host = Sec("95.216.35.232");
|
std::string const host = ("95.216.35.232");
|
||||||
|
|
||||||
net::io_context ioc;
|
net::io_context ioc;
|
||||||
tcp::resolver r(ioc);
|
tcp::resolver r(ioc);
|
||||||
|
|
||||||
websocket::stream<tcp::socket> ws(ioc);
|
websocket::stream<tcp::socket> ws(ioc);
|
||||||
auto const results = r.resolve(host, Sec("3600"));
|
auto const results = r.resolve(host, ("3600"));
|
||||||
net::connect(ws.next_layer(), results.begin(), results.end());
|
net::connect(ws.next_layer(), results.begin(), results.end());
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright (c) 2019-present Anonymous275.
|
||||||
|
// BeamMP Server code is not in the public domain and is not free software.
|
||||||
|
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
|
||||||
|
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
|
||||||
///
|
///
|
||||||
/// Created by Anonymous275 on 7/17/2020
|
/// Created by Anonymous275 on 7/17/2020
|
||||||
///
|
///
|
||||||
@@ -36,17 +40,7 @@ void SetThreadName(const std::string& Name, bool overwrite) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string getDate() {
|
std::string getDate() {
|
||||||
typedef std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>::type> days;
|
|
||||||
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
||||||
std::chrono::system_clock::duration tp = now.time_since_epoch();
|
|
||||||
days d = std::chrono::duration_cast<days>(tp);
|
|
||||||
tp -= d;
|
|
||||||
auto h = std::chrono::duration_cast<std::chrono::hours>(tp);
|
|
||||||
tp -= h;
|
|
||||||
auto m = std::chrono::duration_cast<std::chrono::minutes>(tp);
|
|
||||||
tp -= m;
|
|
||||||
auto s = std::chrono::duration_cast<std::chrono::seconds>(tp);
|
|
||||||
tp -= s;
|
|
||||||
time_t tt = std::chrono::system_clock::to_time_t(now);
|
time_t tt = std::chrono::system_clock::to_time_t(now);
|
||||||
tm local_tm {};
|
tm local_tm {};
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -79,9 +73,9 @@ std::string getDate() {
|
|||||||
|
|
||||||
void InitLog() {
|
void InitLog() {
|
||||||
std::ofstream LFS;
|
std::ofstream LFS;
|
||||||
LFS.open(Sec("Server.log"));
|
LFS.open(("Server.log"));
|
||||||
if (!LFS.is_open()) {
|
if (!LFS.is_open()) {
|
||||||
error(Sec("logger file init failed!"));
|
error(("logger file init failed!"));
|
||||||
} else
|
} else
|
||||||
LFS.close();
|
LFS.close();
|
||||||
}
|
}
|
||||||
@@ -101,13 +95,13 @@ void DebugPrintTIDInternal(const std::string& func, bool overwrite) {
|
|||||||
|
|
||||||
void addToLog(const std::string& Line) {
|
void addToLog(const std::string& Line) {
|
||||||
std::ofstream LFS;
|
std::ofstream LFS;
|
||||||
LFS.open(Sec("Server.log"), std::ios_base::app);
|
LFS.open(("Server.log"), std::ios_base::app);
|
||||||
LFS << Line.c_str();
|
LFS << Line.c_str();
|
||||||
LFS.close();
|
LFS.close();
|
||||||
}
|
}
|
||||||
void info(const std::string& toPrint) {
|
void info(const std::string& toPrint) {
|
||||||
std::scoped_lock Guard(LogLock);
|
std::scoped_lock Guard(LogLock);
|
||||||
std::string Print = getDate() + Sec("[INFO] ") + toPrint + "\n";
|
std::string Print = getDate() + ("[INFO] ") + toPrint + "\n";
|
||||||
ConsoleOut(Print);
|
ConsoleOut(Print);
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
}
|
}
|
||||||
@@ -115,25 +109,25 @@ void debug(const std::string& toPrint) {
|
|||||||
if (!Debug)
|
if (!Debug)
|
||||||
return;
|
return;
|
||||||
std::scoped_lock Guard(LogLock);
|
std::scoped_lock Guard(LogLock);
|
||||||
std::string Print = getDate() + Sec("[DEBUG] ") + toPrint + "\n";
|
std::string Print = getDate() + ("[DEBUG] ") + toPrint + "\n";
|
||||||
ConsoleOut(Print);
|
ConsoleOut(Print);
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
}
|
}
|
||||||
void warn(const std::string& toPrint) {
|
void warn(const std::string& toPrint) {
|
||||||
std::scoped_lock Guard(LogLock);
|
std::scoped_lock Guard(LogLock);
|
||||||
std::string Print = getDate() + Sec("[WARN] ") + toPrint + "\n";
|
std::string Print = getDate() + ("[WARN] ") + toPrint + "\n";
|
||||||
ConsoleOut(Print);
|
ConsoleOut(Print);
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
}
|
}
|
||||||
void error(const std::string& toPrint) {
|
void error(const std::string& toPrint) {
|
||||||
std::scoped_lock Guard(LogLock);
|
std::scoped_lock Guard(LogLock);
|
||||||
std::string Print = getDate() + Sec("[ERROR] ") + toPrint + "\n";
|
std::string Print = getDate() + ("[ERROR] ") + toPrint + "\n";
|
||||||
ConsoleOut(Print);
|
ConsoleOut(Print);
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
}
|
}
|
||||||
void except(const std::string& toPrint) {
|
void except(const std::string& toPrint) {
|
||||||
std::scoped_lock Guard(LogLock);
|
std::scoped_lock Guard(LogLock);
|
||||||
std::string Print = getDate() + Sec("[EXCEP] ") + toPrint + "\n";
|
std::string Print = getDate() + ("[EXCEP] ") + toPrint + "\n";
|
||||||
ConsoleOut(Print);
|
ConsoleOut(Print);
|
||||||
addToLog(Print);
|
addToLog(Print);
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/main.cpp
11
src/main.cpp
@@ -1,18 +1,18 @@
|
|||||||
#include "CustomAssert.h"
|
#include "CustomAssert.h"
|
||||||
#include "Security/Xor.h"
|
|
||||||
#include "Startup.h"
|
#include "Startup.h"
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <signal.h>
|
#include <csignal>
|
||||||
void UnixSignalHandler(int sig) {
|
void UnixSignalHandler(int sig) {
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case SIGPIPE:
|
case SIGPIPE:
|
||||||
warn(Sec("ignored signal SIGPIPE: Pipe broken"));
|
warn(("ignored signal SIGPIPE: Pipe broken"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error(Sec("Signal arrived in handler but was not handled: ") + std::to_string(sig));
|
error(("Signal arrived in handler but was not handled: ") + std::to_string(sig));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,8 @@ int main(int argc, char* argv[]) {
|
|||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
DebugPrintTID();
|
DebugPrintTID();
|
||||||
// curl needs to be initialized to properly deallocate its resources later
|
// curl needs to be initialized to properly deallocate its resources later
|
||||||
Assert(curl_global_init(CURL_GLOBAL_DEFAULT) == CURLE_OK);
|
[[maybe_unused]] auto ret = curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
Assert(ret == CURLE_OK);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::thread t1(loop);
|
std::thread t1(loop);
|
||||||
t1.detach();
|
t1.detach();
|
||||||
|
|||||||
Reference in New Issue
Block a user