feat: min code change linux support

This commit is contained in:
mk
2025-11-03 21:03:17 -03:00
parent 777a006792
commit 8d424b7210
19 changed files with 374 additions and 8 deletions

7
.gitignore vendored
View File

@@ -30,3 +30,10 @@
*.exe
*.out
*.app
# Json files created by vscode/zed
*.json
# CMake build and clangd cache
build
.cache/

65
CMakeLists.txt Normal file
View File

@@ -0,0 +1,65 @@
cmake_minimum_required(VERSION 3.16)
project(champions-server VERSION 1.0 LANGUAGES CXX)
# Set default build type to Release
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
message(STATUS "Exporting compile_commands.json...")
endif()
# Compile server with c++20
add_executable(champions-server)
target_compile_features(champions-server PRIVATE cxx_std_20)
# Debug version to have symbols to debug
# Release can't debug and is optimized
target_compile_options(champions-server PRIVATE
$<$<CONFIG:Debug>:-g -O0>
$<$<CONFIG:Release>:-O3 -DNDEBUG>
)
# Enable all warnings
if (MSVC) # For windows
target_compile_options(champions-server PRIVATE /W4)
else() # For linux
target_compile_options(champions-server PRIVATE -Wall -Wextra -Wpedantic)
endif()
# Glob all files for cmake
file(GLOB_RECURSE SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
file(GLOB_RECURSE HEADER_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h")
# Filter out CMake internal files
set(FILTERED_SRC_FILES "")
foreach(file ${SRC_FILES})
if(NOT file MATCHES "CMakeFiles/")
list(APPEND FILTERED_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
endif()
endforeach()
# Targets and links
target_sources(champions-server PRIVATE ${FILTERED_SRC_FILES} ${HEADER_FILES})
target_link_libraries(champions-server PRIVATE sqlite3)
target_include_directories(champions-server
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/Common"
"${CMAKE_CURRENT_SOURCE_DIR}/Crypto"
"${CMAKE_CURRENT_SOURCE_DIR}/Database"
"${CMAKE_CURRENT_SOURCE_DIR}/Dependency/sqlite"
"${CMAKE_CURRENT_SOURCE_DIR}/Discovery Server"
"${CMAKE_CURRENT_SOURCE_DIR}/Game"
"${CMAKE_CURRENT_SOURCE_DIR}/Lobby Server"
"${CMAKE_CURRENT_SOURCE_DIR}/Network"
)
# Organize files in IDEs by folder structure
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${FILTERED_SRC_FILES} ${HEADER_FILES})

View File

@@ -9,6 +9,10 @@
#include "Utility.h"
#include "../Crypto/RealmCrypt.h"
#ifdef __linux__
typedef float float_t;
#endif
class ByteBuffer {
public:
ByteBuffer( const std::vector< uint8_t > &data );

View File

@@ -2,9 +2,11 @@
#include <cmath>
#include <string>
#include <cstdint>
#if defined(_WIN32) || defined(WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#endif
#include "Utility.h"
@@ -62,6 +64,7 @@ std::string Util::IPFromAddr( const sockaddr_in &addr )
return {};
}
#if defined(_WIN32) || defined(WIN32)
std::string Util::WideToUTF8( const std::wstring &wstr )
{
if( wstr.empty() ) return {};
@@ -95,3 +98,20 @@ std::wstring Util::UTF8ToWide( const std::string &str )
);
return result;
}
#endif
#ifdef __linux__
std::string Util::WideToUTF8( const std::wstring &wstr )
{
if( wstr.empty() ) return {};
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
return conv.to_bytes(wstr);
}
std::wstring Util::UTF8ToWide( const std::string &str )
{
if( str.empty() ) return {};
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
return conv.from_bytes(str);
}
#endif

View File

@@ -2,7 +2,17 @@
#include <cstdint>
#include <string>
#ifdef __linux__
#include <netinet/in.h>
#include <arpa/inet.h>
#include <codecvt>
#include <locale>
#endif
#if defined(_WIN32) || defined(WIN32)
#include <WinSock2.h>
#endif
namespace Util
{

View File

@@ -6,6 +6,9 @@
#include <stdexcept>
#include <string>
#include <vector>
#ifdef __linux__
#include <cstdint>
#endif
class rijndael {
private:

View File

@@ -85,7 +85,12 @@ void DiscoveryServer::Run()
{
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
#ifdef __linux__
auto bytesReceived = recvfrom( m_socket, ( char * )m_recvBuffer.data(), 1024, 0, ( struct sockaddr * )&clientAddr, (socklen_t*)&clientAddrLen );
#endif
#if defined(_WIN32) || defined(WIN32)
auto bytesReceived = recvfrom( m_socket, ( char * )m_recvBuffer.data(), 1024, 0, ( struct sockaddr * )&clientAddr, &clientAddrLen );
#endif
if( bytesReceived == SOCKET_ERROR || bytesReceived < 4 )
{

View File

@@ -6,8 +6,22 @@
#include <mutex>
#include <atomic>
#include <vector>
#if defined(_WIN32) || defined(WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#ifdef __linux__
#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define SOCKADDR sockaddr
#include <sys/socket.h>
#define closesocket(s) close(s)
#define InetPtonA(inet, ip, service_addr) inet_pton(inet, ip, service_addr)
#define InetNtopA(inet, client_ip, remote_ip,size) inet_ntop(inet, client_ip, remote_ip, size)
#endif
#include "../Common/ByteStream.h"

View File

@@ -1,5 +1,6 @@
#pragma once
#include <algorithm>
#include <string>
#include <memory>
#include <array>

View File

@@ -12,6 +12,11 @@
#include "../../configuration.h"
#include "../../logging.h"
#ifdef __linux__
#include <cerrno>
#include <sys/socket.h>
#endif
LobbyServer::LobbyServer()
{
m_running = false;
@@ -144,8 +149,14 @@ sptr_socket LobbyServer::OpenListenerSocket( std::string ip, int32_t port, Realm
void LobbyServer::Run()
{
#ifdef __linux__
fd_set readSet;
fd_set writeSet;
#endif
#if defined(_WIN32) || defined(WIN32)
FD_SET readSet;
FD_SET writeSet;
#endif
timeval timeout = { 0, 1000 };
@@ -255,7 +266,12 @@ void LobbyServer::CheckSocketProblem()
void LobbyServer::AcceptConnection( sptr_socket srcSocket )
{
sockaddr_in clientInfo{};
#ifdef __linux__
socklen_t addrSize = sizeof(clientInfo);
#endif
#if defined(_WIN32) || defined(WIN32)
int32_t addrSize = sizeof( clientInfo );
#endif
SOCKET clientSocket = accept( srcSocket->fd, ( SOCKADDR * )&clientInfo, &addrSize );
if( clientSocket == INVALID_SOCKET )
@@ -293,7 +309,12 @@ void LobbyServer::ReadSocket( sptr_socket socket )
if( bytesReceived == SOCKET_ERROR )
{
Log::Info( "Socket Error [{}].", WSAGetLastError() );
#if defined(_WIN32) || defined(WIN32)
Log::Info( "Socket Error [{}].", WSAGetLastError() );
#endif
#ifdef __linux__
Log::Info( "Socket Error [{}].", strerror(errno) );
#endif
socket->flag.disconnected_forced = true;
return;
}
@@ -369,8 +390,14 @@ void LobbyServer::WriteSocket( sptr_socket socket )
if( bytesSent == SOCKET_ERROR )
{
const int err = WSAGetLastError();
if( err == WSAEWOULDBLOCK )
#if defined(_WIN32) || defined(WIN32)
const int err = WSAGetLastError();
#endif
#ifdef __linux__
const int err = errno;
#endif
if( err == WSAEWOULDBLOCK )
break;
Log::Error( "Send failed: {}", err );

View File

@@ -8,8 +8,28 @@
#include <string>
#include <array>
#if defined(_WIN32) || defined(WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#ifdef __linux__
#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define WSAEWOULDBLOCK EWOULDBLOCK
#define SOCKADDR sockaddr
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#define closesocket(s) close(s)
#define InetPtonA(inet, ip, service_addr) inet_pton(inet, ip, service_addr)
#define InetNtopA(inet, client_ip, remote_ip, size) \
inet_ntop(inet, client_ip, remote_ip, size)
#define WSASocket(inet, stream, ipproto_tcp, protocol_info, group, flags) \
socket(inet, stream, ipproto_tcp)
#endif
#include "../Common/Constant.h"
#include "../Common/ByteStream.h"
@@ -56,4 +76,4 @@ private:
void ReadSocket( sptr_socket socket );
void WriteSocket( sptr_socket socket );
void HandleRequest( sptr_socket socket, sptr_byte_stream stream );
};
};

View File

@@ -12,5 +12,10 @@ private:
public:
NotifyClientRequestConnect( std::string clientIp, int32_t clientPort );
#ifdef __WIN32
ByteBuffer &Serialize() override;
};
#endif
#ifdef __linux__
virtual ByteBuffer &Serialize() ;
#endif
};

View File

@@ -3,7 +3,16 @@
#include <memory>
#include <vector>
#include <mutex>
#if defined(_WIN32) || defined(WIN32)
#include <winsock2.h>
#endif
#ifdef __linux__
#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close(s)
#endif
#include "GenericNetRequest.h"
#include "GenericNetResponse.h"

View File

@@ -2,6 +2,9 @@
#include <fstream>
#include <string>
#ifdef __linux__
#include <cstdint>
#endif
class Config
{
@@ -12,4 +15,4 @@ public:
static inline uint16_t con_lobby_port;
static inline uint16_t rta_lobby_port;
static inline uint16_t discovery_port;
};
};

View File

@@ -1,4 +1,12 @@
#include "logging.h"
#include <cstdint>
#include <cstdio>
#include <mutex>
#include <string>
#ifdef __linux__
#define localtime_s(date,t) localtime_r(t,date)
#endif
static const char *LOG_PATH[] = {
"./generic",
@@ -24,6 +32,7 @@ const char *Log::GetTimeStamp()
struct tm date_tm;
localtime_s( &date_tm, &t );
#if defined(_WIN32) || defined(WIN32)
_snprintf_s( timestamp, _TRUNCATE, 63,
"[%4d-%02d-%02d %02d:%02d:%02d]: ",
( date_tm.tm_year + 1900 ),
@@ -32,6 +41,17 @@ const char *Log::GetTimeStamp()
date_tm.tm_hour,
date_tm.tm_min,
date_tm.tm_sec );
#endif
#ifdef __linux__
snprintf(timestamp, sizeof(timestamp),
"[%4d-%02d-%02d %02d:%02d:%02d]: ",
date_tm.tm_year + 1900,
date_tm.tm_mon + 1,
date_tm.tm_mday,
date_tm.tm_hour,
date_tm.tm_min,
date_tm.tm_sec);
#endif
return timestamp;
}
@@ -55,17 +75,30 @@ void Log::CheckFileStatus( LOG_TYPE type )
{
char szFileName[ 256 ] = "";
#if defined(_WIN32) || defined(WIN32)
_snprintf_s( szFileName, _TRUNCATE, 255, "./log/%s/log_%04d.%02d.%02d_%02d.log",
LOG_PATH[ type ],
( date_tm.tm_year + 1900 ),
( date_tm.tm_mon + 1 ),
date_tm.tm_mday,
date_tm.tm_hour );
#endif
#ifdef __linux__
snprintf(szFileName, sizeof(szFileName),
"[%4d-%02d-%02d %02d:%02d:%02d]: ",
date_tm.tm_year + 1900,
date_tm.tm_mon + 1,
date_tm.tm_mday,
date_tm.tm_hour,
date_tm.tm_min,
date_tm.tm_sec);
#endif
file_stream[ type ].open( szFileName, std::fstream::out | std::fstream::app );
}
}
#if defined(_WIN32) || defined(WIN32)
void Log::WriteToLog( LOG_TYPE type, const std::string &message )
{
std::lock_guard lock( log_lock );
@@ -185,3 +218,116 @@ void Log::ToFile( std::string prefix, std::vector<uint8_t> p, size_t size )
file.write( reinterpret_cast< const char * >( p.data() ), size );
file.close();
}
#endif
#ifdef __linux__
void Log::WriteToLog( LOG_TYPE type, const std::string &message ){
std::lock_guard lock(log_lock);
std::string log_msg = "";
switch ( type ) {
case log_generic: log_msg+="\033[0;92m[INFO]\033[0m" ; break;
case log_debug: log_msg+="\033[0;96m[DEBUG]\033[0m"; break;
case log_warn: log_msg+="\033[0;95m[WARN]\033[0m" ; break;
case log_error: log_msg+="\033[0;91m[ERROR]\033[0m"; break;
}
printf("%s\033[0;97m%s\033[0m\n",log_msg.c_str(),message.c_str());
file_stream[type] << GetTimeStamp() << message << '\n';
}
void Log::Packet( std::vector<uint8_t> p, size_t size, bool send ){
std::lock_guard<std::mutex> lock( log_lock );
uint16_t i = 0;
uint8_t line[16]={0};
uint8_t r = 0;
std::string color_open = send ? "\033[92m" : "\033[96m";
std::string color_close = "\033[0m";
printf( "(%s)(00|01|02|03|04|05|06|07|08|09|0A|0B|0C|0D|0E|0F)\n", send ? "SEND" : "RECV" );
while( i < size )
{
if( i % 16 == 0 )
{
if( i > 0 )
{
// Print ASCII characters for the previous line
printf( " " );
for( uint8_t j = 0; j < r; ++j )
{
char c = line[ j ];
printf( "%c", ( c >= 0x20 && c <= 0x7E ) ? c : '.' );
}
printf( "\n" );
}
printf( "(%04X) ", i );
r = 0;
}
line[ r++ ] = p[ i ];
// Highlight packet type or flags
if( i == 0 || i == 1 )
{
printf( "%s%02X%s ", color_open.c_str() ,p[ i ], color_close.c_str());
}
else
{
printf( "%02X ", p[ i ] );
}
++i;
}
// Padding for incomplete final line
if( r > 0 )
{
for( uint8_t j = r; j < 16; ++j )
printf( " " ); // Pad to align character section
printf( " " );
for( uint8_t j = 0; j < r; ++j )
{
char c = line[ j ];
printf( "%c", ( c >= 0x20 && c <= 0x7E ) ? c : '.' );
}
}
printf( "\n\n" );
}
void Log::ToFile( std::string prefix, std::vector<uint8_t> p, size_t size ){
static char timestamp[ 64 ] = "";
time_t t; time( &t );
struct tm date_tm;
localtime_s( &date_tm, &t );
int ret = snprintf(timestamp, sizeof(timestamp),
"%02d-%02d-%02d.packet.bin",
date_tm.tm_hour,
date_tm.tm_min,
date_tm.tm_sec);
if (ret < 0) {
// encoding error
}
std::string filename = prefix + '_' + timestamp;
std::fstream file;
file.open( filename, std::ios::out | std::ios::binary );
if( !file.is_open() )
{
Error( "Failed to open packet log file: %s", filename.c_str() );
return;
}
file.write( reinterpret_cast< const char * >( p.data() ), size );
file.close();
}
#endif

View File

@@ -1,12 +1,17 @@
#pragma once
#include <codecvt>
#include <locale>
#include <string>
#include <vector>
#include <fstream>
#include <mutex>
#include <sstream>
#include <type_traits>
#if defined(_WIN32) || defined(WIN32)
#include <windows.h>
#endif
class Log {
private:
@@ -28,10 +33,20 @@ private:
static std::string WideToMulti( const std::wstring &input )
{
if( input.empty() ) return "";
if( input.empty() ) return "";
std::string result;
#if defined(_WIN32) || defined(WIN32)
int sizeNeeded = WideCharToMultiByte( CP_UTF8, 0, input.data(), ( int )input.size(), nullptr, 0, nullptr, nullptr );
std::string result( sizeNeeded, 0 );
WideCharToMultiByte( CP_UTF8, 0, input.data(), ( int )input.size(), std::data( result ), sizeNeeded, nullptr, nullptr );
#endif
#if __linux__
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
result = conv.to_bytes(input);
#endif
return result;
}

View File

@@ -1,8 +1,14 @@
#if defined(_WIN32) || defined(WIN32)
#include "stdafx.h"
#include <winsock2.h>
#endif
#ifdef __linux__
#include <sys/socket.h>
#endif
#include <atomic>
#include <csignal>
#include <winsock2.h>
#include "logging.h"
#include "configuration.h"
@@ -33,6 +39,7 @@ static void ShowStartup()
static bool NetworkStartup()
{
#ifdef __WIN32__
WORD wVersionRequest = MAKEWORD( 2, 2 );
WSADATA wsaData;
@@ -41,6 +48,7 @@ static bool NetworkStartup()
Log::Error( "WSAStartup() failed" );
return false;
}
#endif
return true;
}

View File

@@ -8,7 +8,9 @@
#include "targetver.h"
#include <stdio.h>
#if defined (_WIN32) || defined (WIN32)
#include <tchar.h>
#endif

View File

@@ -5,4 +5,6 @@
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#if defined (_WIN32) || defined (WIN32)
#include <SDKDDKVer.h>
#endif